<commit_before>//
//  hopf.cpp
//  allovsr
//
//  Created by Pablo Colapinto on 11/28/12.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

//vsr Includes
#include "vsr/vsr.h"
#include "vsr/vsr_op.h"
#include "vsr/vsr_draw.h"
#include "vsr/vsr_camera.h"
#include "vsr/vsr_fiber.h"
#include "vsr/vsr_stat.h"
//#include "vsr/vsr_gamma.h"

//allo includes
#include "allocore/al_Allocore.hpp"
#include "allocore/io/al_ControlNav.hpp"
#include "alloGLV/al_ControlGLV.hpp"

//gamma
//#include "Gamma/Oscillator.h"

//Glue
#include "allovsr/al_vsrInterface.hpp"
#include <iostream>

using namespace al;
using namespace vsr;

#define PRESET \
    static bool bSet = 0;\
    if (!bSet) { \
        bSet = 1;

void knot(al::VsrApp& app){

    // 3-Sphere

    HopfFiber hf;

    // Gamma
//    static gam::LFO<> ramp(1);  GfxSync::master() << ramp;
//    double tramp = .5 + ramp.up2();

    /////////
    /* GUI */
    /////////

    static double m,n,amt,iter;
    static double theta, phi, gamma; //ANGLES of POLES and INITIAL CIRCLE
    static double ntrace, traceamt, bandres;
    static bool bReset, bCirFlow, bDrawCirStrip, bDrawStrip, bDrawSrc;

    PRESET
        app.glv.gui(m,"m",0,10)(n,"n",0,10)(amt,"amt",-10,10)(iter,"iter",1,1000);
        app.glv.gui(theta)(phi)(gamma);
        app.glv.gui(ntrace,"trace",0,1000)(traceamt,"trace_amt",0,10)(bandres,"band_res",0,100);
        app.glv.gui(bReset,"reset")(bCirFlow,"cirFlow")(bDrawCirStrip,"cir_strip")(bDrawStrip, "strip")(bDrawSrc, "src");
        m = 1; n = 5; amt = .005; iter = 1000; ntrace = 10; traceamt = .1;
    }

    /////////////////////////////////
    /* The Transformation Operator */
    /////////////////////////////////

    //HOPF LINKS at Poles (orthogonal)
    vector<Cir> cp = hf.poles(-1 + theta * 2,phi);

    //A Point Pair "Boost" Generator . . .
    PointPair tp = cp[0].dual() * PI/m + cp[1].dual() * PI/n;

    //A Boost
    Bst bst = Gen::bst( tp*amt ) ;
    //Another Boost
    Bst bst2 = Gen::bst( tp*amt*traceamt );

    //POINTS ALONG KNOT

    //A Point you can Touch
    static Point pt = PT(1,0,0);
    app.interface.touch(pt);

    //dp/dt
    vector<Pnt> vp;
    Point np = pt;
    for (int i = 0; i < iter; ++i){
        np = Ro::loc( np.sp( bst ) );           //Extracts Location Each time with Ro::loc
        vp.push_back(np);
    }

    //CIRCLES ALONG THE KNOT

    //A Circle at point
    Circle ct = Ro::cir( pt, Biv::yz  + Biv::xy * gamma * PI, .2);

    vector<Cir> cirp;
    Circle ncirp = ct;
    for (int i = 0; i < iter; ++i){
        ncirp = ncirp.sp( Gen::bst( tp*amt ) ); // Does not Extract Location (so is not stable)
        cirp.push_back(ncirp);
    }

    //////////////////////
    // FLOW //////////////
    //////////////////////

    //Generate Random points, Random Circles

    static vector<Pnt> rp;  //  Points Flow
    static vector<Cir> scp; //  Circle Flow
    static vector<Pnt> bp;  //  Band of Points Flow

    if (bReset){

        rp.clear(); scp.clear(); bp.clear();
        Rand::Seed(10);
        for (int i = 0; i < iter; ++i){

            //Random Point
            double x = Rand::Num(-1,1);
            double y = Rand::Num(-.5,.5);
            double z = Rand::Num(-1,1);
            Pnt p = Vector(x,y,z).null();
            rp.push_back( p );

            //Random Circle
            Biv biv( Rand::Num(), Rand::Num(), Rand::Num());
            Cir tcir = Ro::cir(p, biv.unit(), .1);
            scp.push_back( tcir );

            for (int j = 0; j < bandres; ++j){
                double t = 1.0 * j/bandres;
                bp.push_back( Ro::pnt_cir( tcir, t * PI) );
            }
        }
    }

    //////////////////////
    // Draw Flow    //////
    //////////////////////

    //Modular Flow of Points
    for (int i = 0; i < rp.size(); ++i){
        double t = 1.0 * i/rp.size();
        Pnt np =  Ro::loc( rp[i].sp( bst ) ) ;
        rp[i] = np;
        for (int j = 0; j < ntrace; ++j){
            double jt = 1.0 * j/ntrace;
            np =  Ro::loc( np.sp( bst2 ) ) ;
            DRAW4(np,t,jt,1-t,1-jt);
        }
    }

    //Switch Circular or Band of Points

    if (bCirFlow){
        //Modular Flow of Circles
        for (int i = 0; i < scp.size(); ++i){
            double t = 1.0 * i/ cirp.size();
            Cir np =  scp[i].sp( bst ) ;
            scp[i] = np;
            for (int j = 0; j < ntrace; ++j){
                double jt = 1.0 * j/ntrace;
                np =  np.sp( bst2 ) ;
                DRAW4(np,t,jt,1-t,1-jt);
            }
        }
    } else {
        //Modular Flow of Band of points
        for (int i = 0; i < bp.size(); ++i){
            double t = 1.0 * i / cirp.size();
            Pnt np =  Ro::loc( bp[i].sp( bst ) );
            bp[i] = np;
            for (int j = 0; j < ntrace; ++j){
                double jt = 1.0 * j/ntrace;
                np =  Ro::loc( np.sp( bst2 ) ) ;
                DRAW4(np,t,jt,1-t,1-jt);
            }
        }
    }

    if (bDrawSrc){
        //Draw the Point
        DRAW3(pt,1,0,0);
        //Draw Polar Circles (Hopf Links)
        DRAW(cp[0]); DRAW(cp[1]);
    }

    if (bDrawStrip){
        //DRAW the Knot Strip
        glBegin(GL_LINE_STRIP);
            for (int i = 0; i < vp.size(); ++i){
                GL::vertex(vp[i].w());
            }
        glEnd();
    }

    if (bDrawCirStrip){
        //DRAW the Circle Knot Strip
        for (int i = 0; i < cirp.size(); ++i){
            DRAW3( cirp[i],0,1,0 );
        }
    }

}

class MyApp : public al::VsrApp {

    public:

    MyApp() : al::VsrApp() {

        stereo.stereo(true);
        stereo.mode( Stereographic::ACTIVE );

	lens.eyeSep(lens.eyeSepAuto() *-1);
        //cout << lens.eyeSep() << endl;
	//displayMode ( DEFAULT_BUF | STEREO_BUF );
    }

    virtual void onDraw(Graphics& gl){

        //Model Transform
        Rot t = Gen::aa( scene().model.rot() );
        GL::rotate( t.w() );

        knot(*this);
    }

};

MyApp app;

int main(int argc, const char * argv[]){

    app.create(Window::Dim(800, 600), "Allovsr Demo: Hopf Fibration", 60, Window::DEFAULT_BUF | Window::STEREO_BUF);
    //app.lens.eyeSep( app.lens.eyeSepAuto() );
    cout << app.lens.eyeSep() << endl;
    MainLoop::start();

	return 0;

}
<commit_msg>allovsr knot demo<commit_after>//
//  hopf.cpp
//  allovsr
//
//  Created by Pablo Colapinto on 11/28/12.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

//vsr Includes
#include "vsr/vsr.h"
#include "vsr/vsr_op.h"
#include "vsr/vsr_draw.h"
#include "vsr/vsr_camera.h"
#include "vsr/vsr_fiber.h"
#include "vsr/vsr_stat.h"
//#include "vsr/vsr_gamma.h"

//allo includes
#include "allocore/al_Allocore.hpp"
#include "allocore/io/al_ControlNav.hpp"
#include "alloGLV/al_ControlGLV.hpp"

//gamma
//#include "Gamma/Oscillator.h"

//Glue
#include "allovsr/al_vsrInterface.hpp"
#include <iostream>

using namespace al;
using namespace vsr;

#define PRESET \
    static bool bSet = 0;\
    if (!bSet) { \
        bSet = 1;

void knot(al::VsrApp& app){

    // 3-Sphere

    HopfFiber hf;

    // Gamma
//    static gam::LFO<> ramp(1);  GfxSync::master() << ramp;
//    double tramp = .5 + ramp.up2();

    /////////
    /* GUI */
    /////////

    static double m,n,amt,iter;
    static double theta, phi, gamma; //ANGLES of POLES and INITIAL CIRCLE
    static double ntrace, traceamt, bandres;
    static bool bReset, bCirFlow, bDrawCirStrip, bDrawStrip, bDrawSrc;

	//stereo controls
	static double eyesep, fovy;

    PRESET
        app.glv.gui(m,"m",0,10)(n,"n",0,10)(amt,"amt",-10,10)(iter,"iter",1,1000);
        app.glv.gui(theta)(phi)(gamma);
        app.glv.gui(ntrace,"trace",0,1000)(traceamt,"trace_amt",0,10)(bandres,"band_res",0,100);
        app.glv.gui(bReset,"reset")(bCirFlow,"cirFlow")(bDrawCirStrip,"cir_strip")(bDrawStrip, "strip")(bDrawSrc, "src");
	app.glv.gui(eyesep,"eyesep",0,2)(fovy,"fovy",0,180);
        m = 1; n = 5; amt = .005; iter = 1000; ntrace = 10; traceamt = .1;
	eyesep = .2; fovy = 45;
    }

	app.lens.eyeSep(eyesep*-1); app.lens.fovy(fovy);

    /////////////////////////////////
    /* The Transformation Operator */
    /////////////////////////////////

    //HOPF LINKS at Poles (orthogonal)
    vector<Cir> cp = hf.poles(-1 + theta * 2,phi);

    //A Point Pair "Boost" Generator . . .
    PointPair tp = cp[0].dual() * PI/m + cp[1].dual() * PI/n;

    //A Boost
    Bst bst = Gen::bst( tp*amt ) ;
    //Another Boost
    Bst bst2 = Gen::bst( tp*amt*traceamt );

    //POINTS ALONG KNOT

    //A Point you can Touch
    static Point pt = PT(1,0,0);
    app.interface.touch(pt);

    //dp/dt
    vector<Pnt> vp;
    Point np = pt;
    for (int i = 0; i < iter; ++i){
        np = Ro::loc( np.sp( bst ) );           //Extracts Location Each time with Ro::loc
        vp.push_back(np);
    }

    //CIRCLES ALONG THE KNOT

    //A Circle at point
    Circle ct = Ro::cir( pt, Biv::yz  + Biv::xy * gamma * PI, .2);

    vector<Cir> cirp;
    Circle ncirp = ct;
    for (int i = 0; i < iter; ++i){
        ncirp = ncirp.sp( Gen::bst( tp*amt ) ); // Does not Extract Location (so is not stable)
        cirp.push_back(ncirp);
    }

    //////////////////////
    // FLOW //////////////
    //////////////////////

    //Generate Random points, Random Circles

    static vector<Pnt> rp;  //  Points Flow
    static vector<Cir> scp; //  Circle Flow
    static vector<Pnt> bp;  //  Band of Points Flow

    if (bReset){

        rp.clear(); scp.clear(); bp.clear();
        Rand::Seed(10);
        for (int i = 0; i < iter; ++i){

            //Random Point
            double x = Rand::Num(-1,1);
            double y = Rand::Num(-.5,.5);
            double z = Rand::Num(-1,1);
            Pnt p = Vector(x,y,z).null();
            rp.push_back( p );

            //Random Circle
            Biv biv( Rand::Num(), Rand::Num(), Rand::Num());
            Cir tcir = Ro::cir(p, biv.unit(), .1);
            scp.push_back( tcir );

            for (int j = 0; j < bandres; ++j){
                double t = 1.0 * j/bandres;
                bp.push_back( Ro::pnt_cir( tcir, t * PI) );
            }
        }
    }

    //////////////////////
    // Draw Flow    //////
    //////////////////////

    //Modular Flow of Points
    for (int i = 0; i < rp.size(); ++i){
        double t = 1.0 * i/rp.size();
        Pnt np =  Ro::loc( rp[i].sp( bst ) ) ;
        rp[i] = np;
        for (int j = 0; j < ntrace; ++j){
            double jt = 1.0 * j/ntrace;
            np =  Ro::loc( np.sp( bst2 ) ) ;
            DRAW4(np,t,jt,1-t,1-jt);
        }
    }

    //Switch Circular or Band of Points

    if (bCirFlow){
        //Modular Flow of Circles
        for (int i = 0; i < scp.size(); ++i){
            double t = 1.0 * i/ cirp.size();
            Cir np =  scp[i].sp( bst ) ;
            scp[i] = np;
            for (int j = 0; j < ntrace; ++j){
                double jt = 1.0 * j/ntrace;
                np =  np.sp( bst2 ) ;
                DRAW4(np,t,jt,1-t,1-jt);
            }
        }
    } else {
        //Modular Flow of Band of points
        for (int i = 0; i < bp.size(); ++i){
            double t = 1.0 * i / cirp.size();
            Pnt np =  Ro::loc( bp[i].sp( bst ) );
            bp[i] = np;
            for (int j = 0; j < ntrace; ++j){
                double jt = 1.0 * j/ntrace;
                np =  Ro::loc( np.sp( bst2 ) ) ;
                DRAW4(np,t,jt,1-t,1-jt);
            }
        }
    }

    if (bDrawSrc){
        //Draw the Point
        DRAW3(pt,1,0,0);
        //Draw Polar Circles (Hopf Links)
        DRAW(cp[0]); DRAW(cp[1]);
    }

    if (bDrawStrip){
        //DRAW the Knot Strip
        glBegin(GL_LINE_STRIP);
            for (int i = 0; i < vp.size(); ++i){
                GL::vertex(vp[i].w());
            }
        glEnd();
    }

    if (bDrawCirStrip){
        //DRAW the Circle Knot Strip
        for (int i = 0; i < cirp.size(); ++i){
            DRAW3( cirp[i],0,1,0 );
        }
    }

}

class MyApp : public al::VsrApp {

    public:

    MyApp() : al::VsrApp() {

        stereo.stereo(true);
        stereo.mode( Stereographic::ACTIVE );

	lens.fovy(45);
	lens.eyeSep(lens.eyeSepAuto() *-1);
        //cout << lens.eyeSep() << endl;
	//displayMode ( DEFAULT_BUF | STEREO_BUF );
    }

    virtual void onDraw(Graphics& gl){

        //Model Transform
        Rot t = Gen::aa( scene().model.rot() );
        GL::rotate( t.w() );

        knot(*this);
    }

};

MyApp app;

int main(int argc, const char * argv[]){

    app.create(Window::Dim(800, 600), "Allovsr Demo: Hopf Fibration", 60, Window::DEFAULT_BUF | Window::STEREO_BUF);
    //app.lens.eyeSep( app.lens.eyeSepAuto() );
    cout << app.lens.eyeSep() << endl;
    MainLoop::start();

	return 0;

}
<|endoftext|>


<commit_before>//
// Created by dar on 11/27/15.
//

#include "Game.h"

Game::Game(Core *core) : core(core), renderer(core) {
}

void Game::run() {
    this->renderer.init();
    SDL_StartTextInput();
    double deltaTime = timer.GetDelta();
    double accumulator = 0.0;
    while (this->core->isRunning()) {
        deltaTime = timer.GetDelta();
        accumulator += deltaTime;
        while (accumulator > TIME_STEP) {
            this->update();
            accumulator -= TIME_STEP;
        }
        this->renderer.run();
    }
    SDL_StopTextInput();
}

void Game::update() {
    for (int i = 0; i < 256; i++) {
        if (this->pressDelays[i] > 0) this->pressDelays[i]--;
    }
    handleKeyboard();
    SDL_Event e;
    while (SDL_PollEvent(&e) != 0) {
        switch (e.type) {
            case SDL_QUIT:
                this->core->stop();
                break;
            case SDL_WINDOWEVENT:
                if (e.window.event == SDL_WINDOWEVENT_RESIZED || e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
                    this->renderer.resize((unsigned int) e.window.data1, (unsigned int) e.window.data2);
                }
                break;
            case SDL_KEYDOWN:
            case SDL_KEYUP:
                if (e.key.repeat == 0)
                    handleKeypress(e);
                break;
        }
    }
    this->core->getMap()->update();
    this->core->getMap()->getWorld()->Step(TIME_STEP, 8, 3);
    for (int i = 0; i < this->core->getMap()->getEntities().size(); i++) {
        Entity *entity = this->core->getMap()->getEntities().at(i);
        if (entity->isToBeDeleted()) {
            this->core->getMap()->removeEntity(entity);
            i--;

        }
    }
    this->core->setCamX(-this->core->getCamX() + (this->core->getPlayer()->getX() * this->core->getBlockSize() * this->core->getGeneralScale() + this->core->getCamX()) * 0.05);
    this->core->setCamY(-this->core->getCamY() + (this->core->getPlayer()->getY() * this->core->getBlockSize() * this->core->getGeneralScale() + this->core->getCamY()) * 0.05);
}

void Game::handleKeyboard() {
    float SPEED = 1.0f;
    const Uint8 *keystate = SDL_GetKeyboardState(NULL);
    if (keystate[SDL_SCANCODE_W]) {
        this->core->getPlayer()->setVelY(-SPEED);
    }
    if (keystate[SDL_SCANCODE_S]) {
        this->core->getPlayer()->setVelY(SPEED);
    }
    if (keystate[SDL_SCANCODE_A]) {
        this->core->getPlayer()->setVelX(-SPEED);
    }
    if (keystate[SDL_SCANCODE_D]) {
        this->core->getPlayer()->setVelX(SPEED);
    }
    if (keystate[SDL_SCANCODE_Q]) {
        this->core->stop();
    }
    if (keystate[SDL_SCANCODE_MINUS]) {
        this->core->setBlockSize(this->core->getBlockSize() - 0.15);
    }
    if (keystate[SDL_SCANCODE_EQUALS]) {
        this->core->setBlockSize(this->core->getBlockSize() + 0.15);
    }
}

void Game::handleKeypress(SDL_Event event) {
    switch (event.type) {
        case SDL_KEYDOWN: {
            SDL_Keycode key = event.key.keysym.sym;
            unsigned char delay_tmp = 255;
            static int TELEPORT_DELAY = 255 - 25;
            switch (key) {
                case SDLK_a:
                    if (this->pressDelays[event.key.keysym.sym] > TELEPORT_DELAY) {
                        this->core->getPlayer()->teleport(-1.95, 0);
                        delay_tmp = 0, resetMovementPressDelays();
                    }
                    break;
                case SDLK_d:
                    if (this->pressDelays[event.key.keysym.sym] > TELEPORT_DELAY) {
                        this->core->getPlayer()->teleport(1.95, 0);
                        delay_tmp = 0, resetMovementPressDelays();
                    }
                    break;
                case SDLK_w:
                    if (this->pressDelays[event.key.keysym.sym] > TELEPORT_DELAY) {
                        this->core->getPlayer()->teleport(0, -1.95);
                        delay_tmp = 0, resetMovementPressDelays();
                    }
                    break;
                case SDLK_s:
                    if (this->pressDelays[event.key.keysym.sym] > TELEPORT_DELAY) {
                        this->core->getPlayer()->teleport(0, 1.95);
                        delay_tmp = 0, resetMovementPressDelays();
                    }
                    break;
                case SDLK_c: {
                    double angle = atan2(this->core->getPlayer()->getVelY(), this->core->getPlayer()->getVelX()) + M_PI;
                    EntityBullet *p = new EntityBullet(this->core, angle, 1);
                    p->setX(this->core->getPlayer()->getX() - (this->core->getPlayer()->getWidth() - p->getWidth()) / 2 + 0.5 * cos(angle));
                    p->setY(this->core->getPlayer()->getY() - (this->core->getPlayer()->getHeight() - p->getHeight()) / 2 + 0.5 * sin(angle));
                    this->core->getMap()->addEntity(p);
                    break;
                }
                default:
                    break;
            }
            if (event.key.keysym.sym >= 0 && event.key.keysym.sym < 256)
                this->pressDelays[event.key.keysym.sym] = delay_tmp;
            break;
        }
        case SDL_KEYUP:
            break;

        default:
            break;
    }
}

void Game::resetMovementPressDelays() {
    this->pressDelays[SDLK_a] = this->pressDelays[SDLK_d] = this->pressDelays[SDLK_w] = this->pressDelays[SDLK_s] = 0;
}

Game::~Game() {
    delete this->core;
}
<commit_msg>Added player spawning with N key (for demo purpose)<commit_after>//
// Created by dar on 11/27/15.
//

#include "Game.h"

Game::Game(Core *core) : core(core), renderer(core) {
}

void Game::run() {
    this->renderer.init();
    SDL_StartTextInput();
    double deltaTime = timer.GetDelta();
    double accumulator = 0.0;
    while (this->core->isRunning()) {
        deltaTime = timer.GetDelta();
        accumulator += deltaTime;
        while (accumulator > TIME_STEP) {
            this->update();
            accumulator -= TIME_STEP;
        }
        this->renderer.run();
    }
    SDL_StopTextInput();
}

void Game::update() {
    for (int i = 0; i < 256; i++) {
        if (this->pressDelays[i] > 0) this->pressDelays[i]--;
    }
    handleKeyboard();
    SDL_Event e;
    while (SDL_PollEvent(&e) != 0) {
        switch (e.type) {
            case SDL_QUIT:
                this->core->stop();
                break;
            case SDL_WINDOWEVENT:
                if (e.window.event == SDL_WINDOWEVENT_RESIZED || e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
                    this->renderer.resize((unsigned int) e.window.data1, (unsigned int) e.window.data2);
                }
                break;
            case SDL_KEYDOWN:
            case SDL_KEYUP:
                if (e.key.repeat == 0)
                    handleKeypress(e);
                break;
        }
    }
    this->core->getMap()->update();
    this->core->getMap()->getWorld()->Step(TIME_STEP, 8, 3);
    for (int i = 0; i < this->core->getMap()->getEntities().size(); i++) {
        Entity *entity = this->core->getMap()->getEntities().at(i);
        if (entity->isToBeDeleted()) {
            this->core->getMap()->removeEntity(entity);
            i--;

        }
    }
    this->core->setCamX(-this->core->getCamX() + (this->core->getPlayer()->getX() * this->core->getBlockSize() * this->core->getGeneralScale() + this->core->getCamX()) * 0.05);
    this->core->setCamY(-this->core->getCamY() + (this->core->getPlayer()->getY() * this->core->getBlockSize() * this->core->getGeneralScale() + this->core->getCamY()) * 0.05);
}

void Game::handleKeyboard() {
    float SPEED = 1.0f;
    const Uint8 *keystate = SDL_GetKeyboardState(NULL);
    if (keystate[SDL_SCANCODE_W]) {
        this->core->getPlayer()->setVelY(-SPEED);
    }
    if (keystate[SDL_SCANCODE_S]) {
        this->core->getPlayer()->setVelY(SPEED);
    }
    if (keystate[SDL_SCANCODE_A]) {
        this->core->getPlayer()->setVelX(-SPEED);
    }
    if (keystate[SDL_SCANCODE_D]) {
        this->core->getPlayer()->setVelX(SPEED);
    }
    if (keystate[SDL_SCANCODE_Q]) {
        this->core->stop();
    }
    if (keystate[SDL_SCANCODE_MINUS]) {
        this->core->setBlockSize(this->core->getBlockSize() - 0.15);
    }
    if (keystate[SDL_SCANCODE_EQUALS]) {
        this->core->setBlockSize(this->core->getBlockSize() + 0.15);
    }
}

void Game::handleKeypress(SDL_Event event) {
    switch (event.type) {
        case SDL_KEYDOWN: {
            SDL_Keycode key = event.key.keysym.sym;
            unsigned char delay_tmp = 255;
            static int TELEPORT_DELAY = 255 - 25;
            switch (key) {
                case SDLK_a:
                    if (this->pressDelays[event.key.keysym.sym] > TELEPORT_DELAY) {
                        this->core->getPlayer()->teleport(-1.95, 0);
                        delay_tmp = 0, resetMovementPressDelays();
                    }
                    break;
                case SDLK_d:
                    if (this->pressDelays[event.key.keysym.sym] > TELEPORT_DELAY) {
                        this->core->getPlayer()->teleport(1.95, 0);
                        delay_tmp = 0, resetMovementPressDelays();
                    }
                    break;
                case SDLK_w:
                    if (this->pressDelays[event.key.keysym.sym] > TELEPORT_DELAY) {
                        this->core->getPlayer()->teleport(0, -1.95);
                        delay_tmp = 0, resetMovementPressDelays();
                    }
                    break;
                case SDLK_s:
                    if (this->pressDelays[event.key.keysym.sym] > TELEPORT_DELAY) {
                        this->core->getPlayer()->teleport(0, 1.95);
                        delay_tmp = 0, resetMovementPressDelays();
                    }
                    break;
                case SDLK_c: {
                    double angle = atan2(this->core->getPlayer()->getVelY(), this->core->getPlayer()->getVelX()) + M_PI;
                    EntityBullet *p = new EntityBullet(this->core, angle, 1);
                    p->setX(this->core->getPlayer()->getX() - (this->core->getPlayer()->getWidth() - p->getWidth()) / 2 + 0.5 * cos(angle));
                    p->setY(this->core->getPlayer()->getY() - (this->core->getPlayer()->getHeight() - p->getHeight()) / 2 + 0.5 * sin(angle));
                    this->core->getMap()->addEntity(p);
                    break;
                }
                case SDLK_n: {
                    Player *p = new Player(this->core);
                    p->setX(this->core->getPlayer()->getX() - this->core->getPlayer()->getWidth() / 2);
                    p->setY(this->core->getPlayer()->getY() - this->core->getPlayer()->getHeight() / 2);
                    this->core->getMap()->addEntity(p);
                    break;
                }
                default:
                    break;
            }
            if (event.key.keysym.sym >= 0 && event.key.keysym.sym < 256)
                this->pressDelays[event.key.keysym.sym] = delay_tmp;
            break;
        }
        case SDL_KEYUP:
            break;

        default:
            break;
    }
}

void Game::resetMovementPressDelays() {
    this->pressDelays[SDLK_a] = this->pressDelays[SDLK_d] = this->pressDelays[SDLK_w] = this->pressDelays[SDLK_s] = 0;
}

Game::~Game() {
    delete this->core;
}
<|endoftext|>


<commit_before>
#include <vector>
#include <fstream>
#include <iostream>

#include "../include/Grid.hpp"
#include "../include/Utils.hpp"

Grid::Grid() {}

const bool Grid::loadFromFile(const std::string& fileName) {
  unsigned int height, width;

  if (std::ifstream fs{fileName}) {
    fs >> height >> width;
    colClues.resize(height);
    rowClues.resize(width);
    grid.resize(height);

    for (unsigned int i = 0; i < height; ++i)
      grid[i].resize(width);

    {
      int value, lineNumber = 1;
      std::string line;

      while (std::getline(fs, line)) {
        if (lineNumber > 1) { // If the line isn't the first one (which is <height width>)
          std::vector<std::string> vals;

          if (lineNumber == 2) { // Second line is column's
            /* Filling columns' clues */
            Utils::split(line, ';', vals);

            for (unsigned int i = 0; i < vals.size(); ++i) {
              std::stringstream ss{vals[i]};
              while (ss >> value)
                colClues[i].push_back(value);
            }
          } else if (lineNumber == 3) { // Third line is row's
            /* Filling rows' clues */
            Utils::split(line, ';', vals);

            for (unsigned int i = 0; i < vals.size(); ++i) {
              std::stringstream ss{vals[i]};
              while (ss >> value)
                rowClues[i].push_back(value);
            }
          } // End of if (lineNumber == 3)
        } // End of if (lineNumber > 1)
        lineNumber++;
      } // End of while (std::getline(fs, line)))
    }
  } else { // If the file couldn't have been opened
    return false;
  }
  return true;
}

Grid& Grid::solve() { return *this; }

std::ostream& operator<<(std::ostream& os, const Grid& grid) {
  // For each entry in rows' clues, prints two spaces to make a margin (plus two for the starting '[ ')
  // Ideally, should get the entry with maximum number of clues and remove the last space
  // TODO: should also handle numbers, not only digits
  for (unsigned int i = 0; i <= grid.getRowClues()[0].size(); ++i)
    os << "  ";

  for (unsigned int colIndex = 0; colIndex < grid.getColClues().size(); ++colIndex) // Prints columns' clues
    os << grid.getColClues()[colIndex][0] << ' ';
  os << std::endl;

  for (unsigned int height = 0; height < grid.getGrid().size(); ++height) { // For each row
    for (unsigned int rowIndex = 0; rowIndex < grid.getRowClues()[height].size(); ++rowIndex) { // Prints rows' clues
      os << grid.getRowClues()[height][rowIndex] << ' ';
    }

    // Prints the whole grid in the form:
    // [ X O X ]
    // [ - O X ]
    // [ - O - ]
    // Where the tiles marked as 'O' are filled, those with an 'X' are denied, and '-' means it's empty
    os << "[ ";
    for (unsigned int width = 0; width < grid.getGrid()[height].size(); ++width) { // For each tile
      char res = '-';
      switch (grid.getGrid()[height][width].getState()) { // Prints ouput depending of the tile's state
        case FILLED:
          res = 'O';
          break;
        case DENIED:
          res = 'X';
          break;
        default:
          break;
      }
      os << res << ' ';
    }
    os << ']' << std::endl;
  }
  return os;
}
<commit_msg>[Update] Added clues' display on the right & bottom of the grid. May replace top/left for simplicity<commit_after>
#include <vector>
#include <fstream>
#include <iostream>

#include "../include/Grid.hpp"
#include "../include/Utils.hpp"

Grid::Grid() {}

const bool Grid::loadFromFile(const std::string& fileName) {
  if (std::ifstream fs{fileName}) { // If the file could have been opened
    unsigned int height, width;

    // Fetching height & width of the grid from the first 2 characters
    fs >> height >> width;
    colClues.resize(height);
    rowClues.resize(width);

    // Resizing the grid accordingly
    grid.resize(height);
    for (unsigned int i = 0; i < height; ++i)
      grid[i].resize(width);

    // Fetching grid's clues
    {
      int value, lineNumber = 1;
      std::string line;

      while (std::getline(fs, line)) {
        if (lineNumber > 1) { // If the line isn't the first one (which is <height width>)
          std::vector<std::string> vals;

          if (lineNumber == 2) { // Second line is column's
            // Filling columns' clues
            Utils::split(line, ';', vals);

            for (unsigned int i = 0; i < vals.size(); ++i) {
              std::stringstream ss{vals[i]};
              while (ss >> value)
                colClues[i].push_back(value);
            }
          } else if (lineNumber == 3) { // Third line is row's
            // Filling rows' clues
            Utils::split(line, ';', vals);

            for (unsigned int i = 0; i < vals.size(); ++i) {
              std::stringstream ss{vals[i]};
              while (ss >> value)
                rowClues[i].push_back(value);
            }
          } // End of if (lineNumber == 3)
        } // End of if (lineNumber > 1)
        lineNumber++;
      } // End of while (std::getline(fs, line)))
    }
  } else { // If the file couldn't have been opened
    return false;
  }
  return true;
}

Grid& Grid::solve() { return *this; } //TODO: implement solver

std::ostream& operator<<(std::ostream& os, const Grid& grid) {
  // For each entry in rows' clues, prints two spaces to make a margin (plus two for the starting '[ ')
  // Ideally, should get the entry with maximum number of clues and remove the last space
  // TODO: should also handle numbers, not only digits
  for (unsigned int i = 0; i <= grid.getRowClues()[0].size(); ++i)
    os << "  ";

  for (unsigned int colIndex = 0; colIndex < grid.getColClues().size(); ++colIndex) // Prints columns' clues
    os << grid.getColClues()[colIndex][0] << ' ';
  os << std::endl;

  for (unsigned int height = 0; height < grid.getGrid().size(); ++height) { // For each row
    for (unsigned int rowIndex = 0; rowIndex < grid.getRowClues()[height].size(); ++rowIndex) // Prints rows' clues
      os << grid.getRowClues()[height][rowIndex] << ' ';

    // Prints the whole grid in the form:
    // [ X O X ]
    // [ - O X ]
    // [ - O - ]
    // Where the tiles marked as 'O' are filled, those with an 'X' are denied, and '-' means it's empty
    os << "[ ";
    for (unsigned int width = 0; width < grid.getGrid()[height].size(); ++width) { // For each tile
      char res = '-';
      switch (grid.getGrid()[height][width].getState()) { // Prints ouput depending of the tile's state
        case FILLED:
          res = 'O';
          break;
        case DENIED:
          res = 'X';
          break;
        default:
          break;
      }
      os << res << ' ';
    }
    os << "] ";

    for (unsigned int rowIndex = 0; rowIndex < grid.getRowClues()[height].size(); ++rowIndex) // Prints rows' clues
      os << grid.getRowClues()[height][rowIndex] << ' ';
    os << std::endl;
  }

  // Prints margin again at the bottom of the grid
  for (unsigned int i = 0; i <= grid.getRowClues()[0].size(); ++i)
    os << "  ";
  for (unsigned int colIndex = 0; colIndex < grid.getColClues().size(); ++colIndex) // Prints columns' clues
    os << grid.getColClues()[colIndex][0] << ' ';

  return os << std::endl;
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
/// @brief test suite for PathEnumerator class
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2004-2012 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2015, ArangoDB GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "Basics/Common.h"

#include "catch.hpp"

#include "RocksDBEngine/RocksDBComparator.h"
#include "RocksDBEngine/RocksDBKey.h"
#include "RocksDBEngine/RocksDBKeyBounds.h"
#include "RocksDBEngine/RocksDBTypes.h"
#include "Basics/Exceptions.h"

using namespace arangodb;

// -----------------------------------------------------------------------------
// --SECTION--                                                        test suite
// -----------------------------------------------------------------------------

/// @brief test RocksDBKey class
TEST_CASE("RocksDBKeyTest", "[rocksdbkeytest]") {

/// @brief test database
SECTION("test_database") {
  RocksDBKey key1 = RocksDBKey::Database(0);
  auto const& s1 = key1.string();

  CHECK(s1.size() == sizeof(char) + sizeof(uint64_t));
  CHECK(s1 == std::string("0\0\0\0\0\0\0\0\0\0", 9));

  RocksDBKey key2 = RocksDBKey::Database(1);
  auto const& s2 = key2.string();

  CHECK(s2.size() == sizeof(char) + sizeof(uint64_t));
  CHECK(s2 == std::string("0\1\0\0\0\0\0\0\0\0", 9));

  RocksDBKey key3 = RocksDBKey::Database(255);
  auto const& s3 = key3.string();

  CHECK(s3.size() == sizeof(char) + sizeof(uint64_t));
  CHECK(s3 == std::string("0\xff\0\0\0\0\0\0\0\0", 9));

  RocksDBKey key4 = RocksDBKey::Database(256);
  auto const& s4 = key4.string();

  CHECK(s4.size() == sizeof(char) + sizeof(uint64_t));
  CHECK(s4 == std::string("0\0\x01\0\0\0\0\0\0\0", 9));

  RocksDBKey key5 = RocksDBKey::Database(49152);
  auto const& s5 = key5.string();

  CHECK(s5.size() == sizeof(char) + sizeof(uint64_t));
  CHECK(s5 == std::string("0\0\xc0\0\0\0\0\0\0\0", 9));

  RocksDBKey key6 = RocksDBKey::Database(12345678901);
  auto const& s6 = key6.string();

  CHECK(s6.size() == sizeof(char) + sizeof(uint64_t));
  CHECK(s6 == std::string("0\x35\x1c\xdc\xdf\x02\0\0\0", 9));

  RocksDBKey key7 = RocksDBKey::Database(0xf0f1f2f3f4f5f6f7ULL);
  auto const& s7 = key7.string();

  CHECK(s7.size() == sizeof(char) + sizeof(uint64_t));
  CHECK(s7 == std::string("0\xf7\xf6\xf5\xf4\xf3\xf2\xf1\xf0", 9));
}

/// @brief test collection
SECTION("test_collection") {
  RocksDBKey key1 = RocksDBKey::Collection(0, 0);
  auto const& s1 = key1.string();

  CHECK(s1.size() == sizeof(char) + sizeof(uint64_t) + sizeof(uint64_t));
  CHECK(s1 == std::string("1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 17));

  RocksDBKey key2 = RocksDBKey::Collection(23, 42);
  auto const& s2 = key2.string();

  CHECK(s2.size() == sizeof(char) + sizeof(uint64_t) + sizeof(uint64_t));
  CHECK(s2 == std::string("1\x17\0\0\0\0\0\0\0\x2a\0\0\0\0\0\0\0", 17));

  RocksDBKey key3 = RocksDBKey::Collection(255, 255);
  auto const& s3 = key3.string();

  CHECK(s3.size() == sizeof(char) + sizeof(uint64_t) + sizeof(uint64_t));
  CHECK(s3 == std::string("1\xff\0\0\0\0\0\0\0\xff\0\0\0\0\0\0\0", 17));

  RocksDBKey key4 = RocksDBKey::Collection(256, 257);
  auto const& s4 = key4.string();

  CHECK(s4.size() == sizeof(char) + sizeof(uint64_t) + sizeof(uint64_t));
  CHECK(s4 == std::string("1\0\x01\0\0\0\0\0\0\x01\x01\0\0\0\0\0\0", 17));

  RocksDBKey key5 = RocksDBKey::Collection(49152, 16384);
  auto const& s5 = key5.string();

  CHECK(s5.size() == sizeof(char) + sizeof(uint64_t) + sizeof(uint64_t));
  CHECK(s5 == std::string("1\0\xc0\0\0\0\0\0\0\0\x40\0\0\0\0\0\0", 17));

  RocksDBKey key6 = RocksDBKey::Collection(12345678901, 987654321);
  auto const& s6 = key6.string();

  CHECK(s6.size() == sizeof(char) + sizeof(uint64_t) + sizeof(uint64_t)) ;
  CHECK(s6 == std::string("1\x35\x1c\xdc\xdf\x02\0\0\0\xb1\x68\xde\x3a\0\0\0\0", 17));

  RocksDBKey key7 = RocksDBKey::Collection(0xf0f1f2f3f4f5f6f7ULL, 0xf0f1f2f3f4f5f6f7ULL);
  auto const& s7 = key7.string();

  CHECK(s7.size() == sizeof(char) + sizeof(uint64_t) + sizeof(uint64_t));
  CHECK(s7 == std::string("1\xf7\xf6\xf5\xf4\xf3\xf2\xf1\xf0\xf7\xf6\xf5\xf4\xf3\xf2\xf1\xf0", 17));
}

/// @brief test document
SECTION("test_document") {
  RocksDBKey key1 = RocksDBKey::Document(0, 0);
  auto const& s1 = key1.string();

  CHECK(s1.size() == sizeof(char) + sizeof(uint64_t) + sizeof(uint64_t));
  CHECK(s1 == std::string("3\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 17));

  RocksDBKey key2 = RocksDBKey::Document(23, 42);
  auto const& s2 = key2.string();

  CHECK(s2.size() == sizeof(char) + sizeof(uint64_t) + sizeof(uint64_t));
  CHECK(s2 == std::string("3\x17\0\0\0\0\0\0\0\x2a\0\0\0\0\0\0\0", 17));

  RocksDBKey key3 = RocksDBKey::Document(255, 255);
  auto const& s3 = key3.string();

  CHECK(s3.size() == sizeof(char) + sizeof(uint64_t) + sizeof(uint64_t));
  CHECK(s3 == std::string("3\xff\0\0\0\0\0\0\0\xff\0\0\0\0\0\0\0", 17));

  RocksDBKey key4 = RocksDBKey::Document(256, 257);
  auto const& s4 = key4.string();

  CHECK(s4.size() == sizeof(char) + sizeof(uint64_t) + sizeof(uint64_t));
  CHECK(s4 == std::string("3\0\x01\0\0\0\0\0\0\x01\x01\0\0\0\0\0\0", 17));

  RocksDBKey key5 = RocksDBKey::Document(49152, 16384);
  auto const& s5 = key5.string();

  CHECK(s5.size() == sizeof(char) + sizeof(uint64_t) + sizeof(uint64_t));
  CHECK(s5 == std::string("3\0\xc0\0\0\0\0\0\0\0\x40\0\0\0\0\0\0", 17));

  RocksDBKey key6 = RocksDBKey::Document(12345678901, 987654321);
  auto const& s6 = key6.string();

  CHECK(s6.size() == sizeof(char) + sizeof(uint64_t) + sizeof(uint64_t)) ;
  CHECK(s6 == std::string("3\x35\x1c\xdc\xdf\x02\0\0\0\xb1\x68\xde\x3a\0\0\0\0", 17));

  RocksDBKey key7 = RocksDBKey::Document(0xf0f1f2f3f4f5f6f7ULL, 0xf0f1f2f3f4f5f6f7ULL);
  auto const& s7 = key7.string();

  CHECK(s7.size() == sizeof(char) + sizeof(uint64_t) + sizeof(uint64_t));
  CHECK(s7 == std::string("3\xf7\xf6\xf5\xf4\xf3\xf2\xf1\xf0\xf7\xf6\xf5\xf4\xf3\xf2\xf1\xf0", 17));
}

/// @brief test primary index
SECTION("test_primary_index") {
  RocksDBKey key1 = RocksDBKey::PrimaryIndexValue(0, StringRef(""));
  auto const& s1 = key1.string();

  CHECK(s1.size() == sizeof(char) + sizeof(uint64_t) + strlen(""));
  CHECK(s1 == std::string("4\0\0\0\0\0\0\0\0", 9));

  RocksDBKey key2 = RocksDBKey::PrimaryIndexValue(0, StringRef("abc"));
  auto const& s2 = key2.string();

  CHECK(s2.size() == sizeof(char) + sizeof(uint64_t) + strlen("abc"));
  CHECK(s2 == std::string("4\0\0\0\0\0\0\0\0abc", 12));

  RocksDBKey key3 = RocksDBKey::PrimaryIndexValue(0, StringRef(" "));
  auto const& s3 = key3.string();

  CHECK(s3.size() == sizeof(char) + sizeof(uint64_t) + strlen(" "));
  CHECK(s3 == std::string("4\0\0\0\0\0\0\0\0 ", 10));

  RocksDBKey key4 = RocksDBKey::PrimaryIndexValue(0, StringRef("this is a key"));
  auto const& s4 = key4.string();

  CHECK(s4.size() == sizeof(char) + sizeof(uint64_t) + strlen("this is a key"));
  CHECK(s4 == std::string("4\0\0\0\0\0\0\0\0this is a key", 22));

  // 254 bytes
  char const* longKey = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
  RocksDBKey key5 = RocksDBKey::PrimaryIndexValue(0, StringRef(longKey));
  auto const& s5 = key5.string();

  CHECK(s5.size() == sizeof(char) + sizeof(uint64_t) + strlen(longKey));
  CHECK(s5 == std::string("4\0\0\0\0\0\0\0\0", 9) + longKey);

  RocksDBKey key6 = RocksDBKey::PrimaryIndexValue(123456789, StringRef("this is a key"));
  auto const& s6 = key6.string();

  CHECK(s6.size() == sizeof(char) + sizeof(uint64_t) + strlen("this is a key"));
  CHECK(s6 == std::string("4\x15\xcd\x5b\x07\0\0\0\0this is a key", 22));
}

/// @brief test edge index
SECTION("test_edge_index") {
  RocksDBKey key1 = RocksDBKey::EdgeIndexValue(0, StringRef("a/1"), 33);
  auto const& s1 = key1.string();

  CHECK(s1.size() == sizeof(char) + sizeof(uint64_t) + strlen("a/1") + sizeof(char) + strlen("foobar") + sizeof(char));
  CHECK(s1 == std::string("5\0\0\0\0\0\0\0\0a/1\0\0\0!\0\0\0\0", 20));
}
}

/// @brief test RocksDBKeyBounds class
TEST_CASE("RocksDBKeyBoundsTest", "[rocksdbkeybounds]") {

/// @brief test geo index key and bounds consistency
SECTION("test_geo_index") {

  rocksdb::Comparator const* cmp = rocksdb::BytewiseComparator();

  RocksDBKey k1 = RocksDBKey::GeoIndexValue(256, 128, false);
  RocksDBKeyBounds bb1 = RocksDBKeyBounds::GeoIndex(256, false);

  CHECK(cmp->Compare(k1.string(), bb1.start()) > 0);
  CHECK(cmp->Compare(k1.string(), bb1.end()) < 0);

  RocksDBKey k2 = RocksDBKey::GeoIndexValue(256, 128, true);
  RocksDBKeyBounds bb2 = RocksDBKeyBounds::GeoIndex(256, true);
  CHECK(cmp->Compare(k2.string(), bb2.start()) > 0);
  CHECK(cmp->Compare(k2.string(), bb2.end()) < 0);
}

}
<commit_msg>Fixing catch test<commit_after>////////////////////////////////////////////////////////////////////////////////
/// @brief test suite for PathEnumerator class
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2004-2012 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2015, ArangoDB GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

#include "Basics/Common.h"

#include "catch.hpp"

#include "RocksDBEngine/RocksDBComparator.h"
#include "RocksDBEngine/RocksDBKey.h"
#include "RocksDBEngine/RocksDBKeyBounds.h"
#include "RocksDBEngine/RocksDBTypes.h"
#include "Basics/Exceptions.h"

using namespace arangodb;

// -----------------------------------------------------------------------------
// --SECTION--                                                        test suite
// -----------------------------------------------------------------------------

/// @brief test RocksDBKey class
TEST_CASE("RocksDBKeyTest", "[rocksdbkeytest]") {

/// @brief test database
SECTION("test_database") {
  RocksDBKey key1 = RocksDBKey::Database(0);
  auto const& s1 = key1.string();

  CHECK(s1.size() == sizeof(char) + sizeof(uint64_t));
  CHECK(s1 == std::string("0\0\0\0\0\0\0\0\0\0", 9));

  RocksDBKey key2 = RocksDBKey::Database(1);
  auto const& s2 = key2.string();

  CHECK(s2.size() == sizeof(char) + sizeof(uint64_t));
  CHECK(s2 == std::string("0\1\0\0\0\0\0\0\0\0", 9));

  RocksDBKey key3 = RocksDBKey::Database(255);
  auto const& s3 = key3.string();

  CHECK(s3.size() == sizeof(char) + sizeof(uint64_t));
  CHECK(s3 == std::string("0\xff\0\0\0\0\0\0\0\0", 9));

  RocksDBKey key4 = RocksDBKey::Database(256);
  auto const& s4 = key4.string();

  CHECK(s4.size() == sizeof(char) + sizeof(uint64_t));
  CHECK(s4 == std::string("0\0\x01\0\0\0\0\0\0\0", 9));

  RocksDBKey key5 = RocksDBKey::Database(49152);
  auto const& s5 = key5.string();

  CHECK(s5.size() == sizeof(char) + sizeof(uint64_t));
  CHECK(s5 == std::string("0\0\xc0\0\0\0\0\0\0\0", 9));

  RocksDBKey key6 = RocksDBKey::Database(12345678901);
  auto const& s6 = key6.string();

  CHECK(s6.size() == sizeof(char) + sizeof(uint64_t));
  CHECK(s6 == std::string("0\x35\x1c\xdc\xdf\x02\0\0\0", 9));

  RocksDBKey key7 = RocksDBKey::Database(0xf0f1f2f3f4f5f6f7ULL);
  auto const& s7 = key7.string();

  CHECK(s7.size() == sizeof(char) + sizeof(uint64_t));
  CHECK(s7 == std::string("0\xf7\xf6\xf5\xf4\xf3\xf2\xf1\xf0", 9));
}

/// @brief test collection
SECTION("test_collection") {
  RocksDBKey key1 = RocksDBKey::Collection(0, 0);
  auto const& s1 = key1.string();

  CHECK(s1.size() == sizeof(char) + sizeof(uint64_t) + sizeof(uint64_t));
  CHECK(s1 == std::string("1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 17));

  RocksDBKey key2 = RocksDBKey::Collection(23, 42);
  auto const& s2 = key2.string();

  CHECK(s2.size() == sizeof(char) + sizeof(uint64_t) + sizeof(uint64_t));
  CHECK(s2 == std::string("1\x17\0\0\0\0\0\0\0\x2a\0\0\0\0\0\0\0", 17));

  RocksDBKey key3 = RocksDBKey::Collection(255, 255);
  auto const& s3 = key3.string();

  CHECK(s3.size() == sizeof(char) + sizeof(uint64_t) + sizeof(uint64_t));
  CHECK(s3 == std::string("1\xff\0\0\0\0\0\0\0\xff\0\0\0\0\0\0\0", 17));

  RocksDBKey key4 = RocksDBKey::Collection(256, 257);
  auto const& s4 = key4.string();

  CHECK(s4.size() == sizeof(char) + sizeof(uint64_t) + sizeof(uint64_t));
  CHECK(s4 == std::string("1\0\x01\0\0\0\0\0\0\x01\x01\0\0\0\0\0\0", 17));

  RocksDBKey key5 = RocksDBKey::Collection(49152, 16384);
  auto const& s5 = key5.string();

  CHECK(s5.size() == sizeof(char) + sizeof(uint64_t) + sizeof(uint64_t));
  CHECK(s5 == std::string("1\0\xc0\0\0\0\0\0\0\0\x40\0\0\0\0\0\0", 17));

  RocksDBKey key6 = RocksDBKey::Collection(12345678901, 987654321);
  auto const& s6 = key6.string();

  CHECK(s6.size() == sizeof(char) + sizeof(uint64_t) + sizeof(uint64_t)) ;
  CHECK(s6 == std::string("1\x35\x1c\xdc\xdf\x02\0\0\0\xb1\x68\xde\x3a\0\0\0\0", 17));

  RocksDBKey key7 = RocksDBKey::Collection(0xf0f1f2f3f4f5f6f7ULL, 0xf0f1f2f3f4f5f6f7ULL);
  auto const& s7 = key7.string();

  CHECK(s7.size() == sizeof(char) + sizeof(uint64_t) + sizeof(uint64_t));
  CHECK(s7 == std::string("1\xf7\xf6\xf5\xf4\xf3\xf2\xf1\xf0\xf7\xf6\xf5\xf4\xf3\xf2\xf1\xf0", 17));
}

/// @brief test document
SECTION("test_document") {
  RocksDBKey key1 = RocksDBKey::Document(0, 0);
  auto const& s1 = key1.string();

  CHECK(s1.size() == sizeof(char) + sizeof(uint64_t) + sizeof(uint64_t));
  CHECK(s1 == std::string("3\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 17));

  RocksDBKey key2 = RocksDBKey::Document(23, 42);
  auto const& s2 = key2.string();

  CHECK(s2.size() == sizeof(char) + sizeof(uint64_t) + sizeof(uint64_t));
  CHECK(s2 == std::string("3\x17\0\0\0\0\0\0\0\x2a\0\0\0\0\0\0\0", 17));

  RocksDBKey key3 = RocksDBKey::Document(255, 255);
  auto const& s3 = key3.string();

  CHECK(s3.size() == sizeof(char) + sizeof(uint64_t) + sizeof(uint64_t));
  CHECK(s3 == std::string("3\xff\0\0\0\0\0\0\0\xff\0\0\0\0\0\0\0", 17));

  RocksDBKey key4 = RocksDBKey::Document(256, 257);
  auto const& s4 = key4.string();

  CHECK(s4.size() == sizeof(char) + sizeof(uint64_t) + sizeof(uint64_t));
  CHECK(s4 == std::string("3\0\x01\0\0\0\0\0\0\x01\x01\0\0\0\0\0\0", 17));

  RocksDBKey key5 = RocksDBKey::Document(49152, 16384);
  auto const& s5 = key5.string();

  CHECK(s5.size() == sizeof(char) + sizeof(uint64_t) + sizeof(uint64_t));
  CHECK(s5 == std::string("3\0\xc0\0\0\0\0\0\0\0\x40\0\0\0\0\0\0", 17));

  RocksDBKey key6 = RocksDBKey::Document(12345678901, 987654321);
  auto const& s6 = key6.string();

  CHECK(s6.size() == sizeof(char) + sizeof(uint64_t) + sizeof(uint64_t)) ;
  CHECK(s6 == std::string("3\x35\x1c\xdc\xdf\x02\0\0\0\xb1\x68\xde\x3a\0\0\0\0", 17));

  RocksDBKey key7 = RocksDBKey::Document(0xf0f1f2f3f4f5f6f7ULL, 0xf0f1f2f3f4f5f6f7ULL);
  auto const& s7 = key7.string();

  CHECK(s7.size() == sizeof(char) + sizeof(uint64_t) + sizeof(uint64_t));
  CHECK(s7 == std::string("3\xf7\xf6\xf5\xf4\xf3\xf2\xf1\xf0\xf7\xf6\xf5\xf4\xf3\xf2\xf1\xf0", 17));
}

/// @brief test primary index
SECTION("test_primary_index") {
  RocksDBKey key1 = RocksDBKey::PrimaryIndexValue(0, StringRef(""));
  auto const& s1 = key1.string();

  CHECK(s1.size() == sizeof(char) + sizeof(uint64_t) + strlen(""));
  CHECK(s1 == std::string("4\0\0\0\0\0\0\0\0", 9));

  RocksDBKey key2 = RocksDBKey::PrimaryIndexValue(0, StringRef("abc"));
  auto const& s2 = key2.string();

  CHECK(s2.size() == sizeof(char) + sizeof(uint64_t) + strlen("abc"));
  CHECK(s2 == std::string("4\0\0\0\0\0\0\0\0abc", 12));

  RocksDBKey key3 = RocksDBKey::PrimaryIndexValue(0, StringRef(" "));
  auto const& s3 = key3.string();

  CHECK(s3.size() == sizeof(char) + sizeof(uint64_t) + strlen(" "));
  CHECK(s3 == std::string("4\0\0\0\0\0\0\0\0 ", 10));

  RocksDBKey key4 = RocksDBKey::PrimaryIndexValue(0, StringRef("this is a key"));
  auto const& s4 = key4.string();

  CHECK(s4.size() == sizeof(char) + sizeof(uint64_t) + strlen("this is a key"));
  CHECK(s4 == std::string("4\0\0\0\0\0\0\0\0this is a key", 22));

  // 254 bytes
  char const* longKey = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
  RocksDBKey key5 = RocksDBKey::PrimaryIndexValue(0, StringRef(longKey));
  auto const& s5 = key5.string();

  CHECK(s5.size() == sizeof(char) + sizeof(uint64_t) + strlen(longKey));
  CHECK(s5 == std::string("4\0\0\0\0\0\0\0\0", 9) + longKey);

  RocksDBKey key6 = RocksDBKey::PrimaryIndexValue(123456789, StringRef("this is a key"));
  auto const& s6 = key6.string();

  CHECK(s6.size() == sizeof(char) + sizeof(uint64_t) + strlen("this is a key"));
  CHECK(s6 == std::string("4\x15\xcd\x5b\x07\0\0\0\0this is a key", 22));
}

/// @brief test edge index
SECTION("test_edge_index") {
  RocksDBKey key1 = RocksDBKey::EdgeIndexValue(0, StringRef("a/1"), 33);
  auto const& s1 = key1.string();

  CHECK(s1.size() == sizeof(char) + sizeof(uint64_t) + strlen("a/1") + sizeof(char) + sizeof(uint64_t));
  CHECK(s1 == std::string("5\0\0\0\0\0\0\0\0a/1\0!\0\0\0\0\0\0\0", 21));
}
}

/// @brief test RocksDBKeyBounds class
TEST_CASE("RocksDBKeyBoundsTest", "[rocksdbkeybounds]") {

/// @brief test geo index key and bounds consistency
SECTION("test_geo_index") {

  rocksdb::Comparator const* cmp = rocksdb::BytewiseComparator();

  RocksDBKey k1 = RocksDBKey::GeoIndexValue(256, 128, false);
  RocksDBKeyBounds bb1 = RocksDBKeyBounds::GeoIndex(256, false);

  CHECK(cmp->Compare(k1.string(), bb1.start()) > 0);
  CHECK(cmp->Compare(k1.string(), bb1.end()) < 0);

  RocksDBKey k2 = RocksDBKey::GeoIndexValue(256, 128, true);
  RocksDBKeyBounds bb2 = RocksDBKeyBounds::GeoIndex(256, true);
  CHECK(cmp->Compare(k2.string(), bb2.start()) > 0);
  CHECK(cmp->Compare(k2.string(), bb2.end()) < 0);
}

}
<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>
#include <stdexcept>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
#include <unordered_map>

#include "global.hpp"
#include "operators.hpp"
#include "tokens.hpp"
#include "nodes.hpp"
#include "builtins.hpp"
#include "operator_maps.hpp"

namespace lang {

  class Parser {
  private:
    std::vector<Token> tokens {};
    inline void skipCharacters(unsigned int& i, int by) {i += by;}
    // If we're already at the next character, but the loop will increment i by 1
    inline void preventIncrement(unsigned int& i) {i--;}

    std::vector<Token> variables {};
    std::vector<std::string> keywords {"define", "if", "while"};
    std::vector<std::string> constructKeywords {"do", "end", "else"};
  public:
    AST tree = AST();

    Parser(std::string code) {
      if (PARSER_PRINT_INPUT) print(code, "\n");
      try {
        tokenize(code);
        if (PARSER_PRINT_TOKENS) for (auto tok : tokens) print(tok, "\n");
        if (PARSER_PRINT_AS_EXPR) for (auto tok : ExpressionNode(tokens).getRPNOutput()) print(tok.data, " ");
        buildTree(tokens);
      } catch (SyntaxError &e) {
        print(e.toString(), "\n");
      }
    }

    void tokenize(std::string code) {
      unsigned int lines = 0;
      for (unsigned int i = 0; i < code.length(); ++i) {
        if (code[i] == '/' && code[i + 1] == '/') while(code[i] != '\n' && code[i] != '\0') skipCharacters(i, 1);
        if (code[i] == '\n') lines++;

        // Ignore whitespace
        if (isspace(code[i])) continue;

        // Block begin/end
        // Parenthesis
        // Semicolons
        if (code[i] == '{' || code[i] == '}' ||
        code[i] == '(' || code[i] == ')' ||
        code[i] == ';') {
          tokens.push_back(Token(std::string(1, code[i]), CONSTRUCT, lines));
          continue;
        }

        // Operators
        auto initTokSize = tokens.size();
        std::for_each(opList.begin(), opList.end(), [this, initTokSize, code, i, lines](Operator& op) {
          if (initTokSize < tokens.size()) return; // If there are more tokens than before for_each, the operator was already added, so return.
          if (op.toString().length() + i > code.length()) return; // If the operator is longer than the source string, ignore it.
          if (op.toString() == code.substr(i, op.toString().length())) {
            Operator* tmp = &op;
            // TODO: apply DRY on these ifs
            if (tmp->toString() == "++" || tmp->toString() == "--") {
              // Prefix version
              if (tokens.back().type == OPERATOR || tokens.back().type == CONSTRUCT) tmp = new Operator(tmp->toString(), 12, ASSOCIATE_FROM_RIGHT, UNARY);
              // Postfix version
              else tmp = new Operator(tmp->toString(), 13, ASSOCIATE_FROM_RIGHT, UNARY);
            }
            if (tmp->toString() == "+" || tmp->toString() == "-") {
              // Unary version
              if (tokens.back().type == OPERATOR || tokens.back().type == CONSTRUCT) tmp = new Operator(tmp->toString(), 12, ASSOCIATE_FROM_RIGHT, UNARY);
              // Binary version
              else tmp = new Operator(tmp->toString(), 10);
            }
            if (PARSER_PRINT_OPERATOR_TOKENS) print("Parser found Token with Operator ", *tmp, ", at address ", tmp, "\n");
            tokens.push_back(Token(tmp, OPERATOR, lines));
          }
        });

        if (initTokSize < tokens.size()) {
          skipCharacters(i, tokens.back().data.length() - 1);
          continue; // Token added, continue.
        }

        // Numbers
        if (isdigit(code[i])) {
          int base = 10;
          std::string current = "";
          if (code[i] == '0') {
            switch (code[i + 1]) {
              case 'x': base = 16; skipCharacters(i, 2); break;
              case 'b': base =  2; skipCharacters(i, 2); break;
              case 'o': base =  8; skipCharacters(i, 2); break;
              default: break;
            }
          }
          bool isFloat = false;
          while (isdigit(code[i]) || code[i] == '.') {
            current += code[i];
            if (code[i] == '.') {
              if (isFloat) throw SyntaxError("Malformed float, multiple decimal points: \"" + current + "\"", lines);
              isFloat = true;
            }
            skipCharacters(i, 1);
          }
          preventIncrement(i);
          if (current[current.length() - 1] == '.') throw SyntaxError("Malformed float, missing digits after decimal point: \"" + current + "\"", lines);
          if (base != 10 && isFloat) throw SyntaxError("Floating point numbers must be used with base 10 numbers: \"" + current + "\"", lines);
          Token t;
          if (isFloat) t = Token(new Float(current), FLOAT, lines);
          else t = Token(new Integer(current, base), INTEGER, lines);
          tokens.push_back(t);
          continue;
        }

        // String literals
        if (code[i] == '"') {
          skipCharacters(i, 1); // Skip the double quote
          std::string current = "";
          while (code[i] != '"') {
            // TODO: add escape sequences
            current += code[i];
            skipCharacters(i, 1);
          }
          // Don't call preventIncrement here so the other double quote is skipped
          tokens.push_back(Token(new String(current), STRING, lines));
          continue;
        }

        // Others
        Token token = Token();
        while (!isspace(code[i])) {
          if (isReservedChar(code[i]) || code[i] == '\0') break;
          token.data += code[i];
          skipCharacters(i, 1);
        }
        // Check if the thing is a Boolean
        if (token.data == "true" || token.data == "false") {
          token.type = BOOLEAN;
          token.typeData = new Boolean(token.data);
        }
        // Check if the thing references a variable
        for (auto tok : variables)
          if (tok.data == token.data) {
            token = tok;
            break;
          }
        // Check if the thing is a new variable
        if (tokens.size() > 0 && ((tokens.back().type == KEYWORD && tokens.back().data == "define") || tokens.back().type == TYPE)) {
          token.type = VARIABLE;
          variables.push_back(token);
        }
        // Check if the thing is a keyword
        if (contains(token.data, keywords)) token.type = KEYWORD;
        if (contains(token.data, constructKeywords)) token.type = CONSTRUCT;

        // Push token
        preventIncrement(i);
        token.line = lines;
        tokens.push_back(token);
      }
    }

    ExpressionNode* evaluateCondition(std::vector<Token>& toks) {
      std::vector<Token> exprToks = std::vector<Token>(toks.begin() + 1, toks.end() - 1);
      ExpressionNode* condition = new ExpressionNode(exprToks);
      condition->buildSubtree();
      return condition;
    }

    void buildTree(std::vector<Token> tokens) {
      static std::vector<BlockNode*> blockStack {};
      auto addToBlock = [this](ASTNode* child) {
        if (blockStack.size() == 0) tree.addRootChild(child);
        else blockStack.back()->addChild(child);
      };
      auto logicalLines = splitVector(tokens, isNewLine);
      for (uint64 i = 0; i < logicalLines.size(); i++) {
        std::vector<Token>& toks = logicalLines[i];
        if (toks.size() == 0) continue;
        // TODO: check for solid types here as well
        if (toks[0].data == "define" && toks[0].type == KEYWORD) {
          DeclarationNode* decl = new DeclarationNode("define", toks[1]);
          decl->setLineNumber(toks[1].line);
          if (toks[2].data != ";" || toks[2].type != CONSTRUCT) {
            std::vector<Token> exprToks(toks.begin() + 1, toks.end());
            ExpressionNode* expr = new ExpressionNode(exprToks);
            expr->buildSubtree();
            decl->addChild(expr);
          }
          if (PARSER_PRINT_DECL_TREE) decl->printTree(blockStack.size());
          addToBlock(decl);
        } else if (toks[0].data == "while" && toks[0].type == KEYWORD) {
          auto wBlock = new WhileNode(evaluateCondition(toks), new BlockNode());
          if (PARSER_PRINT_WHILE_TREE) wBlock->printTree(blockStack.size());
          addToBlock(wBlock);
          blockStack.push_back(wBlock);
        } else if (toks[0].data == "if" && toks[0].type == KEYWORD) {
          auto cBlock = new ConditionalNode(evaluateCondition(toks), new BlockNode(), new BlockNode());
          if (PARSER_PRINT_COND_TREE) cBlock->printTree(blockStack.size());
          addToBlock(cBlock);
          blockStack.push_back(cBlock);
        } else if (toks[0].data == "else" && toks[0].type == CONSTRUCT) {
          auto cNode = dynamic_cast<ConditionalNode*>(blockStack.back());
          if (cNode == nullptr) throw SyntaxError("Cannot find conditional structure for token `else`.\n", blockStack.back()->getLineNumber());
          cNode->nextBlock();
        } else if (toks[0].data == "end" && toks[0].type == CONSTRUCT) {
          blockStack.pop_back();
        } else {
          ExpressionNode* expr = new ExpressionNode(toks);
          expr->buildSubtree();
          expr->setLineNumber(dynamic_cast<ExpressionChildNode*>(expr->getChildren()[0])->t.line);
          if (PARSER_PRINT_EXPR_TREE) expr->printTree(blockStack.size());
          addToBlock(expr);
        }
      }
    }

    std::vector<Token> getTokens() {
      return tokens;
    }

  };

  class Interpreter {
  private:
    AST tree;
    // TODO: implement some scope
    Scope globalVars {};
  public:
    Interpreter(AST tree): tree(tree) {
      interpret(tree.getRootChildren());
    }
  private:
    void interpret(ChildrenNodes nodes) {
      for (uint64 i = 0; i < nodes.size(); ++i) {
        auto nodeType = nodes[i]->getNodeType();
        if (nodeType == "ExpressionNode") {
          interpretExpression(dynamic_cast<ExpressionChildNode*>(nodes[i]->getChildren()[0]))->printTree(0);
        } else if (nodeType == "DeclarationNode") {
          registerDeclaration(dynamic_cast<DeclarationNode*>(nodes[i]));
        } else if (nodeType == "ConditionalNode") {
          resolveCondition(dynamic_cast<ConditionalNode*>(nodes[i]));
        } else if (nodeType == "WhileNode") {
          doWhileLoop(dynamic_cast<WhileNode*>(nodes[i]));
        }
      }
    }

    void doWhileLoop(WhileNode* node) {
      while (true) {
        auto condition = interpretExpression(dynamic_cast<ExpressionChildNode*>(node->getCondition()->getChild()));
        if (!static_cast<Object*>(condition->t.typeData)->isTruthy()) break;
        interpret(node->getLoopNode()->getChildren());
      }
    }

    void resolveCondition(ConditionalNode* node) {
      auto condRes = interpretExpression(dynamic_cast<ExpressionChildNode*>(node->getCondition()->getChild()));
      if (static_cast<Object*>(condRes->t.typeData)->isTruthy()) {
        interpret(node->getTrueBlock()->getChildren());
      } else {
        interpret(node->getFalseBlock()->getChildren());
      }
    }

    void registerDeclaration(DeclarationNode* node) {
      node->getParentScope()->insert({node->identifier.data, new Variable()});
      if (node->getChildren().size() == 1) {
        (*node->getParentScope())[node->identifier.data]->assign(
          static_cast<Object*>(interpretExpression(dynamic_cast<ExpressionChildNode*>(node->getChild()->getChildren()[0]))->t.typeData)
        );
      }
    }

    ExpressionChildNode* interpretExpression(ExpressionChildNode* node) {
      if (node->getChildren().size() == 0) return node;
      if (node->t.type == OPERATOR) {
        ExpressionChildNode* processed = new ExpressionChildNode(node->t);
        processed->setParent(node->getParent());
        auto ch = node->getChildren();
        std::for_each(ch.begin(), ch.end(), [=](ASTNode*& n) {
          auto node = dynamic_cast<ExpressionChildNode*>(n);
          if (node->getChildren().size() != 0) processed->addChild(interpretExpression(node));
          else processed->addChild(node);
        });
        return new ExpressionChildNode(Token(runOperator(processed), UNPROCESSED, -2));
      }
      throw std::runtime_error("Wrong type of token.\n");
    }

  };

} /* namespace lang */

void printHelp() {
  print(
    "Use -c to read from constants.data and inputs.data, -e [CODE] to evaluate code and -f [PATH] to load code from a file.\n",
    "Examples:\n",
    "  lang -c\n",
    "  lang -e \"if true != false do 1 + 1; end\"\n",
    "  lang -f \"/path/to/file.txt\"\n"
  );
}

int main(int argc, char** argv) {
  if (argc == 1) {
    printHelp();
    return 1;
  }
  else if (std::string(argv[1]) == "-c") getConstants();
  else if (std::string(argv[1]) == "-e") INPUT = argv[2];
  else if (std::string(argv[1]) == "-f") {
    std::ifstream in(argv[2]);
    std::string contents((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
    INPUT = contents;
  } else {
    printHelp();
    return 1;
  }
  try {
    lang::Parser a(INPUT);
    lang::Interpreter in(a.tree);
  } catch(SyntaxError& se) {
    print(se.toString(), "\n");
  } catch(TypeError& te) {
    print(te.toString(), "\n");
  }
  return 0;
}
<commit_msg>Removed TODO for scope<commit_after>#include <iostream>
#include <fstream>
#include <stdexcept>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
#include <unordered_map>

#include "global.hpp"
#include "operators.hpp"
#include "tokens.hpp"
#include "nodes.hpp"
#include "builtins.hpp"
#include "operator_maps.hpp"

namespace lang {

  class Parser {
  private:
    std::vector<Token> tokens {};
    inline void skipCharacters(unsigned int& i, int by) {i += by;}
    // If we're already at the next character, but the loop will increment i by 1
    inline void preventIncrement(unsigned int& i) {i--;}

    std::vector<Token> variables {};
    std::vector<std::string> keywords {"define", "if", "while"};
    std::vector<std::string> constructKeywords {"do", "end", "else"};
  public:
    AST tree = AST();

    Parser(std::string code) {
      if (PARSER_PRINT_INPUT) print(code, "\n");
      try {
        tokenize(code);
        if (PARSER_PRINT_TOKENS) for (auto tok : tokens) print(tok, "\n");
        if (PARSER_PRINT_AS_EXPR) for (auto tok : ExpressionNode(tokens).getRPNOutput()) print(tok.data, " ");
        buildTree(tokens);
      } catch (SyntaxError &e) {
        print(e.toString(), "\n");
      }
    }

    void tokenize(std::string code) {
      unsigned int lines = 0;
      for (unsigned int i = 0; i < code.length(); ++i) {
        if (code[i] == '/' && code[i + 1] == '/') while(code[i] != '\n' && code[i] != '\0') skipCharacters(i, 1);
        if (code[i] == '\n') lines++;

        // Ignore whitespace
        if (isspace(code[i])) continue;

        // Block begin/end
        // Parenthesis
        // Semicolons
        if (code[i] == '{' || code[i] == '}' ||
        code[i] == '(' || code[i] == ')' ||
        code[i] == ';') {
          tokens.push_back(Token(std::string(1, code[i]), CONSTRUCT, lines));
          continue;
        }

        // Operators
        auto initTokSize = tokens.size();
        std::for_each(opList.begin(), opList.end(), [this, initTokSize, code, i, lines](Operator& op) {
          if (initTokSize < tokens.size()) return; // If there are more tokens than before for_each, the operator was already added, so return.
          if (op.toString().length() + i > code.length()) return; // If the operator is longer than the source string, ignore it.
          if (op.toString() == code.substr(i, op.toString().length())) {
            Operator* tmp = &op;
            // TODO: apply DRY on these ifs
            if (tmp->toString() == "++" || tmp->toString() == "--") {
              // Prefix version
              if (tokens.back().type == OPERATOR || tokens.back().type == CONSTRUCT) tmp = new Operator(tmp->toString(), 12, ASSOCIATE_FROM_RIGHT, UNARY);
              // Postfix version
              else tmp = new Operator(tmp->toString(), 13, ASSOCIATE_FROM_RIGHT, UNARY);
            }
            if (tmp->toString() == "+" || tmp->toString() == "-") {
              // Unary version
              if (tokens.back().type == OPERATOR || tokens.back().type == CONSTRUCT) tmp = new Operator(tmp->toString(), 12, ASSOCIATE_FROM_RIGHT, UNARY);
              // Binary version
              else tmp = new Operator(tmp->toString(), 10);
            }
            if (PARSER_PRINT_OPERATOR_TOKENS) print("Parser found Token with Operator ", *tmp, ", at address ", tmp, "\n");
            tokens.push_back(Token(tmp, OPERATOR, lines));
          }
        });

        if (initTokSize < tokens.size()) {
          skipCharacters(i, tokens.back().data.length() - 1);
          continue; // Token added, continue.
        }

        // Numbers
        if (isdigit(code[i])) {
          int base = 10;
          std::string current = "";
          if (code[i] == '0') {
            switch (code[i + 1]) {
              case 'x': base = 16; skipCharacters(i, 2); break;
              case 'b': base =  2; skipCharacters(i, 2); break;
              case 'o': base =  8; skipCharacters(i, 2); break;
              default: break;
            }
          }
          bool isFloat = false;
          while (isdigit(code[i]) || code[i] == '.') {
            current += code[i];
            if (code[i] == '.') {
              if (isFloat) throw SyntaxError("Malformed float, multiple decimal points: \"" + current + "\"", lines);
              isFloat = true;
            }
            skipCharacters(i, 1);
          }
          preventIncrement(i);
          if (current[current.length() - 1] == '.') throw SyntaxError("Malformed float, missing digits after decimal point: \"" + current + "\"", lines);
          if (base != 10 && isFloat) throw SyntaxError("Floating point numbers must be used with base 10 numbers: \"" + current + "\"", lines);
          Token t;
          if (isFloat) t = Token(new Float(current), FLOAT, lines);
          else t = Token(new Integer(current, base), INTEGER, lines);
          tokens.push_back(t);
          continue;
        }

        // String literals
        if (code[i] == '"') {
          skipCharacters(i, 1); // Skip the double quote
          std::string current = "";
          while (code[i] != '"') {
            // TODO: add escape sequences
            current += code[i];
            skipCharacters(i, 1);
          }
          // Don't call preventIncrement here so the other double quote is skipped
          tokens.push_back(Token(new String(current), STRING, lines));
          continue;
        }

        // Others
        Token token = Token();
        while (!isspace(code[i])) {
          if (isReservedChar(code[i]) || code[i] == '\0') break;
          token.data += code[i];
          skipCharacters(i, 1);
        }
        // Check if the thing is a Boolean
        if (token.data == "true" || token.data == "false") {
          token.type = BOOLEAN;
          token.typeData = new Boolean(token.data);
        }
        // Check if the thing references a variable
        for (auto tok : variables)
          if (tok.data == token.data) {
            token = tok;
            break;
          }
        // Check if the thing is a new variable
        if (tokens.size() > 0 && ((tokens.back().type == KEYWORD && tokens.back().data == "define") || tokens.back().type == TYPE)) {
          token.type = VARIABLE;
          variables.push_back(token);
        }
        // Check if the thing is a keyword
        if (contains(token.data, keywords)) token.type = KEYWORD;
        if (contains(token.data, constructKeywords)) token.type = CONSTRUCT;

        // Push token
        preventIncrement(i);
        token.line = lines;
        tokens.push_back(token);
      }
    }

    ExpressionNode* evaluateCondition(std::vector<Token>& toks) {
      std::vector<Token> exprToks = std::vector<Token>(toks.begin() + 1, toks.end() - 1);
      ExpressionNode* condition = new ExpressionNode(exprToks);
      condition->buildSubtree();
      return condition;
    }

    void buildTree(std::vector<Token> tokens) {
      static std::vector<BlockNode*> blockStack {};
      auto addToBlock = [this](ASTNode* child) {
        if (blockStack.size() == 0) tree.addRootChild(child);
        else blockStack.back()->addChild(child);
      };
      auto logicalLines = splitVector(tokens, isNewLine);
      for (uint64 i = 0; i < logicalLines.size(); i++) {
        std::vector<Token>& toks = logicalLines[i];
        if (toks.size() == 0) continue;
        // TODO: check for solid types here as well
        if (toks[0].data == "define" && toks[0].type == KEYWORD) {
          DeclarationNode* decl = new DeclarationNode("define", toks[1]);
          decl->setLineNumber(toks[1].line);
          if (toks[2].data != ";" || toks[2].type != CONSTRUCT) {
            std::vector<Token> exprToks(toks.begin() + 1, toks.end());
            ExpressionNode* expr = new ExpressionNode(exprToks);
            expr->buildSubtree();
            decl->addChild(expr);
          }
          if (PARSER_PRINT_DECL_TREE) decl->printTree(blockStack.size());
          addToBlock(decl);
        } else if (toks[0].data == "while" && toks[0].type == KEYWORD) {
          auto wBlock = new WhileNode(evaluateCondition(toks), new BlockNode());
          if (PARSER_PRINT_WHILE_TREE) wBlock->printTree(blockStack.size());
          addToBlock(wBlock);
          blockStack.push_back(wBlock);
        } else if (toks[0].data == "if" && toks[0].type == KEYWORD) {
          auto cBlock = new ConditionalNode(evaluateCondition(toks), new BlockNode(), new BlockNode());
          if (PARSER_PRINT_COND_TREE) cBlock->printTree(blockStack.size());
          addToBlock(cBlock);
          blockStack.push_back(cBlock);
        } else if (toks[0].data == "else" && toks[0].type == CONSTRUCT) {
          auto cNode = dynamic_cast<ConditionalNode*>(blockStack.back());
          if (cNode == nullptr) throw SyntaxError("Cannot find conditional structure for token `else`.\n", blockStack.back()->getLineNumber());
          cNode->nextBlock();
        } else if (toks[0].data == "end" && toks[0].type == CONSTRUCT) {
          blockStack.pop_back();
        } else {
          ExpressionNode* expr = new ExpressionNode(toks);
          expr->buildSubtree();
          expr->setLineNumber(dynamic_cast<ExpressionChildNode*>(expr->getChildren()[0])->t.line);
          if (PARSER_PRINT_EXPR_TREE) expr->printTree(blockStack.size());
          addToBlock(expr);
        }
      }
    }

    std::vector<Token> getTokens() {
      return tokens;
    }

  };

  class Interpreter {
  private:
    AST tree;
  public:
    Interpreter(AST tree): tree(tree) {
      interpret(tree.getRootChildren());
    }
  private:
    void interpret(ChildrenNodes nodes) {
      for (uint64 i = 0; i < nodes.size(); ++i) {
        auto nodeType = nodes[i]->getNodeType();
        if (nodeType == "ExpressionNode") {
          interpretExpression(dynamic_cast<ExpressionChildNode*>(nodes[i]->getChildren()[0]))->printTree(0);
        } else if (nodeType == "DeclarationNode") {
          registerDeclaration(dynamic_cast<DeclarationNode*>(nodes[i]));
        } else if (nodeType == "ConditionalNode") {
          resolveCondition(dynamic_cast<ConditionalNode*>(nodes[i]));
        } else if (nodeType == "WhileNode") {
          doWhileLoop(dynamic_cast<WhileNode*>(nodes[i]));
        }
      }
    }

    void doWhileLoop(WhileNode* node) {
      while (true) {
        auto condition = interpretExpression(dynamic_cast<ExpressionChildNode*>(node->getCondition()->getChild()));
        if (!static_cast<Object*>(condition->t.typeData)->isTruthy()) break;
        interpret(node->getLoopNode()->getChildren());
      }
    }

    void resolveCondition(ConditionalNode* node) {
      auto condRes = interpretExpression(dynamic_cast<ExpressionChildNode*>(node->getCondition()->getChild()));
      if (static_cast<Object*>(condRes->t.typeData)->isTruthy()) {
        interpret(node->getTrueBlock()->getChildren());
      } else {
        interpret(node->getFalseBlock()->getChildren());
      }
    }

    void registerDeclaration(DeclarationNode* node) {
      node->getParentScope()->insert({node->identifier.data, new Variable()});
      if (node->getChildren().size() == 1) {
        (*node->getParentScope())[node->identifier.data]->assign(
          static_cast<Object*>(interpretExpression(dynamic_cast<ExpressionChildNode*>(node->getChild()->getChildren()[0]))->t.typeData)
        );
      }
    }

    ExpressionChildNode* interpretExpression(ExpressionChildNode* node) {
      if (node->getChildren().size() == 0) return node;
      if (node->t.type == OPERATOR) {
        ExpressionChildNode* processed = new ExpressionChildNode(node->t);
        processed->setParent(node->getParent());
        auto ch = node->getChildren();
        std::for_each(ch.begin(), ch.end(), [=](ASTNode*& n) {
          auto node = dynamic_cast<ExpressionChildNode*>(n);
          if (node->getChildren().size() != 0) processed->addChild(interpretExpression(node));
          else processed->addChild(node);
        });
        return new ExpressionChildNode(Token(runOperator(processed), UNPROCESSED, -2));
      }
      throw std::runtime_error("Wrong type of token.\n");
    }

  };

} /* namespace lang */

void printHelp() {
  print(
    "Use -c to read from constants.data and inputs.data, -e [CODE] to evaluate code and -f [PATH] to load code from a file.\n",
    "Examples:\n",
    "  lang -c\n",
    "  lang -e \"if true != false do 1 + 1; end\"\n",
    "  lang -f \"/path/to/file.txt\"\n"
  );
}

int main(int argc, char** argv) {
  if (argc == 1) {
    printHelp();
    return 1;
  }
  else if (std::string(argv[1]) == "-c") getConstants();
  else if (std::string(argv[1]) == "-e") INPUT = argv[2];
  else if (std::string(argv[1]) == "-f") {
    std::ifstream in(argv[2]);
    std::string contents((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
    INPUT = contents;
  } else {
    printHelp();
    return 1;
  }
  try {
    lang::Parser a(INPUT);
    lang::Interpreter in(a.tree);
  } catch(SyntaxError& se) {
    print(se.toString(), "\n");
  } catch(TypeError& te) {
    print(te.toString(), "\n");
  }
  return 0;
}
<|endoftext|>


<commit_before>#include "BootSplash.h"
#include "ui_BootSplash.h"

#include <LuminaXDG.h>
#include <LUtils.h>
#include <LDesktopUtils.h>

BootSplash::BootSplash() : QWidget(0, Qt::SplashScreen | Qt::X11BypassWindowManagerHint | Qt::WindowStaysOnTopHint | Qt::WindowDoesNotAcceptFocus), ui(new Ui::BootSplash){
  ui->setupUi(this);
  this->setObjectName("LuminaBootSplash"); //for theme styling
  //Center the window on the primary screen
  QPoint ctr = QApplication::desktop()->screenGeometry().center();
  this->move( ctr.x()-(this->width()/2), ctr.y()-(this->height()/2) );
  generateTipOfTheDay();
  ui->label_version->setText( QString(tr("Version %1")).arg(LDesktopUtils::LuminaDesktopVersion()) );
}

void BootSplash::generateTipOfTheDay(){
  int index = qrand()%5; //Make sure this number matches the length of the case below (max value +1)
  QString tip = "This desktop is generously sponsored by iXsystems\nwww.ixsystems.com"; //fallback message (just in case)
  switch(index){
    case 0:
	tip = tr("This desktop is powered by coffee, coffee, and more coffee."); break;
    case 1:
	tip = tr("Keep up with desktop news!")+"\n\nwww.lumina-desktop.org"; break;
    case 2:
	tip = tr("There is a full handbook of information about the desktop available online.")+"\n\nwww.lumina-desktop.org/handbook"; break;
    case 3:
	tip = tr("Want to change the interface? Everything is customizable in the desktop configuration!"); break;
    case 4:
	tip = tr("Lumina can easily reproduce the interface from most other desktop environments."); break;
    case 5:
	tip = tr(""); break;
    case 6:
	tip = tr(""); break;
  }
  ui->label_welcome->setText( "\""+tip+"\"" );
}

void BootSplash::showScreen(QString loading){ //update icon, text, and progress
  QString txt, icon;
  int per = 0;
  if(loading=="init"){
    txt = tr("Initializing Session …"); per = 10;
    icon = "preferences-system-login";
  }else if(loading=="settings"){
    txt = tr("Loading System Settings …"); per = 20;
    icon = "user-home";
  }else if(loading=="user"){
    txt = tr("Loading User Preferences …"); per = 30;
    icon = "preferences-desktop-user";
  }else if(loading=="systray"){
    txt = tr("Preparing System Tray …"); per = 40;
    icon = "preferences-plugin";
  }else if(loading=="wm"){
    txt = tr("Starting Window Manager …"); per = 50;
    icon = "preferences-system-windows-actions";
  }else if(loading=="apps"){
    txt = tr("Detecting Applications …"); per = 60;
    icon = "preferences-desktop-icons";
  }else if(loading=="menus"){
    txt = tr("Preparing Menus …"); per = 70;
    icon = "preferences-system-windows";
  }else if(loading=="desktop"){
    txt = tr("Preparing Workspace …"); per = 80;
    icon = "preferences-desktop-wallpaper";
  }else if(loading=="final"){
    txt = tr("Finalizing …"); per = 90;
    icon = "start-here-lumina";
  }else if(loading.startsWith("app::")){
    txt = QString(tr("Starting App: %1")).arg(loading.section("::",1,50)); per = -1;
  }
  if(per>0){ ui->progressBar->setValue(per); }
  else{ ui->progressBar->setRange(0,0); } //loading indicator
  ui->label_text->setText(txt);
  if(!icon.isEmpty()){ui->label_icon->setPixmap( LXDG::findIcon(icon, "Lumina-DE").pixmap(64,64) ); }
  this->raise();
  this->show();
  this->update();
  QApplication::processEvents();
}

void BootSplash::showText(QString txt){ //will only update the text, not the icon/progress
  ui->label_text->setText(txt);
  this->show();
  this->update();
  QApplication::processEvents();
}
<commit_msg>Add a couple more options for the tip of the day.<commit_after>#include "BootSplash.h"
#include "ui_BootSplash.h"

#include <LuminaXDG.h>
#include <LUtils.h>
#include <LDesktopUtils.h>

BootSplash::BootSplash() : QWidget(0, Qt::SplashScreen | Qt::X11BypassWindowManagerHint | Qt::WindowStaysOnTopHint | Qt::WindowDoesNotAcceptFocus), ui(new Ui::BootSplash){
  ui->setupUi(this);
  this->setObjectName("LuminaBootSplash"); //for theme styling
  //Center the window on the primary screen
  QPoint ctr = QApplication::desktop()->screenGeometry().center();
  this->move( ctr.x()-(this->width()/2), ctr.y()-(this->height()/2) );
  generateTipOfTheDay();
  ui->label_version->setText( QString(tr("Version %1")).arg(LDesktopUtils::LuminaDesktopVersion()) );
}

void BootSplash::generateTipOfTheDay(){
  int index = qrand()%7; //Make sure this number matches the length of the case below (max value +1)
  QString tip;
  switch(index){
    case 0:
	tip = tr("This desktop is powered by coffee, coffee, and more coffee."); break;
    case 1:
	tip = tr("Keep up with desktop news!")+"\n\nwww.lumina-desktop.org"; break;
    case 2:
	tip = tr("There is a full handbook of information about the desktop available online.")+"\n\nwww.lumina-desktop.org/handbook"; break;
    case 3:
	tip = tr("Want to change the interface? Everything is customizable in the desktop configuration!"); break;
    case 4:
	tip = tr("Lumina can easily reproduce the interface from most other desktop environments."); break;
    case 5:
	tip = tr("This desktop is generously sponsored by iXsystems")+"\n\nwww.ixsystems.com"; break;
    case 6:
	tip = "\""+tr("I have never been hurt by what I have not said")+"\"\n\n- Calvin Coolidge -"; break;
  }
  ui->label_welcome->setText( tip);
}

void BootSplash::showScreen(QString loading){ //update icon, text, and progress
  QString txt, icon;
  int per = 0;
  if(loading=="init"){
    txt = tr("Initializing Session …"); per = 10;
    icon = "preferences-system-login";
  }else if(loading=="settings"){
    txt = tr("Loading System Settings …"); per = 20;
    icon = "user-home";
  }else if(loading=="user"){
    txt = tr("Loading User Preferences …"); per = 30;
    icon = "preferences-desktop-user";
  }else if(loading=="systray"){
    txt = tr("Preparing System Tray …"); per = 40;
    icon = "preferences-plugin";
  }else if(loading=="wm"){
    txt = tr("Starting Window Manager …"); per = 50;
    icon = "preferences-system-windows-actions";
  }else if(loading=="apps"){
    txt = tr("Detecting Applications …"); per = 60;
    icon = "preferences-desktop-icons";
  }else if(loading=="menus"){
    txt = tr("Preparing Menus …"); per = 70;
    icon = "preferences-system-windows";
  }else if(loading=="desktop"){
    txt = tr("Preparing Workspace …"); per = 80;
    icon = "preferences-desktop-wallpaper";
  }else if(loading=="final"){
    txt = tr("Finalizing …"); per = 90;
    icon = "start-here-lumina";
  }else if(loading.startsWith("app::")){
    txt = QString(tr("Starting App: %1")).arg(loading.section("::",1,50)); per = -1;
  }
  if(per>0){ ui->progressBar->setValue(per); }
  else{ ui->progressBar->setRange(0,0); } //loading indicator
  ui->label_text->setText(txt);
  if(!icon.isEmpty()){ui->label_icon->setPixmap( LXDG::findIcon(icon, "Lumina-DE").pixmap(64,64) ); }
  this->raise();
  this->show();
  this->update();
  QApplication::processEvents();
}

void BootSplash::showText(QString txt){ //will only update the text, not the icon/progress
  ui->label_text->setText(txt);
  this->show();
  this->update();
  QApplication::processEvents();
}
<|endoftext|>