<commit_before>/*
 *   Copyright (C) 2011 Ivan Cukic <ivan.cukic(at)kde.org>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License version 2,
 *   or (at your option) any later version, as published by the Free
 *   Software Foundation
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details
 *
 *   You should have received a copy of the GNU General Public
 *   License along with this program; if not, write to the
 *   Free Software Foundation, Inc.,
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include "Documents.h"
#include "Documents_p.h"
#include "rankingsclientadaptor.h"

#include <QList>
#include <QDBusConnection>
#include <QDesktopServices>

#include <Nepomuk/Resource>
#include <Nepomuk/Variant>

#include <KDebug>
#include <KUrl>
#include <KFileItem>

#include "nfo.h"
#include "nie.h"
#include "kext.h"

#define KAMD_DBUS_ADDRESS "org.kde.kactivitymanagerd"

using namespace Nepomuk::Vocabulary;

// Private

DocumentsEnginePrivate::DocumentsEnginePrivate(DocumentsEngine * parent)
    : q(parent)
{
    activitymanager = new KActivities::Consumer(this);

    QDBusConnection dbus = QDBusConnection::sessionBus();

    // Making us visible on d-bus
    new RankingsClientAdaptor(this);
    // kDebug() << "registering the client" <<
    dbus.registerObject("/RankingsClient", this);

    if (dbus.interface()->isServiceRegistered(KAMD_DBUS_ADDRESS)) {
        serviceOnline();
    }

    QDBusServiceWatcher * watcher = new QDBusServiceWatcher(
            KAMD_DBUS_ADDRESS, dbus,
            QDBusServiceWatcher::WatchForRegistration | QDBusServiceWatcher::WatchForUnregistration,
            this
        );
    connect(watcher, SIGNAL(serviceRegistered(QString)),
            this, SLOT(serviceOnline()));
    connect(watcher, SIGNAL(serviceUnregistered(QString)),
            this, SLOT(serviceOffline()));
}

void DocumentsEnginePrivate::serviceOnline()
{
    kDebug() << KAMD_DBUS_ADDRESS << "went online";

    QDBusInterface rankingsservice(KAMD_DBUS_ADDRESS,
            "/Rankings", "org.kde.ActivityManager.Rankings");

    rankingsservice.asyncCall("registerClient", "org.kde.Contour", QString(), "nao:Document");
}

void DocumentsEnginePrivate::serviceOffline()
{
    kDebug() << KAMD_DBUS_ADDRESS << "went offline";

    q->recommendationsUpdated(QList<Contour::RecommendationItem>());
}

DocumentsEnginePrivate::~DocumentsEnginePrivate()
{
}

void DocumentsEnginePrivate::updated(const QVariantList & data)
{
    kDebug() << "@@@@@@@@@@@@@@@@@@" << data;
    recommendations.clear();

    double score = 1.0;

    foreach (const QVariant & item, data) {
        Nepomuk::Resource resource(KUrl(item.toString()));

        // The problem is when the resource has no particular type set (web page)
        // if (!resource.hasType(Nepomuk::Vocabulary::NFO::FileDataObject())) continue;

        Nepomuk::Resource currentActivityResource(activitymanager->currentActivity(), KEXT::Activity());

        // TODO: See ActivityManager.coo
        // I'd like a resource isRelated activity more than vice-versa
        // but the active models are checking for the other way round.
        // It is defined in the ontologies as a symmetric relation, but
        // Nepomuk doesn't care about that.

        // if (resource.isRelateds().contains(currentActivityResource)) continue;
        if (currentActivityResource.isRelateds().contains(resource)) continue;

        Contour::RecommendationItem recommendation;

        recommendation.score       = score;
        recommendation.id          = item.toString();

        if (recommendation.id.startsWith("nepomuk:")) {
            if (!resource.hasProperty(NIE::url()))
                continue;

            recommendation.id = resource.property(NIE::url()).toString();
        }

        score /= 2;

        recommendation.title       = resource.genericLabel();
        recommendation.description = i18n("Open and add to the current activity");
        recommendation.icon        = resource.genericIcon();

        if (recommendation.icon.isEmpty()) {
            KFileItem fileItem(KFileItem::Unknown, KFileItem::Unknown,
                    KUrl(recommendation.id));
            recommendation.icon = fileItem.iconName();
        }

        kDebug()
            << "score:" << recommendation.score
            << "id:" << recommendation.id
            << "title:" << recommendation.title
            << "description:" << recommendation.description
            ;

        recommendations << recommendation;

        if (recommendations.size() >= 10) break;

    }

    q->recommendationsUpdated(recommendations);

}

void DocumentsEnginePrivate::removeRecommendation(const QString & id)
{
    // kDebug() << "removing" << id;

    for (int i = 0; i < recommendations.size(); i++) {
        if (recommendations[i].id == id) {
            // kDebug() << "before removal:" << recommendations;
            recommendations.removeAt(i);
            // kDebug() << "after removal:" << recommendations;
            break;
        }
    }
}

void DocumentsEnginePrivate::inserted(int position, const QVariantList & item)
{
}

void DocumentsEnginePrivate::removed(int position)
{
}

void DocumentsEnginePrivate::changed(int position, const QVariantList & item)
{
}

// DocumentsEngine

DocumentsEngine::DocumentsEngine(QObject * parent, const QVariantList & args)
    : Contour::RecommendationEngine(parent), d(new DocumentsEnginePrivate(this))
{
}

DocumentsEngine::~DocumentsEngine()
{
    delete d;
}

void DocumentsEngine::init()
{
    Contour::RecommendationEngine::init();

    emit recommendationsUpdated(d->recommendations);
}

void DocumentsEngine::activate(const QString & id, const QString & action)
{
    KUrl url(id);

    d->removeRecommendation(id);

    // I *really* don't like this - handling http stuff as bookmarks, no matter
    // what they are...
    if (id.startsWith("http")) {
        // Evil handling of the resources - making bookmarks

        Nepomuk::Resource bookmark(url);
        QList <QUrl> types;
        types << NFO::Bookmark();

        bookmark.setTypes(types);

    }

    // Proper handling of the resources
    d->activitymanager->linkResourceToActivity(url);

    QDesktopServices::openUrl(url);

    recommendationsUpdated(d->recommendations);
}

RECOMMENDATION_EXPORT_PLUGIN(DocumentsEngine, "contour_recommendationengine_documents")

<commit_msg>temporary revert of last commit<commit_after>/*
 *   Copyright (C) 2011 Ivan Cukic <ivan.cukic(at)kde.org>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License version 2,
 *   or (at your option) any later version, as published by the Free
 *   Software Foundation
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details
 *
 *   You should have received a copy of the GNU General Public
 *   License along with this program; if not, write to the
 *   Free Software Foundation, Inc.,
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include "Documents.h"
#include "Documents_p.h"
#include "rankingsclientadaptor.h"

#include <QList>
#include <QDBusConnection>
#include <QDesktopServices>

#include <Nepomuk/Resource>
#include <Nepomuk/Variant>

#include <KDebug>
#include <KUrl>
#include <KFileItem>

#include "nfo.h"
#include "nie.h"
#include "kext.h"

#define KAMD_DBUS_ADDRESS "org.kde.kactivitymanagerd"

using namespace Nepomuk::Vocabulary;

// Private

DocumentsEnginePrivate::DocumentsEnginePrivate(DocumentsEngine * parent)
    : q(parent)
{
    activitymanager = new KActivities::Consumer(this);

    QDBusConnection dbus = QDBusConnection::sessionBus();

    // Making us visible on d-bus
    new RankingsClientAdaptor(this);
    // kDebug() << "registering the client" <<
    dbus.registerObject("/RankingsClient", this);

    if (dbus.interface()->isServiceRegistered(KAMD_DBUS_ADDRESS)) {
        serviceOnline();
    }

    QDBusServiceWatcher * watcher = new QDBusServiceWatcher(
            KAMD_DBUS_ADDRESS, dbus,
            QDBusServiceWatcher::WatchForRegistration | QDBusServiceWatcher::WatchForUnregistration,
            this
        );
    connect(watcher, SIGNAL(serviceRegistered(QString)),
            this, SLOT(serviceOnline()));
    connect(watcher, SIGNAL(serviceUnregistered(QString)),
            this, SLOT(serviceOffline()));
}

void DocumentsEnginePrivate::serviceOnline()
{
    kDebug() << KAMD_DBUS_ADDRESS << "went online";

    QDBusInterface rankingsservice(KAMD_DBUS_ADDRESS,
            "/Rankings", "org.kde.ActivityManager.Rankings");

    rankingsservice.asyncCall("registerClient", "org.kde.Contour", QString(), "nao:Document");
}

void DocumentsEnginePrivate::serviceOffline()
{
    kDebug() << KAMD_DBUS_ADDRESS << "went offline";

    q->recommendationsUpdated(QList<Contour::RecommendationItem>());
}

DocumentsEnginePrivate::~DocumentsEnginePrivate()
{
}

void DocumentsEnginePrivate::updated(const QVariantList & data)
{
    kDebug() << "@@@@@@@@@@@@@@@@@@" << data;
    recommendations.clear();

    double score = 1.0;

    foreach (const QVariant & item, data) {
        Nepomuk::Resource resource(KUrl(item.toString()));

        // The problem is when the resource has no particular type set (web page)
        // if (!resource.hasType(Nepomuk::Vocabulary::NFO::FileDataObject())) continue;

        Nepomuk::Resource currentActivityResource(activitymanager->currentActivity(), KEXT::Activity());

        // TODO: See ActivityManager.coo
        // I'd like a resource isRelated activity more than vice-versa
        // but the active models are checking for the other way round.
        // It is defined in the ontologies as a symmetric relation, but
        // Nepomuk doesn't care about that.

        // if (resource.isRelateds().contains(currentActivityResource)) continue;
        if (currentActivityResource.isRelateds().contains(resource)) continue;

        Contour::RecommendationItem recommendation;

        recommendation.score       = score;
        recommendation.id          = item.toString();

        if (recommendation.id.startsWith("nepomuk:")) {
            if (!resource.hasProperty(NIE::url()))
                continue;

            recommendation.id = resource.property(NIE::url()).toString();
        }

        score /= 2;

        recommendation.title       = resource.genericLabel();
        recommendation.description = i18n("Open and add to the current activity");
        recommendation.icon        = resource.genericIcon();

        if (recommendation.icon.isEmpty()) {
            KFileItem fileItem(KFileItem::Unknown, KFileItem::Unknown,
                    KUrl(recommendation.id));
            recommendation.icon = fileItem.iconName();
        }

        kDebug()
            << "score:" << recommendation.score
            << "id:" << recommendation.id
            << "title:" << recommendation.title
            << "description:" << recommendation.description
            ;

        recommendations << recommendation;

        if (recommendations.size() >= 10) break;

    }

    q->recommendationsUpdated(recommendations);

}

void DocumentsEnginePrivate::removeRecommendation(const QString & id)
{
    // kDebug() << "removing" << id;

    for (int i = 0; i < recommendations.size(); i++) {
        if (recommendations[i].id == id) {
            // kDebug() << "before removal:" << recommendations;
            recommendations.removeAt(i);
            // kDebug() << "after removal:" << recommendations;
            break;
        }
    }
}

void DocumentsEnginePrivate::inserted(int position, const QVariantList & item)
{
}

void DocumentsEnginePrivate::removed(int position)
{
}

void DocumentsEnginePrivate::changed(int position, const QVariantList & item)
{
}

// DocumentsEngine

DocumentsEngine::DocumentsEngine(QObject * parent, const QVariantList & args)
    : Contour::RecommendationEngine(parent), d(new DocumentsEnginePrivate(this))
{
}

DocumentsEngine::~DocumentsEngine()
{
    delete d;
}

void DocumentsEngine::init()
{
    Contour::RecommendationEngine::init();

    emit recommendationsUpdated(d->recommendations);
}

void DocumentsEngine::activate(const QString & id, const QString & action)
{
    KUrl url(id);

    d->removeRecommendation(id);
/*
    // I *really* don't like this - handling http stuff as bookmarks, no matter
    // what they are...
    if (id.startsWith("http")) {
        // Evil handling of the resources - making bookmarks

        Nepomuk::Resource bookmark(url);
        QList <QUrl> types;
        types << NFO::Bookmark();

        bookmark.setTypes(types);

    }
*/
    // Proper handling of the resources
    d->activitymanager->linkResourceToActivity(url);

    QDesktopServices::openUrl(url);

    recommendationsUpdated(d->recommendations);
}

RECOMMENDATION_EXPORT_PLUGIN(DocumentsEngine, "contour_recommendationengine_documents")

<|endoftext|>


<commit_before>/*
 *   Copyright (C) 2011 Ivan Cukic <ivan.cukic(at)kde.org>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License version 2,
 *   or (at your option) any later version, as published by the Free
 *   Software Foundation
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details
 *
 *   You should have received a copy of the GNU General Public
 *   License along with this program; if not, write to the
 *   Free Software Foundation, Inc.,
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include "Documents.h"
#include "Documents_p.h"
#include "rankingsclientadaptor.h"

#include <QList>
#include <QDBusConnection>
#include <QDesktopServices>

#include <Nepomuk/Resource>
#include <Nepomuk/Variant>

#include <KDebug>
#include <KUrl>
#include <KFileItem>

#include "nfo.h"
#include "nie.h"

// Private

DocumentsEnginePrivate::DocumentsEnginePrivate(DocumentsEngine * parent)
    : q(parent)
{
    QDBusConnection dbus = QDBusConnection::sessionBus();
    new RankingsClientAdaptor(this);
    kDebug() << "registering the client" <<
    dbus.registerObject("/RankingsClient", this);

    QDBusInterface rankingsservice("org.kde.kactivitymanagerd",
            "/Rankings", "org.kde.ActivityManager.Rankings");

    kDebug() << "calling registerClient" <<
    rankingsservice.call("registerClient", "org.kde.Contour", QString(), "nao:Document");
}

DocumentsEnginePrivate::~DocumentsEnginePrivate()
{
}

void DocumentsEnginePrivate::updated(const QVariantList & data)
{
    kDebug() << "@@@@@@@@@@@@@@@@@@" << data;
    recommendations.clear();

    double score = 1.0;

    foreach (const QVariant & item, data) {
        Nepomuk::Resource resource(KUrl(item.toString()));

        if (!resource.hasType(Nepomuk::Vocabulary::NFO::FileDataObject())) continue;

        Contour::RecommendationItem recommendation;

        recommendation.score       = score;
        recommendation.id          = item.toString();
        score /= 2;

        recommendation.title       = resource.genericLabel();
        recommendation.description = i18n("Open in the current activity");
        recommendation.icon        = resource.genericIcon();

        if (recommendation.icon.isEmpty()) {
            KFileItem fileItem(KFileItem::Unknown, KFileItem::Unknown,
                    KUrl(resource.property(Nepomuk::Vocabulary::NIE::url()).toString()));
            recommendation.icon = fileItem.iconName();
        }

        kDebug() << recommendation;

        recommendations << recommendation;

        if (recommendations.size() >= 3) break;

    }

    q->recommendationsUpdated(recommendations);

}

void DocumentsEnginePrivate::inserted(int position, const QVariantList & item)
{
}

void DocumentsEnginePrivate::removed(int position)
{
}

void DocumentsEnginePrivate::changed(int position, const QVariantList & item)
{
}

// DocumentsEngine

DocumentsEngine::DocumentsEngine(QObject * parent, const QVariantList & args)
    : Contour::RecommendationEngine(parent), d(new DocumentsEnginePrivate(this))
{
}

DocumentsEngine::~DocumentsEngine()
{
    delete d;
}

void DocumentsEngine::init()
{
    kDebug() << "We are going to work";

    Contour::RecommendationItem recommendation;

    recommendation.score       = 1.0;
    recommendation.title       = "Not implemented yet";
    recommendation.description = "Stay tuned";
    recommendation.icon        = "preferences-activities";
    recommendation.id          = "null";

    d->recommendations << recommendation;

    emit recommendationsUpdated(d->recommendations);
}

void DocumentsEngine::activate(const QString & id, const QString & action)
{
    QDesktopServices::openUrl(KUrl(id));

}

RECOMMENDATION_EXPORT_PLUGIN(DocumentsEngine, "contour_recommendationengine_documents")

<commit_msg>Added TODO<commit_after>/*
 *   Copyright (C) 2011 Ivan Cukic <ivan.cukic(at)kde.org>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License version 2,
 *   or (at your option) any later version, as published by the Free
 *   Software Foundation
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details
 *
 *   You should have received a copy of the GNU General Public
 *   License along with this program; if not, write to the
 *   Free Software Foundation, Inc.,
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include "Documents.h"
#include "Documents_p.h"
#include "rankingsclientadaptor.h"

#include <QList>
#include <QDBusConnection>
#include <QDesktopServices>

#include <Nepomuk/Resource>
#include <Nepomuk/Variant>

#include <KDebug>
#include <KUrl>
#include <KFileItem>

#include "nfo.h"
#include "nie.h"

// Private

DocumentsEnginePrivate::DocumentsEnginePrivate(DocumentsEngine * parent)
    : q(parent)
{
    QDBusConnection dbus = QDBusConnection::sessionBus();
    new RankingsClientAdaptor(this);
    kDebug() << "registering the client" <<
    dbus.registerObject("/RankingsClient", this);

    QDBusInterface rankingsservice("org.kde.kactivitymanagerd",
            "/Rankings", "org.kde.ActivityManager.Rankings");

    kDebug() << "calling registerClient" <<
    rankingsservice.call("registerClient", "org.kde.Contour", QString(), "nao:Document");
}

DocumentsEnginePrivate::~DocumentsEnginePrivate()
{
}

void DocumentsEnginePrivate::updated(const QVariantList & data)
{
    kDebug() << "@@@@@@@@@@@@@@@@@@" << data;
    recommendations.clear();

    double score = 1.0;

    foreach (const QVariant & item, data) {
        Nepomuk::Resource resource(KUrl(item.toString()));

        if (!resource.hasType(Nepomuk::Vocabulary::NFO::FileDataObject())) continue;

        Contour::RecommendationItem recommendation;

        recommendation.score       = score;
        recommendation.id          = item.toString();
        score /= 2;

        recommendation.title       = resource.genericLabel();
        recommendation.description = i18n("Open in the current activity");
        recommendation.icon        = resource.genericIcon();

        if (recommendation.icon.isEmpty()) {
            KFileItem fileItem(KFileItem::Unknown, KFileItem::Unknown,
                    KUrl(resource.property(Nepomuk::Vocabulary::NIE::url()).toString()));
            recommendation.icon = fileItem.iconName();
        }

        kDebug() << recommendation;

        recommendations << recommendation;

        if (recommendations.size() >= 3) break;

    }

    q->recommendationsUpdated(recommendations);

}

void DocumentsEnginePrivate::inserted(int position, const QVariantList & item)
{
}

void DocumentsEnginePrivate::removed(int position)
{
}

void DocumentsEnginePrivate::changed(int position, const QVariantList & item)
{
}

// DocumentsEngine

DocumentsEngine::DocumentsEngine(QObject * parent, const QVariantList & args)
    : Contour::RecommendationEngine(parent), d(new DocumentsEnginePrivate(this))
{
}

DocumentsEngine::~DocumentsEngine()
{
    delete d;
}

void DocumentsEngine::init()
{
    kDebug() << "We are going to work";

    Contour::RecommendationItem recommendation;

    recommendation.score       = 1.0;
    recommendation.title       = "Not implemented yet";
    recommendation.description = "Stay tuned";
    recommendation.icon        = "preferences-activities";
    recommendation.id          = "null";

    d->recommendations << recommendation;

    emit recommendationsUpdated(d->recommendations);
}

void DocumentsEngine::activate(const QString & id, const QString & action)
{
    // TODO: Add isRelated url -> activity

    QDesktopServices::openUrl(url);

}

RECOMMENDATION_EXPORT_PLUGIN(DocumentsEngine, "contour_recommendationengine_documents")

<|endoftext|>


<commit_before>
#include "Beetle.h"

#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
#include <boost/program_options.hpp>
#include <boost/thread/lock_types.hpp>
#include <boost/thread/pthread/shared_mutex.hpp>
#include <cassert>
#include <iostream>
#include <thread>
#include <utility>
#include <cstdint>

#include "AutoConnect.h"
#include "CLI.h"
#include "device/BeetleMetaDevice.h"
#include "Debug.h"
#include "Device.h"
#include "hat/BlockAllocator.h"
#include "hat/HandleAllocationTable.h"
#include "Router.h"
#include "Scanner.h"
#include "tcp/TCPDeviceServer.h"

/* Global debug variables */
bool debug = true;				// Debug.h
bool debug_scan = false;		// Scan.h
bool debug_discovery = false;	// VirtualDevice.h
bool debug_router = false;		// Router.h
bool debug_socket = false;		// Debug.h

void resetHciHelper() {
	assert(system(NULL) != 0);
	int hciDevice = hci_get_route(NULL);
	assert(hciDevice >= 0);
	std::string hciName = "hci" + std::to_string(hciDevice);
	std::string command = "hciconfig " + hciName + " down";
	pdebug("running: " + command);
	assert(system(command.c_str()) == 0);
	command = "hciconfig " + hciName + " up";
	pdebug("running: " + command);
	assert(system(command.c_str()) == 0);
}

std::string getDefaultName() {
	char name[100];
	assert(gethostname(name, sizeof(name)) == 0);
	return "beetle@" + std::string(name);
}

int main(int argc, char *argv[]) {
	int tcpPort = 5000;
	bool scanningEnabled = true;
	bool debugAll = false;
	bool autoConnectAll = false;
	bool resetHci = true;
	std::string name = "";

	namespace po = boost::program_options;
	po::options_description desc("Options");
	desc.add_options()
			("help,h", "")
			("name,n", po::value<std::string>(&name),
					"Name this Beetle gateway (default: Beetle)")
			("scan,s", po::value<bool>(&scanningEnabled),
					"Enable scanning for BLE devices (default: true")
			("tcp-port,p", po::value<int>(&tcpPort),
					"Specify remote TCP server port (default: 5000)")
			("debug,d", po::value<bool>(&debug),
					"Enable general debugging (default: true)")
			("auto-connect-all", po::value<bool>(&autoConnectAll),
					"Connect to all nearby BLE devices (default: false")
			("reset-hci", po::value<bool>(&resetHci),
					"Set hci down/up at start-up (default: true")
			("debug-discovery", po::value<bool>(&debug_discovery),
					"Enable debugging for GATT discovery (default: false)")
			("debug-scan", po::value<bool>(&debug_scan),
					"Enable debugging for BLE scanning (default: false)")
			("debug-socket", po::value<bool>(&debug_socket),
					"Enable debugging for sockets (default: false)")
			("debug-router", po::value<bool>(&debug_router),
					"Enable debugging for router (default: false)")
			("debug-all", po::value<bool>(&debugAll),
					"Enable ALL debugging (default: false)");
	po::variables_map vm;
	try {
		po::store(po::parse_command_line(argc, argv, desc), vm);
		if (vm.count("help")) {
			std::cout << "Beetle Linux" << std::endl << desc << std::endl;
			return 0;
		}
		po::notify(vm);
	} catch(po::error& e) {
		std::cerr << "ERROR: " << e.what() << std::endl << std::endl;
		std::cerr << desc << std::endl;
		return 1;
	}

	if (debugAll) {
		debug = true;
		debug_scan = true;
		debug_router = true;
		debug_socket = true;
		debug_discovery = true;
	}

	if (resetHci) resetHciHelper();
	if (name == "") {
		name = getDefaultName();
	}

	try {
		Beetle btl(name);
		TCPDeviceServer tcpServer(btl, tcpPort);
		AutoConnect autoConnect(btl, autoConnectAll);
		CLI cli(btl);

		Scanner scanner;
		scanner.registerHandler(cli.getDiscoveryHander());
		scanner.registerHandler(autoConnect.getDiscoveryHandler());

		if (scanningEnabled) {
			scanner.start();
		}

		cli.join();
	} catch(std::exception& e) {
		std::cerr << "Unhandled Exception reached the top of main: "
				<< e.what() << ", application will now exit" << std::endl;
		return 2;
	}
	return 0;
}

Beetle::Beetle(std::string name_) {
	router = new Router(*this);
	beetleDevice = new BeetleMetaDevice(*this, name_);
	devices[BEETLE_RESERVED_DEVICE] = beetleDevice;
	name = name_;
}

Beetle::~Beetle() {

}

void Beetle::addDevice(Device *d) {
	boost::unique_lock<boost::shared_mutex> deviceslk(devicesMutex);
	devices[d->getId()] = d;
}

void Beetle::removeDevice(device_t id) {
	if (id == BEETLE_RESERVED_DEVICE) {
		pwarn("not allowed to remove Beetle!");
		return;
	}
	boost::unique_lock<boost::shared_mutex> lk(devicesMutex);
	Device *d = devices[id];
	devices.erase(id);

	for (auto &kv : devices) {
		/*
		 * Cancel subscriptions and inform that services have changed
		 */
		assert(kv.first != id);
		kv.second->unsubscribeAll(id);
		if (!kv.second->hat->getDeviceRange(id).isNull()) {
			beetleDevice->informServicesChanged(kv.second->hat->free(id), kv.first);
		}
	}

	/*
	 * Spin deallocator thread to avoid blocking
	 */
	std::thread t([d]() { delete d; });
	t.detach();
}

void Beetle::mapDevices(device_t from, device_t to) {
	if (from == BEETLE_RESERVED_DEVICE || to == BEETLE_RESERVED_DEVICE) {
		pwarn("not allowed to map Beetle");
	} else if (from == NULL_RESERVED_DEVICE || to == NULL_RESERVED_DEVICE) {
		pwarn("not allowed to map null device");
	} else if (from == to) {
		pwarn("cannot map device to itself");
	} else {
		boost::shared_lock<boost::shared_mutex> devicesLk(devicesMutex);
		if (devices.find(from) == devices.end()) {
			pwarn(std::to_string(from) + " does not id a device");
		} else if (devices.find(to) == devices.end()) {
			pwarn(std::to_string(to) +" does not id a device");
		} else {
			Device *toD = devices[to];

			std::lock_guard<std::mutex> hatLg(toD->hatMutex);
			if (!toD->hat->getDeviceRange(from).isNull()) {
				std::stringstream ss;
				ss << from << " is already mapped into " << to << "'s space";
				pwarn(ss.str());
			} else {
				handle_range_t range = toD->hat->reserve(from);
				if (debug) {
					pdebug("reserved " + range.str() + " at device " + std::to_string(to));
				}
			}
		}
	}
}

void Beetle::unmapDevices(device_t from, device_t to) {
	if (from == BEETLE_RESERVED_DEVICE || to == BEETLE_RESERVED_DEVICE) {
		pwarn("not allowed to unmap Beetle");
	} else if (from == NULL_RESERVED_DEVICE || to == NULL_RESERVED_DEVICE) {
		pwarn("unmapping null is a nop");
	} else if (from == to) {
		pwarn("cannot unmap self from self");
	} else {
		if (devices.find(from) == devices.end()) {
			pwarn(std::to_string(from) + " does not id a device");
		} else if (devices.find(to) == devices.end()) {
			pwarn(std::to_string(to) +" does not id a device");
		} else {
			Device *toD = devices[to];

			std::lock_guard<std::mutex> hatLg(toD->hatMutex);
			handle_range_t range = toD->hat->free(from);
			if (debug) {
				pdebug("freed " + range.str() + " at device " + std::to_string(to));
			}
		}
	}
}

<commit_msg>Fix typo.<commit_after>
#include "Beetle.h"

#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
#include <boost/program_options.hpp>
#include <boost/thread/lock_types.hpp>
#include <boost/thread/pthread/shared_mutex.hpp>
#include <cassert>
#include <iostream>
#include <thread>
#include <utility>
#include <cstdint>

#include "AutoConnect.h"
#include "CLI.h"
#include "device/BeetleMetaDevice.h"
#include "Debug.h"
#include "Device.h"
#include "hat/BlockAllocator.h"
#include "hat/HandleAllocationTable.h"
#include "Router.h"
#include "Scanner.h"
#include "tcp/TCPDeviceServer.h"

/* Global debug variables */
bool debug = true;				// Debug.h
bool debug_scan = false;		// Scan.h
bool debug_discovery = false;	// VirtualDevice.h
bool debug_router = false;		// Router.h
bool debug_socket = false;		// Debug.h

void resetHciHelper() {
	assert(system(NULL) != 0);
	int hciDevice = hci_get_route(NULL);
	assert(hciDevice >= 0);
	std::string hciName = "hci" + std::to_string(hciDevice);
	std::string command = "hciconfig " + hciName + " down";
	pdebug("running: " + command);
	assert(system(command.c_str()) == 0);
	command = "hciconfig " + hciName + " up";
	pdebug("running: " + command);
	assert(system(command.c_str()) == 0);
}

std::string getDefaultName() {
	char name[100];
	assert(gethostname(name, sizeof(name)) == 0);
	return "beetle@" + std::string(name);
}

int main(int argc, char *argv[]) {
	int tcpPort = 5000;
	bool scanningEnabled = true;
	bool debugAll = false;
	bool autoConnectAll = false;
	bool resetHci = true;
	std::string name = "";

	namespace po = boost::program_options;
	po::options_description desc("Options");
	desc.add_options()
			("help,h", "")
			("name,n", po::value<std::string>(&name),
					"Name this Beetle gateway (default: beetle@hostname)")
			("scan,s", po::value<bool>(&scanningEnabled),
					"Enable scanning for BLE devices (default: true")
			("tcp-port,p", po::value<int>(&tcpPort),
					"Specify remote TCP server port (default: 5000)")
			("debug,d", po::value<bool>(&debug),
					"Enable general debugging (default: true)")
			("auto-connect-all", po::value<bool>(&autoConnectAll),
					"Connect to all nearby BLE devices (default: false")
			("reset-hci", po::value<bool>(&resetHci),
					"Set hci down/up at start-up (default: true")
			("debug-discovery", po::value<bool>(&debug_discovery),
					"Enable debugging for GATT discovery (default: false)")
			("debug-scan", po::value<bool>(&debug_scan),
					"Enable debugging for BLE scanning (default: false)")
			("debug-socket", po::value<bool>(&debug_socket),
					"Enable debugging for sockets (default: false)")
			("debug-router", po::value<bool>(&debug_router),
					"Enable debugging for router (default: false)")
			("debug-all", po::value<bool>(&debugAll),
					"Enable ALL debugging (default: false)");
	po::variables_map vm;
	try {
		po::store(po::parse_command_line(argc, argv, desc), vm);
		if (vm.count("help")) {
			std::cout << "Beetle Linux" << std::endl << desc << std::endl;
			return 0;
		}
		po::notify(vm);
	} catch(po::error& e) {
		std::cerr << "ERROR: " << e.what() << std::endl << std::endl;
		std::cerr << desc << std::endl;
		return 1;
	}

	if (debugAll) {
		debug = true;
		debug_scan = true;
		debug_router = true;
		debug_socket = true;
		debug_discovery = true;
	}

	if (resetHci) resetHciHelper();
	if (name == "") {
		name = getDefaultName();
	}

	try {
		Beetle btl(name);
		TCPDeviceServer tcpServer(btl, tcpPort);
		AutoConnect autoConnect(btl, autoConnectAll);
		CLI cli(btl);

		Scanner scanner;
		scanner.registerHandler(cli.getDiscoveryHander());
		scanner.registerHandler(autoConnect.getDiscoveryHandler());

		if (scanningEnabled) {
			scanner.start();
		}

		cli.join();
	} catch(std::exception& e) {
		std::cerr << "Unhandled Exception reached the top of main: "
				<< e.what() << ", application will now exit" << std::endl;
		return 2;
	}
	return 0;
}

Beetle::Beetle(std::string name_) {
	router = new Router(*this);
	beetleDevice = new BeetleMetaDevice(*this, name_);
	devices[BEETLE_RESERVED_DEVICE] = beetleDevice;
	name = name_;
}

Beetle::~Beetle() {

}

void Beetle::addDevice(Device *d) {
	boost::unique_lock<boost::shared_mutex> deviceslk(devicesMutex);
	devices[d->getId()] = d;
}

void Beetle::removeDevice(device_t id) {
	if (id == BEETLE_RESERVED_DEVICE) {
		pwarn("not allowed to remove Beetle!");
		return;
	}
	boost::unique_lock<boost::shared_mutex> lk(devicesMutex);
	Device *d = devices[id];
	devices.erase(id);

	for (auto &kv : devices) {
		/*
		 * Cancel subscriptions and inform that services have changed
		 */
		assert(kv.first != id);
		kv.second->unsubscribeAll(id);
		if (!kv.second->hat->getDeviceRange(id).isNull()) {
			beetleDevice->informServicesChanged(kv.second->hat->free(id), kv.first);
		}
	}

	/*
	 * Spin deallocator thread to avoid blocking
	 */
	std::thread t([d]() { delete d; });
	t.detach();
}

void Beetle::mapDevices(device_t from, device_t to) {
	if (from == BEETLE_RESERVED_DEVICE || to == BEETLE_RESERVED_DEVICE) {
		pwarn("not allowed to map Beetle");
	} else if (from == NULL_RESERVED_DEVICE || to == NULL_RESERVED_DEVICE) {
		pwarn("not allowed to map null device");
	} else if (from == to) {
		pwarn("cannot map device to itself");
	} else {
		boost::shared_lock<boost::shared_mutex> devicesLk(devicesMutex);
		if (devices.find(from) == devices.end()) {
			pwarn(std::to_string(from) + " does not id a device");
		} else if (devices.find(to) == devices.end()) {
			pwarn(std::to_string(to) +" does not id a device");
		} else {
			Device *toD = devices[to];

			std::lock_guard<std::mutex> hatLg(toD->hatMutex);
			if (!toD->hat->getDeviceRange(from).isNull()) {
				std::stringstream ss;
				ss << from << " is already mapped into " << to << "'s space";
				pwarn(ss.str());
			} else {
				handle_range_t range = toD->hat->reserve(from);
				if (debug) {
					pdebug("reserved " + range.str() + " at device " + std::to_string(to));
				}
			}
		}
	}
}

void Beetle::unmapDevices(device_t from, device_t to) {
	if (from == BEETLE_RESERVED_DEVICE || to == BEETLE_RESERVED_DEVICE) {
		pwarn("not allowed to unmap Beetle");
	} else if (from == NULL_RESERVED_DEVICE || to == NULL_RESERVED_DEVICE) {
		pwarn("unmapping null is a nop");
	} else if (from == to) {
		pwarn("cannot unmap self from self");
	} else {
		if (devices.find(from) == devices.end()) {
			pwarn(std::to_string(from) + " does not id a device");
		} else if (devices.find(to) == devices.end()) {
			pwarn(std::to_string(to) +" does not id a device");
		} else {
			Device *toD = devices[to];

			std::lock_guard<std::mutex> hatLg(toD->hatMutex);
			handle_range_t range = toD->hat->free(from);
			if (debug) {
				pdebug("freed " + range.str() + " at device " + std::to_string(to));
			}
		}
	}
}

<|endoftext|>


<commit_before>#include "ctc.h"
#include "logger.h"

PrefixTree::Node::Node() :
  inTok (0),
  parent (NULL),
  nStates (0),
  outLen (0)
{ }

PrefixTree::Node::Node (const PrefixTree& tree, const Node* parent, InputToken inTok) :
  inTok (inTok),
  parent (parent),
  nStates (tree.nStates),
  outLen (tree.outLen)
{ }

void PrefixTree::Node::fill (const PrefixTree& tree)
{
  cellStorage = vector<double> (nCells(), -numeric_limits<double>::infinity());
  logPrefixProb = -numeric_limits<double>::infinity();

  if (!parent)
    seqCell (0, 0) = 0;

  for (OutputIndex outPos = 0; outPos <= outLen; ++outPos) {
    const OutputToken outTok = outPos ? tree.output[outPos-1] : OutputTokenizer::emptyToken();
    for (StateIndex d = 0; d < nStates; ++d) {
      LogThisAt(9,"d="<<d<<": ");
      const EvaluatedMachineState& state = tree.machine.state[d];
      double& ll = seqCell (outPos, d);
      if (parent && state.incoming.count (inTok)) {
	const auto& incoming = state.incoming.at (inTok);
	if (outPos)
	  accumulateSeqCell (ll, incoming, *parent, outTok, outPos - 1);
	accumulateSeqCell (ll, incoming, *parent, OutputTokenizer::emptyToken(), outPos);
      }
      if (state.incoming.count (InputTokenizer::emptyToken())) {
	const auto& incoming = state.incoming.at (InputTokenizer::emptyToken());
	if (outPos)
	  accumulateSeqCell (ll, incoming, *this, outTok, outPos - 1);
	accumulateSeqCell (ll, incoming, *this, OutputTokenizer::emptyToken(), outPos);
      }
      LogThisAt(8,"seqCell("<<outPos<<","<<d<<")="<<ll<<endl);
    }
    // looping over d AND prevState seems inefficient! Could precompute sumInTrans*outTrans for each outTok
    for (StateIndex d = 0; d < nStates; ++d) {
      double& ll = prefixCell (outPos, d);
      ll = seqCell (outPos, d);
      if (outPos) {
	const EvaluatedMachineState& state = tree.machine.state[d];
	for (const auto& i_ostm: state.incoming) {
	  const EvaluatedMachineState::OutStateTransMap& outStateTransMap = i_ostm.second;
	  if (outStateTransMap.count (outTok))
	    for (const auto& st: outStateTransMap.at (outTok)) {
	      const EvaluatedMachineState::Trans& trans = st.second;
	      for (StateIndex prevState = 0; prevState < nStates; ++prevState) {
		const double prevCell = prefixCell (outPos - 1, prevState);
		const double logEmitWeight = prevCell + tree.sumInTrans[prevState][st.first] + trans.logWeight;
		log_accum_exp (ll, logEmitWeight);
		LogThisAt(9,"prefixCell("<<outPos<<","<<d<<") logsum+= "<<prevCell<<" + "<<tree.sumInTrans[prevState][st.first]<<" + "<<trans.logWeight<<" ("<<prevState<<"->"<<st.first<<"->"<<d<<")"<<endl);
	      }
	    }
	}
      }
      LogThisAt(8,"prefixCell("<<outPos<<","<<d<<")="<<ll<<endl);
    }
  }

  for (StateIndex d = 0; d < nStates; ++d) {
    log_accum_exp (logPrefixProb, prefixCell(outLen,d) + tree.sumInTrans[d][tree.nStates - 1]);
    LogThisAt(9,"logPrefixProb logsum+= "<<prefixCell(outLen,d)<<" + "<<tree.sumInTrans[d][tree.nStates - 1]<<" ("<<d<<"->end)"<<endl);
  }

  if (parent && logPrefixProb > parent->logPrefixProb)
    Warn ("LogP(%s*)=%g rose from LogP(%s*)=%g",
	  to_string_join(tree.seqTraceback(this),"").c_str(), logPrefixProb,
	  to_string_join(tree.seqTraceback(parent),"").c_str(), parent->logPrefixProb);
}

double PrefixTree::Node::logSeqProb() const {
  return seqCell (outLen, nStates - 1);
}

PrefixTree::PrefixTree (const EvaluatedMachine& machine, const vguard<OutputSymbol>& outSym) :
  machine (machine),
  sumInTrans (machine.sumInTrans()),
  output (machine.outputTokenizer.tokenize (outSym)),
  outLen (output.size()),
  nStates (machine.nStates()),
  bestSeqNode (NULL),
  bestLogSeqProb (-numeric_limits<double>::infinity())
{
  addNode (NULL, machine.inputTokenizer.emptyToken());
  const InputToken inToks = machine.inputTokenizer.tok2sym.size() - 1;
  while (!nodeQueue.empty()) {
    Node* parent = bestPrefixNode();
    LogThisAt (5, "Nodes: " << nodeStore.size() << " Extending " << to_string_join(bestPrefix(),"") << "* (" << parent->logPrefixProb << ")" << endl);
    if (parent->logPrefixProb > bestLogSeqProb) {
      nodeQueue.pop();
      double norm = parent->logSeqProb();
      for (InputToken inTok = 1; inTok <= inToks; ++inTok)
	log_accum_exp (norm, addNode(parent,inTok)->logPrefixProb);
      LogThisAt (6, "log(Sum_x(P(Sx*)) / P(S*)) = " << (norm - exp(parent->logPrefixProb)) << endl);
    } else
      break;
  }
}

PrefixTree::Node* PrefixTree::addNode (const Node* parent, InputToken inTok) {
  nodeStore.push_back (Node (*this, parent, inTok));
  Node* nodePtr = &nodeStore.back();

  LogThisAt (6, "Adding node " << (parent ? to_string_join (seqTraceback (nodePtr), "") : string("<root>")) << endl);

  nodePtr->fill (*this);
  if (nodePtr->logPrefixProb > bestLogSeqProb)
    nodeQueue.push (nodePtr);

  const double logNodeSeqProb = nodePtr->logSeqProb();
  if (logNodeSeqProb > bestLogSeqProb) {
    bestSeqNode = nodePtr;
    bestLogSeqProb = logNodeSeqProb;
    LogThisAt (4, "Nodes: " << nodeStore.size() << " Best sequence so far: " << to_string_join (bestSeq(), "") << " (" << bestLogSeqProb << ")" << endl);
  }
  LogThisAt (7, "logP(seq)=" << logNodeSeqProb << " logP(seq*)=" << nodePtr->logPrefixProb << " seq: " << to_string_join (seqTraceback (nodePtr), "") << endl);

  return nodePtr;
}

vguard<InputSymbol> PrefixTree::seqTraceback (const Node* node) const {
  list<InputToken> inSeq;
  while (node && node->inTok) {
    inSeq.push_back (node->inTok);
    node = node->parent;
  }
  return machine.inputTokenizer.detokenize (vguard<InputToken> (inSeq.rbegin(), inSeq.rend()));
}
<commit_msg>fixed debug msg<commit_after>#include "ctc.h"
#include "logger.h"

PrefixTree::Node::Node() :
  inTok (0),
  parent (NULL),
  nStates (0),
  outLen (0)
{ }

PrefixTree::Node::Node (const PrefixTree& tree, const Node* parent, InputToken inTok) :
  inTok (inTok),
  parent (parent),
  nStates (tree.nStates),
  outLen (tree.outLen)
{ }

void PrefixTree::Node::fill (const PrefixTree& tree)
{
  cellStorage = vector<double> (nCells(), -numeric_limits<double>::infinity());
  logPrefixProb = -numeric_limits<double>::infinity();

  if (!parent)
    seqCell (0, 0) = 0;

  for (OutputIndex outPos = 0; outPos <= outLen; ++outPos) {
    const OutputToken outTok = outPos ? tree.output[outPos-1] : OutputTokenizer::emptyToken();
    for (StateIndex d = 0; d < nStates; ++d) {
      LogThisAt(9,"d="<<d<<": ");
      const EvaluatedMachineState& state = tree.machine.state[d];
      double& ll = seqCell (outPos, d);
      if (parent && state.incoming.count (inTok)) {
	const auto& incoming = state.incoming.at (inTok);
	if (outPos)
	  accumulateSeqCell (ll, incoming, *parent, outTok, outPos - 1);
	accumulateSeqCell (ll, incoming, *parent, OutputTokenizer::emptyToken(), outPos);
      }
      if (state.incoming.count (InputTokenizer::emptyToken())) {
	const auto& incoming = state.incoming.at (InputTokenizer::emptyToken());
	if (outPos)
	  accumulateSeqCell (ll, incoming, *this, outTok, outPos - 1);
	accumulateSeqCell (ll, incoming, *this, OutputTokenizer::emptyToken(), outPos);
      }
      LogThisAt(8,"seqCell("<<outPos<<","<<d<<")="<<ll<<endl);
    }
    // looping over d AND prevState seems inefficient! Could precompute sumInTrans*outTrans for each outTok
    for (StateIndex d = 0; d < nStates; ++d) {
      double& ll = prefixCell (outPos, d);
      ll = seqCell (outPos, d);
      if (outPos) {
	const EvaluatedMachineState& state = tree.machine.state[d];
	for (const auto& i_ostm: state.incoming) {
	  const EvaluatedMachineState::OutStateTransMap& outStateTransMap = i_ostm.second;
	  if (outStateTransMap.count (outTok))
	    for (const auto& st: outStateTransMap.at (outTok)) {
	      const EvaluatedMachineState::Trans& trans = st.second;
	      for (StateIndex prevState = 0; prevState < nStates; ++prevState) {
		const double prevCell = prefixCell (outPos - 1, prevState);
		const double logEmitWeight = prevCell + tree.sumInTrans[prevState][st.first] + trans.logWeight;
		log_accum_exp (ll, logEmitWeight);
		LogThisAt(9,"prefixCell("<<outPos<<","<<d<<") logsum+= "<<prevCell<<" + "<<tree.sumInTrans[prevState][st.first]<<" + "<<trans.logWeight<<" ("<<prevState<<"->"<<st.first<<"->"<<d<<")"<<endl);
	      }
	    }
	}
      }
      LogThisAt(8,"prefixCell("<<outPos<<","<<d<<")="<<ll<<endl);
    }
  }

  for (StateIndex d = 0; d < nStates; ++d) {
    log_accum_exp (logPrefixProb, prefixCell(outLen,d) + tree.sumInTrans[d][tree.nStates - 1]);
    LogThisAt(9,"logPrefixProb logsum+= "<<prefixCell(outLen,d)<<" + "<<tree.sumInTrans[d][tree.nStates - 1]<<" ("<<d<<"->end)"<<endl);
  }

  if (parent && logPrefixProb > parent->logPrefixProb)
    Warn ("LogP(%s*)=%g rose from LogP(%s*)=%g",
	  to_string_join(tree.seqTraceback(this),"").c_str(), logPrefixProb,
	  to_string_join(tree.seqTraceback(parent),"").c_str(), parent->logPrefixProb);
}

double PrefixTree::Node::logSeqProb() const {
  return seqCell (outLen, nStates - 1);
}

PrefixTree::PrefixTree (const EvaluatedMachine& machine, const vguard<OutputSymbol>& outSym) :
  machine (machine),
  sumInTrans (machine.sumInTrans()),
  output (machine.outputTokenizer.tokenize (outSym)),
  outLen (output.size()),
  nStates (machine.nStates()),
  bestSeqNode (NULL),
  bestLogSeqProb (-numeric_limits<double>::infinity())
{
  addNode (NULL, machine.inputTokenizer.emptyToken());
  const InputToken inToks = machine.inputTokenizer.tok2sym.size() - 1;
  while (!nodeQueue.empty()) {
    Node* parent = bestPrefixNode();
    LogThisAt (5, "Nodes: " << nodeStore.size() << " Extending " << to_string_join(bestPrefix(),"") << "* (" << parent->logPrefixProb << ")" << endl);
    if (parent->logPrefixProb > bestLogSeqProb) {
      nodeQueue.pop();
      double norm = parent->logSeqProb();
      for (InputToken inTok = 1; inTok <= inToks; ++inTok)
	log_accum_exp (norm, addNode(parent,inTok)->logPrefixProb);
      LogThisAt (6, "log(Sum_x(P(Sx*)) / P(S*)) = " << (norm - parent->logPrefixProb) << endl);
    } else
      break;
  }
}

PrefixTree::Node* PrefixTree::addNode (const Node* parent, InputToken inTok) {
  nodeStore.push_back (Node (*this, parent, inTok));
  Node* nodePtr = &nodeStore.back();

  LogThisAt (6, "Adding node " << (parent ? to_string_join (seqTraceback (nodePtr), "") : string("<root>")) << endl);

  nodePtr->fill (*this);
  if (nodePtr->logPrefixProb > bestLogSeqProb)
    nodeQueue.push (nodePtr);

  const double logNodeSeqProb = nodePtr->logSeqProb();
  if (logNodeSeqProb > bestLogSeqProb) {
    bestSeqNode = nodePtr;
    bestLogSeqProb = logNodeSeqProb;
    LogThisAt (4, "Nodes: " << nodeStore.size() << " Best sequence so far: " << to_string_join (bestSeq(), "") << " (" << bestLogSeqProb << ")" << endl);
  }
  LogThisAt (7, "logP(seq)=" << logNodeSeqProb << " logP(seq*)=" << nodePtr->logPrefixProb << " seq: " << to_string_join (seqTraceback (nodePtr), "") << endl);

  return nodePtr;
}

vguard<InputSymbol> PrefixTree::seqTraceback (const Node* node) const {
  list<InputToken> inSeq;
  while (node && node->inTok) {
    inSeq.push_back (node->inTok);
    node = node->parent;
  }
  return machine.inputTokenizer.detokenize (vguard<InputToken> (inSeq.rbegin(), inSeq.rend()));
}
<|endoftext|>


<commit_before>#include "BBE/BrotBoxEngine.h"
#include <iostream>

constexpr int WINDOW_WIDTH = 1920;
constexpr int WINDOW_HEIGHT = 1080;

class MyGame : public bbe::Game
{

	class Balloon {

	public:
		int x;
		int y;
		int heigth;
		int width;
		float hue;

		Balloon(int x, int y, int width, int heigth, float hue) {
			this->x = x;
			this->y = y;

			this->width = width;
			this->heigth = heigth;
			this->hue = hue;
		}

	};

	int BALLOON_WIDTH = 40;
	int BALLOON_HEIGTH = 60;
	int SCORE = 0;
	bbe::Font myFont;
	bbe::Random random;
	bool gameover = false;
	bbe::Image background;

	bbe::List<Balloon> balloons;

	virtual void onStart() override
	{
		myFont.load("arial.ttf", 200);
		background.load("sky.jpg");
		addBalloon();

	}

	void addBalloon() {
		balloons.add(Balloon(random.randomInt(WINDOW_WIDTH - BALLOON_WIDTH), WINDOW_HEIGHT,
			 BALLOON_WIDTH, BALLOON_HEIGTH, randomBalloonHue()));
	}

	bbe::Color randomBalloonColor() {
		return bbe::Color(random.randomFloat(), random.randomFloat(), 0);
	}

	float randomBalloonHue() {
		return random.randomFloat()*360;
	}

	virtual void update(float timeSinceLastFrame) override
	{

		if (gameover) return;

		for (Balloon& b : balloons) {

			if (checkGameOver(b)) {
				gameover = true;
			}
			// check game over
			if (checkMousePosition(b) && isMousePressed(bbe::MouseButton::LEFT)) {
				b.y = WINDOW_HEIGHT;
				b.x = random.randomInt(WINDOW_WIDTH - b.width);
				b.hue = randomBalloonHue();
				SCORE++;

				if (random.randomFloat()<0.2) {
					addBalloon();
				}
			}
			b.y--;
		}
	}

	bool checkGameOver(const Balloon& b) {
		return  (b.y <= myFont.getFontSize() + 40);
	}

	bool checkMousePosition(const Balloon &b) {
		return (getMouseY() < b.y + b.heigth  && getMouseY() > b.y )
			&& (getMouseX() < b.x + b.width && getMouseX() > b.x);
	}

	virtual void draw3D(bbe::PrimitiveBrush3D & brush) override
	{
	}
	virtual void draw2D(bbe::PrimitiveBrush2D& brush) override
	{

		brush.setColorRGB(bbe::Color(1, 1, 1));
		brush.fillRect(bbe::Rectangle(0, 0, WINDOW_WIDTH, myFont.getFontSize() + 40));

		brush.setColorRGB(bbe::Color(0, 0, 0));
		bbe::String currentScore = "Your Score: ";
		currentScore += SCORE;
		brush.fillText(10, myFont.getFontSize() + 20, currentScore.getRaw(), myFont);

		brush.setColorRGB(bbe::Color(0, 0, 0));
		brush.fillLine(0, myFont.getFontSize() + 40, WINDOW_WIDTH, myFont.getFontSize() + 40, 5);

		brush.drawImage(bbe::Rectangle(0, myFont.getFontSize() + 40, WINDOW_WIDTH, WINDOW_HEIGHT), background);

		// for each balloon draw
		for (Balloon& b : balloons) {
			brush.setColorHSV(b.hue, 1, 1);
			brush.fillCircle(bbe::Circle(b.x, b.y, b.width, b.heigth));
		}

		if (gameover){
			brush.setColorRGB(bbe::Color(1, 0, 0));
			brush.fillText(10, WINDOW_HEIGHT/2, "Game Over!", myFont);

		}
	}

	virtual void onEnd() override
	{
	}

};

int main()
{
	MyGame *mg = new MyGame();
	mg->start(WINDOW_WIDTH, WINDOW_HEIGHT, "Balloon Game");
	delete mg;
}
<commit_msg>Refactored ExampleBalloonGame<commit_after>#include "BBE/BrotBoxEngine.h"
#include <iostream>

constexpr int WINDOW_WIDTH = 1920;
constexpr int WINDOW_HEIGHT = 1080;

class MyGame : public bbe::Game
{
private:
	class Balloon {
	public:
		float x;
		float y;
		float width;
		float heigth;
		float hue;

		Balloon(float x, float y, float width, float heigth, float hue)
			: x(x), y(y), width(width), heigth(heigth), hue(hue)
		{
		}
	};

	static constexpr int BALLOON_WIDTH = 40;
	static constexpr int BALLOON_HEIGTH = 60;

	bool gameover = false;
	int score = 0;

	bbe::Font font;
	bbe::Random random;
	bbe::Image background;
	bbe::List<Balloon> balloons;

	void addBalloon() {
		balloons.add(Balloon(random.randomInt(WINDOW_WIDTH - BALLOON_WIDTH), WINDOW_HEIGHT,
			BALLOON_WIDTH, BALLOON_HEIGTH, randomBalloonHue()));
	}

	float randomBalloonHue() {
		return random.randomFloat() * 360;
	}

	bool checkGameOver(const Balloon& b) {
		return (b.y <= font.getFontSize() + 40);
	}

	bool checkMousePosition(const Balloon& b) {
		return (getMouseY() < b.y + b.heigth && getMouseY() > b.y)
			&& (getMouseX() < b.x + b.width  && getMouseX() > b.x);
	}

public:
	virtual void onStart() override
	{
		font.load("arial.ttf", 200);
		background.load("sky.jpg");
		addBalloon();
	}

	virtual void update(float timeSinceLastFrame) override
	{
		if (gameover) return;

		for (Balloon& b : balloons) {
			if (checkGameOver(b)) {
				gameover = true;
			}

			if (checkMousePosition(b) && isMousePressed(bbe::MouseButton::LEFT)) {
				b.y = WINDOW_HEIGHT;
				b.x = random.randomFloat(WINDOW_WIDTH - b.width);
				b.hue = randomBalloonHue();
				score++;

				if (random.randomFloat()<0.2) {
					addBalloon();
				}
			}
			b.y-=timeSinceLastFrame*60;
		}
	}

	virtual void draw3D(bbe::PrimitiveBrush3D & brush) override
	{
	}

	virtual void draw2D(bbe::PrimitiveBrush2D& brush) override
	{
		brush.setColorRGB(1, 1, 1);
		brush.fillRect(bbe::Rectangle(0, 0, WINDOW_WIDTH, font.getFontSize() + 40));

		brush.setColorRGB(0, 0, 0);
		bbe::String currentScore = "Your Score: ";
		currentScore += score;
		brush.fillText(10, font.getFontSize() + 20, currentScore.getRaw(), font);

		brush.setColorRGB(0, 0, 0);
		brush.fillLine(0, font.getFontSize() + 40, WINDOW_WIDTH, font.getFontSize() + 40, 5);

		brush.setColorRGB(1, 1, 1);
		brush.drawImage(bbe::Rectangle(0, font.getFontSize() + 40, WINDOW_WIDTH, background.getHeight()), background);

		for (Balloon& b : balloons) {
			brush.setColorHSV(b.hue, 1, 1);
			brush.fillCircle(bbe::Circle(b.x, b.y, b.width, b.heigth));
		}

		if (gameover){
			brush.setColorRGB(1, 0, 0);
			brush.fillText(10, WINDOW_HEIGHT/2, "Game Over!", font);

		}
	}

	virtual void onEnd() override
	{
	}
};

int main()
{
	MyGame *mg = new MyGame();
	mg->start(WINDOW_WIDTH, WINDOW_HEIGHT, "Balloon Game");
	delete mg;
}
<|endoftext|>


<commit_before>/*
 * Copyright © 2010 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#include "ast.h"
#include "glsl_types.h"
#include "ir.h"

void
ast_array_specifier::print(void) const
{
   if (this->is_unsized_array) {
      printf("[ ] ");
   }

   foreach_list_typed (ast_node, array_dimension, link, &this->array_dimensions) {
      printf("[ ");
      array_dimension->print();
      printf("] ");
   }
}

/**
 * If \c ir is a reference to an array for which we are tracking the max array
 * element accessed, track that the given element has been accessed.
 * Otherwise do nothing.
 *
 * This function also checks whether the array is a built-in array whose
 * maximum size is too small to accommodate the given index, and if so uses
 * loc and state to report the error.
 */
static void
update_max_array_access(ir_rvalue *ir, unsigned idx, YYLTYPE *loc,
                        struct _mesa_glsl_parse_state *state)
{
   if (ir_dereference_variable *deref_var = ir->as_dereference_variable()) {
      ir_variable *var = deref_var->var;
      if (idx > var->data.max_array_access) {
         var->data.max_array_access = idx;

         /* Check whether this access will, as a side effect, implicitly cause
          * the size of a built-in array to be too large.
          */
         check_builtin_array_max_size(var->name, idx+1, *loc, state);
      }
   } else if (ir_dereference_record *deref_record =
              ir->as_dereference_record()) {
      /* There are two possibilities we need to consider:
       *
       * - Accessing an element of an array that is a member of a named
       *   interface block (e.g. ifc.foo[i])
       *
       * - Accessing an element of an array that is a member of a named
       *   interface block array (e.g. ifc[j].foo[i]).
       */
      ir_dereference_variable *deref_var =
         deref_record->record->as_dereference_variable();
      if (deref_var == NULL) {
         if (ir_dereference_array *deref_array =
             deref_record->record->as_dereference_array()) {
            deref_var = deref_array->array->as_dereference_variable();
         }
      }

      if (deref_var != NULL) {
         if (deref_var->var->is_interface_instance()) {
            const glsl_type *interface_type =
               deref_var->var->get_interface_type();
            unsigned field_index =
               deref_record->record->type->field_index(deref_record->field);
            assert(field_index < interface_type->length);
            if (idx > deref_var->var->max_ifc_array_access[field_index]) {
               deref_var->var->max_ifc_array_access[field_index] = idx;

               /* Check whether this access will, as a side effect, implicitly
                * cause the size of a built-in array to be too large.
                */
               check_builtin_array_max_size(deref_record->field, idx+1, *loc,
                                            state);
            }
         }
      }
   }
}

ir_rvalue *
_mesa_ast_array_index_to_hir(void *mem_ctx,
			     struct _mesa_glsl_parse_state *state,
			     ir_rvalue *array, ir_rvalue *idx,
			     YYLTYPE &loc, YYLTYPE &idx_loc)
{
   if (!array->type->is_error()
       && !array->type->is_array()
       && !array->type->is_matrix()
       && !array->type->is_vector()) {
      _mesa_glsl_error(& idx_loc, state,
		       "cannot dereference non-array / non-matrix / "
		       "non-vector");
   }

   if (!idx->type->is_error()) {
      if (!idx->type->is_integer()) {
	 _mesa_glsl_error(& idx_loc, state, "array index must be integer type");
      } else if (!idx->type->is_scalar()) {
	 _mesa_glsl_error(& idx_loc, state, "array index must be scalar");
      }
   }

   /* If the array index is a constant expression and the array has a
    * declared size, ensure that the access is in-bounds.  If the array
    * index is not a constant expression, ensure that the array has a
    * declared size.
    */
   ir_constant *const const_index = idx->constant_expression_value();
   if (const_index != NULL && idx->type->is_integer()) {
      const int idx = const_index->value.i[0];
      const char *type_name = "error";
      unsigned bound = 0;

      /* From page 24 (page 30 of the PDF) of the GLSL 1.50 spec:
       *
       *    "It is illegal to declare an array with a size, and then
       *    later (in the same shader) index the same array with an
       *    integral constant expression greater than or equal to the
       *    declared size. It is also illegal to index an array with a
       *    negative constant expression."
       */
      if (array->type->is_matrix()) {
	 if (array->type->row_type()->vector_elements <= idx) {
	    type_name = "matrix";
	    bound = array->type->row_type()->vector_elements;
	 }
      } else if (array->type->is_vector()) {
	 if (array->type->vector_elements <= idx) {
	    type_name = "vector";
	    bound = array->type->vector_elements;
	 }
      } else {
	 /* glsl_type::array_size() returns -1 for non-array types.  This means
	  * that we don't need to verify that the type is an array before
	  * doing the bounds checking.
	  */
	 if ((array->type->array_size() > 0)
	     && (array->type->array_size() <= idx)) {
	    type_name = "array";
	    bound = array->type->array_size();
	 }
      }

      if (bound > 0) {
	 _mesa_glsl_error(& loc, state, "%s index must be < %u",
			  type_name, bound);
      } else if (idx < 0) {
	 _mesa_glsl_error(& loc, state, "%s index must be >= 0",
			  type_name);
      }

      if (array->type->is_array())
         update_max_array_access(array, idx, &loc, state);
   } else if (const_index == NULL && array->type->is_array()) {
      if (array->type->is_unsized_array()) {
	 _mesa_glsl_error(&loc, state, "unsized array index must be constant");
      } else if (array->type->fields.array->is_interface()
                 && array->variable_referenced()->data.mode == ir_var_uniform) {
	 /* Page 46 in section 4.3.7 of the OpenGL ES 3.00 spec says:
	  *
	  *     "All indexes used to index a uniform block array must be
	  *     constant integral expressions."
	  */
	 _mesa_glsl_error(&loc, state,
			  "uniform block array index must be constant");
      } else {
	 /* whole_variable_referenced can return NULL if the array is a
	  * member of a structure.  In this case it is safe to not update
	  * the max_array_access field because it is never used for fields
	  * of structures.
	  */
	 ir_variable *v = array->whole_variable_referenced();
	 if (v != NULL)
	    v->data.max_array_access = array->type->array_size() - 1;
      }

      /* From page 23 (29 of the PDF) of the GLSL 1.30 spec:
       *
       *    "Samplers aggregated into arrays within a shader (using square
       *    brackets [ ]) can only be indexed with integral constant
       *    expressions [...]."
       *
       * This restriction was added in GLSL 1.30.  Shaders using earlier
       * version of the language should not be rejected by the compiler
       * front-end for using this construct.  This allows useful things such
       * as using a loop counter as the index to an array of samplers.  If the
       * loop in unrolled, the code should compile correctly.  Instead, emit a
       * warning.
       */
      if (array->type->element_type()->is_sampler()) {
	 if (!state->is_version(130, 100)) {
	    if (state->es_shader) {
	       _mesa_glsl_warning(&loc, state,
				  "sampler arrays indexed with non-constant "
				  "expressions is optional in %s",
				  state->get_version_string());
	    } else {
	       _mesa_glsl_warning(&loc, state,
				  "sampler arrays indexed with non-constant "
				  "expressions will be forbidden in GLSL 1.30 "
				  "and later");
	    }
	 } else {
	    _mesa_glsl_error(&loc, state,
			     "sampler arrays indexed with non-constant "
			     "expressions is forbidden in GLSL 1.30 and "
			     "later");
	 }
      }
   }

   /* After performing all of the error checking, generate the IR for the
    * expression.
    */
   if (array->type->is_array()
       || array->type->is_matrix()) {
      return new(mem_ctx) ir_dereference_array(array, idx);
   } else if (array->type->is_vector()) {
      return new(mem_ctx) ir_expression(ir_binop_vector_extract, array, idx);
   } else if (array->type->is_error()) {
      return array;
   } else {
      ir_rvalue *result = new(mem_ctx) ir_dereference_array(array, idx);
      result->type = glsl_type::error_type;

      return result;
   }
}
<commit_msg>glsl: Allow non-constant UBO array indexing with GLSL4/ARB_gpu_shader5.<commit_after>/*
 * Copyright © 2010 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#include "ast.h"
#include "glsl_types.h"
#include "ir.h"

void
ast_array_specifier::print(void) const
{
   if (this->is_unsized_array) {
      printf("[ ] ");
   }

   foreach_list_typed (ast_node, array_dimension, link, &this->array_dimensions) {
      printf("[ ");
      array_dimension->print();
      printf("] ");
   }
}

/**
 * If \c ir is a reference to an array for which we are tracking the max array
 * element accessed, track that the given element has been accessed.
 * Otherwise do nothing.
 *
 * This function also checks whether the array is a built-in array whose
 * maximum size is too small to accommodate the given index, and if so uses
 * loc and state to report the error.
 */
static void
update_max_array_access(ir_rvalue *ir, unsigned idx, YYLTYPE *loc,
                        struct _mesa_glsl_parse_state *state)
{
   if (ir_dereference_variable *deref_var = ir->as_dereference_variable()) {
      ir_variable *var = deref_var->var;
      if (idx > var->data.max_array_access) {
         var->data.max_array_access = idx;

         /* Check whether this access will, as a side effect, implicitly cause
          * the size of a built-in array to be too large.
          */
         check_builtin_array_max_size(var->name, idx+1, *loc, state);
      }
   } else if (ir_dereference_record *deref_record =
              ir->as_dereference_record()) {
      /* There are two possibilities we need to consider:
       *
       * - Accessing an element of an array that is a member of a named
       *   interface block (e.g. ifc.foo[i])
       *
       * - Accessing an element of an array that is a member of a named
       *   interface block array (e.g. ifc[j].foo[i]).
       */
      ir_dereference_variable *deref_var =
         deref_record->record->as_dereference_variable();
      if (deref_var == NULL) {
         if (ir_dereference_array *deref_array =
             deref_record->record->as_dereference_array()) {
            deref_var = deref_array->array->as_dereference_variable();
         }
      }

      if (deref_var != NULL) {
         if (deref_var->var->is_interface_instance()) {
            const glsl_type *interface_type =
               deref_var->var->get_interface_type();
            unsigned field_index =
               deref_record->record->type->field_index(deref_record->field);
            assert(field_index < interface_type->length);
            if (idx > deref_var->var->max_ifc_array_access[field_index]) {
               deref_var->var->max_ifc_array_access[field_index] = idx;

               /* Check whether this access will, as a side effect, implicitly
                * cause the size of a built-in array to be too large.
                */
               check_builtin_array_max_size(deref_record->field, idx+1, *loc,
                                            state);
            }
         }
      }
   }
}

ir_rvalue *
_mesa_ast_array_index_to_hir(void *mem_ctx,
			     struct _mesa_glsl_parse_state *state,
			     ir_rvalue *array, ir_rvalue *idx,
			     YYLTYPE &loc, YYLTYPE &idx_loc)
{
   if (!array->type->is_error()
       && !array->type->is_array()
       && !array->type->is_matrix()
       && !array->type->is_vector()) {
      _mesa_glsl_error(& idx_loc, state,
		       "cannot dereference non-array / non-matrix / "
		       "non-vector");
   }

   if (!idx->type->is_error()) {
      if (!idx->type->is_integer()) {
	 _mesa_glsl_error(& idx_loc, state, "array index must be integer type");
      } else if (!idx->type->is_scalar()) {
	 _mesa_glsl_error(& idx_loc, state, "array index must be scalar");
      }
   }

   /* If the array index is a constant expression and the array has a
    * declared size, ensure that the access is in-bounds.  If the array
    * index is not a constant expression, ensure that the array has a
    * declared size.
    */
   ir_constant *const const_index = idx->constant_expression_value();
   if (const_index != NULL && idx->type->is_integer()) {
      const int idx = const_index->value.i[0];
      const char *type_name = "error";
      unsigned bound = 0;

      /* From page 24 (page 30 of the PDF) of the GLSL 1.50 spec:
       *
       *    "It is illegal to declare an array with a size, and then
       *    later (in the same shader) index the same array with an
       *    integral constant expression greater than or equal to the
       *    declared size. It is also illegal to index an array with a
       *    negative constant expression."
       */
      if (array->type->is_matrix()) {
	 if (array->type->row_type()->vector_elements <= idx) {
	    type_name = "matrix";
	    bound = array->type->row_type()->vector_elements;
	 }
      } else if (array->type->is_vector()) {
	 if (array->type->vector_elements <= idx) {
	    type_name = "vector";
	    bound = array->type->vector_elements;
	 }
      } else {
	 /* glsl_type::array_size() returns -1 for non-array types.  This means
	  * that we don't need to verify that the type is an array before
	  * doing the bounds checking.
	  */
	 if ((array->type->array_size() > 0)
	     && (array->type->array_size() <= idx)) {
	    type_name = "array";
	    bound = array->type->array_size();
	 }
      }

      if (bound > 0) {
	 _mesa_glsl_error(& loc, state, "%s index must be < %u",
			  type_name, bound);
      } else if (idx < 0) {
	 _mesa_glsl_error(& loc, state, "%s index must be >= 0",
			  type_name);
      }

      if (array->type->is_array())
         update_max_array_access(array, idx, &loc, state);
   } else if (const_index == NULL && array->type->is_array()) {
      if (array->type->is_unsized_array()) {
	 _mesa_glsl_error(&loc, state, "unsized array index must be constant");
      } else if (array->type->fields.array->is_interface()
                 && array->variable_referenced()->data.mode == ir_var_uniform
                 && !state->is_version(400, 0) && !state->ARB_gpu_shader5_enable) {
	 /* Page 46 in section 4.3.7 of the OpenGL ES 3.00 spec says:
	  *
	  *     "All indexes used to index a uniform block array must be
	  *     constant integral expressions."
	  */
	 _mesa_glsl_error(&loc, state,
			  "uniform block array index must be constant");
      } else {
	 /* whole_variable_referenced can return NULL if the array is a
	  * member of a structure.  In this case it is safe to not update
	  * the max_array_access field because it is never used for fields
	  * of structures.
	  */
	 ir_variable *v = array->whole_variable_referenced();
	 if (v != NULL)
	    v->data.max_array_access = array->type->array_size() - 1;
      }

      /* From page 23 (29 of the PDF) of the GLSL 1.30 spec:
       *
       *    "Samplers aggregated into arrays within a shader (using square
       *    brackets [ ]) can only be indexed with integral constant
       *    expressions [...]."
       *
       * This restriction was added in GLSL 1.30.  Shaders using earlier
       * version of the language should not be rejected by the compiler
       * front-end for using this construct.  This allows useful things such
       * as using a loop counter as the index to an array of samplers.  If the
       * loop in unrolled, the code should compile correctly.  Instead, emit a
       * warning.
       */
      if (array->type->element_type()->is_sampler()) {
	 if (!state->is_version(130, 100)) {
	    if (state->es_shader) {
	       _mesa_glsl_warning(&loc, state,
				  "sampler arrays indexed with non-constant "
				  "expressions is optional in %s",
				  state->get_version_string());
	    } else {
	       _mesa_glsl_warning(&loc, state,
				  "sampler arrays indexed with non-constant "
				  "expressions will be forbidden in GLSL 1.30 "
				  "and later");
	    }
	 } else {
	    _mesa_glsl_error(&loc, state,
			     "sampler arrays indexed with non-constant "
			     "expressions is forbidden in GLSL 1.30 and "
			     "later");
	 }
      }
   }

   /* After performing all of the error checking, generate the IR for the
    * expression.
    */
   if (array->type->is_array()
       || array->type->is_matrix()) {
      return new(mem_ctx) ir_dereference_array(array, idx);
   } else if (array->type->is_vector()) {
      return new(mem_ctx) ir_expression(ir_binop_vector_extract, array, idx);
   } else if (array->type->is_error()) {
      return array;
   } else {
      ir_rvalue *result = new(mem_ctx) ir_dereference_array(array, idx);
      result->type = glsl_type::error_type;

      return result;
   }
}
<|endoftext|>


<commit_before>/*
 * Copyright 2017 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrBackendSurface.h"

#ifdef SK_VULKAN
#include "vk/GrVkTypes.h"
#include "vk/GrVkUtil.h"
#endif

GrBackendTexture::GrBackendTexture(int width,
                                   int height,
                                   const GrVkImageInfo* vkInfo)
        : fWidth(width)
        , fHeight(height)
        , fConfig(
#ifdef SK_VULKAN
                  GrVkFormatToPixelConfig(vkInfo->fFormat)
#else
                  kUnknown_GrPixelConfig
#endif
                  )
        , fBackend(kVulkan_GrBackend)
        , fVkInfo(vkInfo) {}

GrBackendTexture::GrBackendTexture(int width,
                                   int height,
                                   GrPixelConfig config,
                                   const GrGLTextureInfo* glInfo)
        : fWidth(width)
        , fHeight(height)
        , fConfig(config)
        , fBackend(kOpenGL_GrBackend)
        , fGLInfo(glInfo) {}

GrBackendTexture::GrBackendTexture(const GrBackendTextureDesc& desc, GrBackend backend)
        : fWidth(desc.fWidth)
        , fHeight(desc.fHeight)
        , fConfig(kVulkan_GrBackend == backend
#ifdef SK_VULKAN
                  ? GrVkFormatToPixelConfig(((GrVkImageInfo*)desc.fTextureHandle)->fFormat)
#else
                  ? kUnknown_GrPixelConfig
#endif
                  : desc.fConfig)
        , fBackend(backend)
        , fHandle(desc.fTextureHandle) {}

const GrVkImageInfo* GrBackendTexture::getVkImageInfo() const {
    if (kVulkan_GrBackend == fBackend) {
        return fVkInfo;
    }
    return nullptr;
}

const GrGLTextureInfo* GrBackendTexture::getGLTextureInfo() const {
    if (kOpenGL_GrBackend == fBackend) {
        return fGLInfo;
    }
    return nullptr;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

GrBackendRenderTarget::GrBackendRenderTarget(int width,
                                             int height,
                                             int sampleCnt,
                                             int stencilBits,
                                             const GrVkImageInfo& vkInfo)
        : fWidth(width)
        , fHeight(height)
        , fSampleCnt(sampleCnt)
        , fStencilBits(stencilBits)
        , fConfig(
#ifdef SK_VULKAN
                  GrVkFormatToPixelConfig(vkInfo.fFormat)
#else
                  kUnknown_GrPixelConfig
#endif
                  )
        , fBackend(kVulkan_GrBackend)
        , fVkInfo(vkInfo) {}

GrBackendRenderTarget::GrBackendRenderTarget(int width,
                                             int height,
                                             int sampleCnt,
                                             int stencilBits,
                                             GrPixelConfig config,
                                             const GrGLFramebufferInfo& glInfo)
        : fWidth(width)
        , fHeight(height)
        , fSampleCnt(sampleCnt)
        , fStencilBits(stencilBits)
        , fConfig(config)
        , fBackend(kOpenGL_GrBackend)
        , fGLInfo(glInfo) {}

GrBackendRenderTarget::GrBackendRenderTarget(const GrBackendRenderTargetDesc& desc,
                                             GrBackend backend)
        : fWidth(desc.fWidth)
        , fHeight(desc.fHeight)
        , fSampleCnt(desc.fSampleCnt)
        , fStencilBits(desc.fStencilBits)
        , fConfig(desc.fConfig)
        , fBackend(backend) {
    if (kOpenGL_GrBackend == backend) {
        fGLInfo = *reinterpret_cast<const GrGLFramebufferInfo*>(desc.fRenderTargetHandle);
    } else {
        SkASSERT(kVulkan_GrBackend == backend);
#ifdef SK_VULKAN
        const GrVkImageInfo* vkInfo =
                reinterpret_cast<const GrVkImageInfo*>(desc.fRenderTargetHandle);
        fConfig = GrVkFormatToPixelConfig(vkInfo->fFormat);
        fVkInfo = *vkInfo;
#else
        fConfig = kUnknown_GrPixelConfig;
#endif
    }
}

const GrVkImageInfo* GrBackendRenderTarget::getVkImageInfo() const {
    if (kVulkan_GrBackend == fBackend) {
        return &fVkInfo;
    }
    return nullptr;
}

const GrGLFramebufferInfo* GrBackendRenderTarget::getGLFramebufferInfo() const {
    if (kOpenGL_GrBackend == fBackend) {
        return &fGLInfo;
    }
    return nullptr;
}

<commit_msg>Fix Creation of GrBackendRenderTarget from GrBackendRenderTargetDesc in GL<commit_after>/*
 * Copyright 2017 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrBackendSurface.h"

#ifdef SK_VULKAN
#include "vk/GrVkTypes.h"
#include "vk/GrVkUtil.h"
#endif

GrBackendTexture::GrBackendTexture(int width,
                                   int height,
                                   const GrVkImageInfo* vkInfo)
        : fWidth(width)
        , fHeight(height)
        , fConfig(
#ifdef SK_VULKAN
                  GrVkFormatToPixelConfig(vkInfo->fFormat)
#else
                  kUnknown_GrPixelConfig
#endif
                  )
        , fBackend(kVulkan_GrBackend)
        , fVkInfo(vkInfo) {}

GrBackendTexture::GrBackendTexture(int width,
                                   int height,
                                   GrPixelConfig config,
                                   const GrGLTextureInfo* glInfo)
        : fWidth(width)
        , fHeight(height)
        , fConfig(config)
        , fBackend(kOpenGL_GrBackend)
        , fGLInfo(glInfo) {}

GrBackendTexture::GrBackendTexture(const GrBackendTextureDesc& desc, GrBackend backend)
        : fWidth(desc.fWidth)
        , fHeight(desc.fHeight)
        , fConfig(kVulkan_GrBackend == backend
#ifdef SK_VULKAN
                  ? GrVkFormatToPixelConfig(((GrVkImageInfo*)desc.fTextureHandle)->fFormat)
#else
                  ? kUnknown_GrPixelConfig
#endif
                  : desc.fConfig)
        , fBackend(backend)
        , fHandle(desc.fTextureHandle) {}

const GrVkImageInfo* GrBackendTexture::getVkImageInfo() const {
    if (kVulkan_GrBackend == fBackend) {
        return fVkInfo;
    }
    return nullptr;
}

const GrGLTextureInfo* GrBackendTexture::getGLTextureInfo() const {
    if (kOpenGL_GrBackend == fBackend) {
        return fGLInfo;
    }
    return nullptr;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

GrBackendRenderTarget::GrBackendRenderTarget(int width,
                                             int height,
                                             int sampleCnt,
                                             int stencilBits,
                                             const GrVkImageInfo& vkInfo)
        : fWidth(width)
        , fHeight(height)
        , fSampleCnt(sampleCnt)
        , fStencilBits(stencilBits)
        , fConfig(
#ifdef SK_VULKAN
                  GrVkFormatToPixelConfig(vkInfo.fFormat)
#else
                  kUnknown_GrPixelConfig
#endif
                  )
        , fBackend(kVulkan_GrBackend)
        , fVkInfo(vkInfo) {}

GrBackendRenderTarget::GrBackendRenderTarget(int width,
                                             int height,
                                             int sampleCnt,
                                             int stencilBits,
                                             GrPixelConfig config,
                                             const GrGLFramebufferInfo& glInfo)
        : fWidth(width)
        , fHeight(height)
        , fSampleCnt(sampleCnt)
        , fStencilBits(stencilBits)
        , fConfig(config)
        , fBackend(kOpenGL_GrBackend)
        , fGLInfo(glInfo) {}

GrBackendRenderTarget::GrBackendRenderTarget(const GrBackendRenderTargetDesc& desc,
                                             GrBackend backend)
        : fWidth(desc.fWidth)
        , fHeight(desc.fHeight)
        , fSampleCnt(desc.fSampleCnt)
        , fStencilBits(desc.fStencilBits)
        , fConfig(desc.fConfig)
        , fBackend(backend) {
    if (kOpenGL_GrBackend == backend) {
        fGLInfo.fFBOID = static_cast<GrGLuint>(desc.fRenderTargetHandle);
    } else {
        SkASSERT(kVulkan_GrBackend == backend);
#ifdef SK_VULKAN
        const GrVkImageInfo* vkInfo =
                reinterpret_cast<const GrVkImageInfo*>(desc.fRenderTargetHandle);
        fConfig = GrVkFormatToPixelConfig(vkInfo->fFormat);
        fVkInfo = *vkInfo;
#else
        fConfig = kUnknown_GrPixelConfig;
#endif
    }
}

const GrVkImageInfo* GrBackendRenderTarget::getVkImageInfo() const {
    if (kVulkan_GrBackend == fBackend) {
        return &fVkInfo;
    }
    return nullptr;
}

const GrGLFramebufferInfo* GrBackendRenderTarget::getGLFramebufferInfo() const {
    if (kOpenGL_GrBackend == fBackend) {
        return &fGLInfo;
    }
    return nullptr;
}

<|endoftext|>


<commit_before>#include <ncurses.h>
#include <iostream>
#include <unistd.h>
#include <algorithm>

#include "interface/Display.h"
#include "map/Map.h"
#include "map/filters/DrunkardsWalkFilter.h"
#include "core/Rand.h"

#include "entity/ecs.h"

void pause_curses(Display& display)
{
	display.pause();

	std::cout << "Paused ncurses..." << std::endl;

	sleep(4);

	std::cout << "Resuming..." << std::endl;

	sleep(1);
	display.resume();
}

bool move_pc(Map& level, PositionComponent& pc_pos, int dx, int dy)
{
	int new_x = pc_pos.x + dx;
	int new_y = pc_pos.y + dy;

	//Make sure it's in bounds
	if(0 <= new_x && new_x < level.getWidth() && 0 <= new_y && new_y < level.getHeight())
	{
		//Make sure it's passable terrain
		if(level[new_x][new_y].isPassable())
		{
			//Adjust PC's x,y coordinates
			pc_pos.x += dx;
			pc_pos.y += dy;

			return true;
		}
	}
	return false;
}

void spawn_npc(Map& level, PositionComponent& npc_pos, PositionComponent& pc_pos, int max_dist = 15)
{
	static Rand rand(time(NULL));

	int min_x = std::max(0, pc_pos.x - max_dist);
	int max_x = std::min(level.getWidth()-1, pc_pos.x + max_dist);

	int min_y = std::max(0, pc_pos.y - max_dist);
	int max_y = std::min(level.getHeight()-1, pc_pos.y + max_dist);

	do {
		npc_pos.x = rand.randInt(min_x, max_x);
		npc_pos.y = rand.randInt(min_y, max_y);
	} while(level[npc_pos.x][npc_pos.y] != FloorTile);
}

int main()
{
	Display display;
	EntityManager em;

	//Set up our ComponentManagers
	PositionManager pos_mgr;
	SpriteManager sprite_mgr;
	SkillManager skill_mgr;
	AttackManager attack_mgr;
	em.addComponentManager(&pos_mgr);
	em.addComponentManager(&sprite_mgr);
	em.addComponentManager(&skill_mgr);
	em.addComponentManager(&attack_mgr);

	//We'll also need an AttackSystem, though no setup is necessary
	AttackSystem sys_attack;

	XYPair screen = display.getScreenSize();

	//Make a map double the screen size
	int map_y = screen.y * 2;
	int map_x = screen.x * 2;
	//Generate a map
	Map cave(map_x, map_y);
	DrunkardsWalkFilter walk;
	walk.setSeed(time(NULL));
	walk.apply(cave);

	//Find a random FloorTile to put our PC on
	Entity pc = em.createEntity();
	PositionComponent pc_pos;
	SpriteComponent pc_sprite = { '@', 0, 0 };
	Rand rand(time(NULL));
	do {
		pc_pos.x = rand.randInt(0, cave.getWidth()-1);
		pc_pos.y = rand.randInt(0, cave.getHeight()-1);
	} while(cave[pc_pos.x][pc_pos.y] != FloorTile);
	pos_mgr.setComponent(pc, pc_pos);
	sprite_mgr.setComponent(pc, pc_sprite);

	//Now create a Window and viewport for our level
	WindowGeometry map_geometry = { {20,3}, {AUTO_SIZE, AUTO_SIZE} };
	Window map = display.addWindow(cave, map_geometry);

	//Geometries for our top and left Windows
	WindowGeometry top_geometry = { {0,0}, {AUTO_SIZE, 3} };
	WindowGeometry left_geometry = { { 0, 3 }, {20, AUTO_SIZE} };
	//And now create them
	Window top = display.addWindow(top_geometry);
	Window left = display.addWindow(left_geometry);

	//top.addBorder();
	//left.addBorder();

	//New set up our RenderSystem
	RenderSystem render(&display, map);

	display.add(top, mkXYPair(1,0), "Message Panel");
	display.add(left, mkXYPair(1,0), "Stat Panel");

	//Center the map viewport on the PC
	display.center(map, pc_pos);

	//Let's display some map display stats
	//Display our view's X and Y coordinates
	//wm.getWindow(1)->add(1, 2, "View Position:");
	//wm.getWindow(1)->add(1, 3, "X:     ");
	//wm.getWindow(1)->addInt(4, 3, map.getViewX());
	//wm.getWindow(1)->add(1, 4, "Y:     ");
	//wm.getWindow(1)->addInt(4, 4, map.getViewY());

	//Display map size
	//wm.getWindow(1)->add(1, 6, "Map Size:");
	//wm.getWindow(1)->add(1, 7, "W:");
	//wm.getWindow(1)->addInt(4, 7, cave.getWidth());
	//wm.getWindow(1)->add(1, 8, "H:");
	//wm.getWindow(1)->addInt(4, 8, cave.getHeight());

	//Display viewport size
	//wm.getWindow(1)->add(1, 9, "View Size:");
	//wm.getWindow(1)->add(1, 10, "W:");
	//wm.getWindow(1)->addInt(4, 10, map.getViewWidth());
	//wm.getWindow(1)->add(1, 11, "H:");
	//wm.getWindow(1)->addInt(4, 11, map.getViewHeight());

	//Display PC's location
	//wm.getWindow(1)->add(1, 12, "PC Position:");
	//wm.getWindow(1)->add(1, 13, "X:     ");
	//wm.getWindow(1)->addInt(4, 13, pc_pos.x);
	//wm.getWindow(1)->add(1, 14, "Y:     ");
	//wm.getWindow(1)->addInt(4, 14, pc_pos.y);

	//Find a random FloorTile to put our kobold on
	Entity kobold = em.createEntity();
	PositionComponent npc_pos;
	SpriteComponent npc_sprite = { 'k', 0, 0 };
	spawn_npc(cave, npc_pos, pc_pos, 15);
	pos_mgr.setComponent(kobold, npc_pos);
	sprite_mgr.setComponent(kobold, npc_sprite);

	//just another entity
	Entity goblin = em.createEntity();
	PositionComponent npc2_pos;
	SpriteComponent npc2_sprite = { 'g', 0, 0 };
	spawn_npc(cave, npc2_pos, pc_pos, 15);
	pos_mgr.setComponent(goblin, npc2_pos);
	sprite_mgr.setComponent(goblin, npc2_sprite);

	//Attack skills
	SkillComponent pc_atk = { 13, 0 };
	skill_mgr.setComponent(pc, BastardSword, pc_atk);

	//Defense skills
	SkillComponent npc_dodge = { 10, 0 };
	skill_mgr.setComponent(kobold, Dodge, npc_dodge);
	SkillComponent npc2_dodge = { 10, 0 };
	skill_mgr.setComponent(goblin, Dodge, npc2_dodge);

	//Now display everything
	render.execute(em);
	display.refresh();

	//Now we enter the "game loop"
	int ch;
	int key_pos = 8;
	int last_key_pos;
	int dx, dy;
	int pc_dx, pc_dy;
	bool run = true;

	sleep(2);

	while(run)
	{
		ch = getch();

		//Display the key code
		//wm.getWindow(0)->add(key_pos, 1, "                                    ");
		//wm.getWindow(0)->addInt(key_pos, 1, ch);

		dx = 0;
		dy = 0;
		pc_dx = 0;
		pc_dy = 0;

		//wm.getWindow(0)->add(1, 1, "     ");
		last_key_pos = key_pos;
		key_pos = 8;
		switch(ch)
		{
			//Viewport movement
			case KEY_UP:
				//wm.getWindow(0)->add(1, 1, "Up");
				dy = -1;
				break;
			case KEY_DOWN:
				//wm.getWindow(0)->add(1, 1, "Down");
				dy = 1;
				break;
			case KEY_LEFT:
				//wm.getWindow(0)->add(1, 1, "Left");
				dx = -1;
				break;
			case KEY_RIGHT:
				//wm.getWindow(0)->add(1, 1, "Right");
				dx = 1;
				break;
			//Orthogonal movement
			case '8':
			case 'k':
				pc_dx = 0;
				pc_dy = -1;
				break;
			case '2':
			case 'j':
				pc_dx = 0;
				pc_dy = 1;
				break;
			case '4':
			case 'h':
				pc_dx = -1;
				pc_dy = 0;
				break;
			case '6':
			case 'l':
				pc_dx = 1;
				pc_dy = 0;
				break;
			//Diagonal movement
			case '7':
			case 'y':
				pc_dx = -1;
				pc_dy = -1;
				break;
			case '9':
			case 'u':
				pc_dx = 1;
				pc_dy = -1;
				break;
			case '1':
			case 'b':
				pc_dx = -1;
				pc_dy = 1;
				break;
			case '3':
			case 'n':
				pc_dx = 1;
				pc_dy = 1;
				break;
			//Other commands
			case 'c':
			case 'C':
				//Center the view on the PC
				display.center(map, pc_pos);
				break;
			case 'p':
			case 'P':
				//Pause ncurses (just a useless demo of the ability)
				pause_curses(display);
				break;
			case 'q':
			case 'Q':
				//Quit
				run = false;
				break;
			default:
				key_pos = last_key_pos + 4;
				if(key_pos > display.getScreenSize().x)
				{
					key_pos = 8;
				}
				break;
		}

		if(pc_dx != 0 || pc_dy != 0)
		{
			//Test if the NPC is there
			if(pos_mgr.isPositionOccupied(pc_pos.x + pc_dx, pc_pos.y + pc_dy))
			{
				//There will be a fight!
				AttackComponent atk = { pos_mgr.getEntityAtPosition(pc_pos.x + pc_dx, pc_pos.y + pc_dy), BastardSword };
				attack_mgr.setComponent(pc, atk);
			} else {
				//Move the PC
				move_pc(cave, pc_pos, pc_dx, pc_dy);
				pos_mgr.setComponent(pc, pc_pos);
			}
		}

		//Process systems in order
		sys_attack.execute(em);
		render.execute(em);

		//Respawn a fresh kobold if we need to
		if(!em.isEntityAlive(kobold))
		{
			kobold = em.createEntity();
			spawn_npc(cave, npc_pos, pc_pos, 15);
			pos_mgr.setComponent(kobold, npc_pos);
			sprite_mgr.setComponent(kobold, npc_sprite);
		}
		//Respawn a fresh goblin if we need to
		if(!em.isEntityAlive(goblin))
		{
			goblin = em.createEntity();
			spawn_npc(cave, npc2_pos, pc_pos, 15);
			pos_mgr.setComponent(goblin, npc2_pos);
			sprite_mgr.setComponent(goblin, npc2_sprite);
		}

		//Move the viewport
		display.moveBy(map, mkXYPair(dx, dy));

		//Display our view's X and Y coordinates
		//wm.getWindow(1)->add(1, 3, "X:     ");
		//wm.getWindow(1)->addInt(4, 3, map.getViewX());
		//wm.getWindow(1)->add(1, 4, "Y:     ");
		//wm.getWindow(1)->addInt(4, 4, map.getViewY());

		//Re-display PC's position
		//wm.getWindow(1)->add(1, 13, "X:     ");
		//wm.getWindow(1)->addInt(4, 13, pc_pos.x);
		//wm.getWindow(1)->add(1, 14, "Y:     ");
		//wm.getWindow(1)->addInt(4, 14, pc_pos.y);

		//Display NPC's position
		//wm.getWindow(1)->add(1, 15, "NPC Position:");
		//wm.getWindow(1)->add(1, 16, "X:     ");
		//wm.getWindow(1)->addInt(4, 16, npc_pos.x);
		//wm.getWindow(1)->add(1, 17, "Y:     ");
		//wm.getWindow(1)->addInt(4, 17, npc_pos.y);

		//wm.getWindow(1)->addInt(1, 19, pc);
		//wm.getWindow(1)->addInt(5, 19, sprite_mgr.getComponent(pc).c);
		//wm.getWindow(1)->addInt(1, 20, kobold);
		//wm.getWindow(1)->addInt(5, 20, sprite_mgr.getComponent(kobold).c);
		//wm.getWindow(1)->addInt(1, 21, goblin);
		//wm.getWindow(1)->addInt(5, 21, sprite_mgr.getComponent(goblin).c);

		//Refresh the display
		display.refresh();
	}
}
<commit_msg>Converting InterfaceTest to use Dungeon; incomplete<commit_after>#include <ncurses.h>
#include <iostream>
#include <unistd.h>
#include <algorithm>

#include "interface/Display.h"
#include "map/Dungeon.h"

#include "entity/ecs.h"

void pause_curses(Display& display)
{
	display.pause();

	std::cout << "Paused ncurses..." << std::endl;

	sleep(4);

	std::cout << "Resuming..." << std::endl;

	sleep(1);
	display.resume();
}

bool move_pc(Dungeon& dungeon, PositionComponent& pc_pos, int dx, int dy)
{
	Map level = dungeon.getMap();

	int new_x = pc_pos.x + dx;
	int new_y = pc_pos.y + dy;

	//Make sure it's in bounds
	if(0 <= new_x && new_x < level.getWidth() && 0 <= new_y && new_y < level.getHeight())
	{
		//Make sure it's passable terrain
		if(level[new_x][new_y].isPassable())
		{
			//Adjust PC's x,y coordinates
			pc_pos.x += dx;
			pc_pos.y += dy;

			return true;
		}
	}
	return false;
}

void spawn_npc(Dungeon& dungeon, PositionComponent& npc_pos, PositionComponent& pc_pos, int max_dist = 15)
{
	std::cout << "\tGetting Dungeon Map..." << std::endl;
	Map level = dungeon.getMap();

	static Rand rand(time(NULL));

	std::cout << "\tGetting min/max X..." << std::endl;
	int min_x = std::max(0, pc_pos.x - max_dist);
	int max_x = std::min(level.getWidth()-1, pc_pos.x + max_dist);

	std::cout << "\tGetting min/max Y..." << std::endl;
	int min_y = std::max(0, pc_pos.y - max_dist);
	int max_y = std::min(level.getHeight()-1, pc_pos.y + max_dist);

	std::cout << "\tPicking Tile..." << std::endl;
	do {
		npc_pos.x = rand.randInt(min_x, max_x);
		npc_pos.y = rand.randInt(min_y, max_y);
	} while(level[npc_pos.x][npc_pos.y] != FloorTile);
	std::cout << "\tAll done!" << std::endl;
}

int main()
{
	Display display;
	EntityManager em;

	//Set up our ComponentManagers
	PositionManager pos_mgr;
	SpriteManager sprite_mgr;
	SkillManager skill_mgr;
	AttackManager attack_mgr;
	em.addComponentManager(&pos_mgr);
	em.addComponentManager(&sprite_mgr);
	em.addComponentManager(&skill_mgr);
	em.addComponentManager(&attack_mgr);

	//We'll also need an AttackSystem, though no setup is necessary
	AttackSystem sys_attack;

	//XYPair screen = display.getScreenSize();

	//We'll use a simple cave Dungeon
	Dungeon cave(CaveDungeon);

	//Find a random FloorTile to put our PC on
	Entity pc = em.createEntity();
	PositionComponent pc_pos;
	SpriteComponent pc_sprite = { '@', 0, 0 };
	Rand rand(time(NULL));
	do {
		pc_pos.x = rand.randInt(0, cave.getMap().getWidth()-1);
		pc_pos.y = rand.randInt(0, cave.getMap().getHeight()-1);
	} while(cave.getMap()[pc_pos.x][pc_pos.y] != FloorTile);
	pos_mgr.setComponent(pc, pc_pos);
	sprite_mgr.setComponent(pc, pc_sprite);

	//Now create a Window and viewport for our level
	WindowGeometry map_geometry = { {20,3}, {AUTO_SIZE, AUTO_SIZE} };
	Window map = display.addWindow(cave.getMap(), map_geometry);

	//Geometries for our top and left Windows
	WindowGeometry top_geometry = { {0,0}, {AUTO_SIZE, 3} };
	WindowGeometry left_geometry = { { 0, 3 }, {20, AUTO_SIZE} };
	//And now create them
	Window top = display.addWindow(top_geometry);
	Window left = display.addWindow(left_geometry);

	//top.addBorder();
	//left.addBorder();

	//New set up our RenderSystem
	RenderSystem render(&display, map);

	display.pause();
	std::cout << "About to add titles..." << std::endl;
	display.add(top, mkXYPair(1,0), "Message Panel");
	display.add(left, mkXYPair(1,0), "Stat Panel");
	std::cout << "Added titles..." << std::endl;

	//Center the map viewport on the PC
	std::cout << "About to center viewport..." << std::endl;
	display.center(map, pc_pos);
	std::cout << "Centered viewport..." << std::endl;

	//Let's display some map display stats
	//Display our view's X and Y coordinates
	//wm.getWindow(1)->add(1, 2, "View Position:");
	//wm.getWindow(1)->add(1, 3, "X:     ");
	//wm.getWindow(1)->addInt(4, 3, map.getViewX());
	//wm.getWindow(1)->add(1, 4, "Y:     ");
	//wm.getWindow(1)->addInt(4, 4, map.getViewY());

	//Display map size
	//wm.getWindow(1)->add(1, 6, "Map Size:");
	//wm.getWindow(1)->add(1, 7, "W:");
	//wm.getWindow(1)->addInt(4, 7, cave.getWidth());
	//wm.getWindow(1)->add(1, 8, "H:");
	//wm.getWindow(1)->addInt(4, 8, cave.getHeight());

	//Display viewport size
	//wm.getWindow(1)->add(1, 9, "View Size:");
	//wm.getWindow(1)->add(1, 10, "W:");
	//wm.getWindow(1)->addInt(4, 10, map.getViewWidth());
	//wm.getWindow(1)->add(1, 11, "H:");
	//wm.getWindow(1)->addInt(4, 11, map.getViewHeight());

	//Display PC's location
	//wm.getWindow(1)->add(1, 12, "PC Position:");
	//wm.getWindow(1)->add(1, 13, "X:     ");
	//wm.getWindow(1)->addInt(4, 13, pc_pos.x);
	//wm.getWindow(1)->add(1, 14, "Y:     ");
	//wm.getWindow(1)->addInt(4, 14, pc_pos.y);

	//Find a random FloorTile to put our kobold on
	Entity kobold = em.createEntity();
	PositionComponent npc_pos;
	SpriteComponent npc_sprite = { 'k', 0, 0 };
	std::cout << "About to spawn kobold..." << std::endl;
	spawn_npc(cave, npc_pos, pc_pos, 15);
	pos_mgr.setComponent(kobold, npc_pos);
	sprite_mgr.setComponent(kobold, npc_sprite);

	//just another entity
	Entity goblin = em.createEntity();
	PositionComponent npc2_pos;
	SpriteComponent npc2_sprite = { 'g', 0, 0 };
	std::cout << "About to spawn goblin..." << std::endl;
	sleep(1);
	spawn_npc(cave, npc2_pos, pc_pos, 15);
	sleep(1);
	std::cout << "Spawned goblin" << std::endl;
	pos_mgr.setComponent(goblin, npc2_pos);
	sprite_mgr.setComponent(goblin, npc2_sprite);
	sleep(1);

	//Attack skills
	std::cout << "Setting PC attack skill..." << std::endl;
	SkillComponent pc_atk = { 13, 0 };
	skill_mgr.setComponent(pc, BastardSword, pc_atk);

	//Defense skills
	std::cout << "Setting NPC defense skills..." << std::endl;
	SkillComponent npc_dodge = { 10, 0 };
	skill_mgr.setComponent(kobold, Dodge, npc_dodge);
	SkillComponent npc2_dodge = { 10, 0 };
	skill_mgr.setComponent(goblin, Dodge, npc2_dodge);

	//Now display everything
	std::cout << "About to render and refresh..." << std::endl;
	render.execute(em);
	display.refresh();

	//Now we enter the "game loop"
	int ch;
	int key_pos = 8;
	int last_key_pos;
	int dx, dy;
	int pc_dx, pc_dy;
	bool run = true;

	sleep(2);

	while(run)
	{
		ch = getch();

		//Display the key code
		//wm.getWindow(0)->add(key_pos, 1, "                                    ");
		//wm.getWindow(0)->addInt(key_pos, 1, ch);

		dx = 0;
		dy = 0;
		pc_dx = 0;
		pc_dy = 0;

		//wm.getWindow(0)->add(1, 1, "     ");
		last_key_pos = key_pos;
		key_pos = 8;
		switch(ch)
		{
			//Viewport movement
			case KEY_UP:
				//wm.getWindow(0)->add(1, 1, "Up");
				dy = -1;
				break;
			case KEY_DOWN:
				//wm.getWindow(0)->add(1, 1, "Down");
				dy = 1;
				break;
			case KEY_LEFT:
				//wm.getWindow(0)->add(1, 1, "Left");
				dx = -1;
				break;
			case KEY_RIGHT:
				//wm.getWindow(0)->add(1, 1, "Right");
				dx = 1;
				break;
			//Orthogonal movement
			case '8':
			case 'k':
				pc_dx = 0;
				pc_dy = -1;
				break;
			case '2':
			case 'j':
				pc_dx = 0;
				pc_dy = 1;
				break;
			case '4':
			case 'h':
				pc_dx = -1;
				pc_dy = 0;
				break;
			case '6':
			case 'l':
				pc_dx = 1;
				pc_dy = 0;
				break;
			//Diagonal movement
			case '7':
			case 'y':
				pc_dx = -1;
				pc_dy = -1;
				break;
			case '9':
			case 'u':
				pc_dx = 1;
				pc_dy = -1;
				break;
			case '1':
			case 'b':
				pc_dx = -1;
				pc_dy = 1;
				break;
			case '3':
			case 'n':
				pc_dx = 1;
				pc_dy = 1;
				break;
			//Other commands
			case 'c':
			case 'C':
				//Center the view on the PC
				display.center(map, pc_pos);
				break;
			case 'p':
			case 'P':
				//Pause ncurses (just a useless demo of the ability)
				pause_curses(display);
				break;
			case 'q':
			case 'Q':
				//Quit
				run = false;
				break;
			default:
				key_pos = last_key_pos + 4;
				if(key_pos > display.getScreenSize().x)
				{
					key_pos = 8;
				}
				break;
		}

		if(pc_dx != 0 || pc_dy != 0)
		{
			//Test if the NPC is there
			if(pos_mgr.isPositionOccupied(pc_pos.x + pc_dx, pc_pos.y + pc_dy))
			{
				//There will be a fight!
				AttackComponent atk = { pos_mgr.getEntityAtPosition(pc_pos.x + pc_dx, pc_pos.y + pc_dy), BastardSword };
				attack_mgr.setComponent(pc, atk);
			} else {
				//Move the PC
				move_pc(cave, pc_pos, pc_dx, pc_dy);
				pos_mgr.setComponent(pc, pc_pos);
			}
		}

		//Process systems in order
		sys_attack.execute(em);
		render.execute(em);

		//Respawn a fresh kobold if we need to
		if(!em.isEntityAlive(kobold))
		{
			kobold = em.createEntity();
			spawn_npc(cave, npc_pos, pc_pos, 15);
			pos_mgr.setComponent(kobold, npc_pos);
			sprite_mgr.setComponent(kobold, npc_sprite);
		}
		//Respawn a fresh goblin if we need to
		if(!em.isEntityAlive(goblin))
		{
			goblin = em.createEntity();
			spawn_npc(cave, npc2_pos, pc_pos, 15);
			pos_mgr.setComponent(goblin, npc2_pos);
			sprite_mgr.setComponent(goblin, npc2_sprite);
		}

		//Move the viewport
		display.moveBy(map, mkXYPair(dx, dy));

		//Display our view's X and Y coordinates
		//wm.getWindow(1)->add(1, 3, "X:     ");
		//wm.getWindow(1)->addInt(4, 3, map.getViewX());
		//wm.getWindow(1)->add(1, 4, "Y:     ");
		//wm.getWindow(1)->addInt(4, 4, map.getViewY());

		//Re-display PC's position
		//wm.getWindow(1)->add(1, 13, "X:     ");
		//wm.getWindow(1)->addInt(4, 13, pc_pos.x);
		//wm.getWindow(1)->add(1, 14, "Y:     ");
		//wm.getWindow(1)->addInt(4, 14, pc_pos.y);

		//Display NPC's position
		//wm.getWindow(1)->add(1, 15, "NPC Position:");
		//wm.getWindow(1)->add(1, 16, "X:     ");
		//wm.getWindow(1)->addInt(4, 16, npc_pos.x);
		//wm.getWindow(1)->add(1, 17, "Y:     ");
		//wm.getWindow(1)->addInt(4, 17, npc_pos.y);

		//wm.getWindow(1)->addInt(1, 19, pc);
		//wm.getWindow(1)->addInt(5, 19, sprite_mgr.getComponent(pc).c);
		//wm.getWindow(1)->addInt(1, 20, kobold);
		//wm.getWindow(1)->addInt(5, 20, sprite_mgr.getComponent(kobold).c);
		//wm.getWindow(1)->addInt(1, 21, goblin);
		//wm.getWindow(1)->addInt(5, 21, sprite_mgr.getComponent(goblin).c);

		//Refresh the display
		display.refresh();
	}
}
<|endoftext|>