<commit_before>
const Viewport = require('./viewport');
const RG = require('../src/battles');

// TODO: Refactor out of this file
/* Builds and returns two arrays. First contains all CSS classNames of
 * cells to be rendered, and the second one all characters to be rendered.*/
const getClassesAndChars = function(seen, cells, selCell) {
    const cssClasses = [];
    const asciiChars = [];

    let selX = -1;
    let selY = -1;

    if (selCell !== null) {
        selX = selCell.getX();
        selY = selCell.getY();
    }

    // TODO: Prevents a bug, if player wants to see inventory right after
    // Load. Should render the visible cells properly though.
    if (!seen) {
        cssClasses.fill('cell-not-seen', 0, cells.length - 1);
        asciiChars.fill('X', 0, cells.length - 1);
        return [cssClasses, asciiChars];
    }

    for (let i = 0; i < cells.length; i++) {
        const cell = cells[i];
        const cellIndex = seen.indexOf(cell);
        const visibleToPlayer = cellIndex < 0 ? false : true;

        let cellClass = RG.getCssClassForCell(cell, visibleToPlayer);
        const cellChar = RG.getCharForCell(cell, visibleToPlayer);

        if (selX === cell.getX() && selY === cell.getY()) {
            cellClass = 'cell-target-selected';
        }

        if (!visibleToPlayer) {
            if (cell.isExplored()) {cellClass += ' cell-not-seen';}
        }
        cssClasses.push(cellClass);
        asciiChars.push(cellChar);
    }

    return [cssClasses, asciiChars];
};

const getClassesAndCharsWithRLE = function(seen, cells, selCell, anim, styles = {}) {
    let prevChar = null;
    let prevClass = null;
    let charRL = 0;
    let classRL = 0;

    const cssClasses = [];
    const asciiChars = [];

    let selX = -1;
    let selY = -1;

    if (selCell) {
        selX = selCell.getX();
        selY = selCell.getY();
    }

    // TODO: Prevents a bug, if player wants to see inventory right after
    // Load. Should render the visible cells properly though.
    if (!seen) {
        cssClasses.fill('cell-not-seen', 0, cells.length - 1);
        asciiChars.fill('X', 0, cells.length - 1);
        return [cssClasses, asciiChars];
    }

    let cellClass = '';
    let cellChar = '';

    for (let i = 0; i < cells.length; i++) {
        const cell = cells[i];
        const cellX = cell.getX();
        const cellY = cell.getY();

        const cellIndex = seen.indexOf(cell);
        const visibleToPlayer = cellIndex < 0 ? false : true;

        cellClass = RG.getCssClassForCell(cell, visibleToPlayer);
        cellChar = RG.getCharForCell(cell, visibleToPlayer);

        // Useless to animate non-visible cells
        if (visibleToPlayer && anim) {
            const key = cellX + ',' + cellY;
            if (anim[key]) {
                cellClass = anim[key].className;
                cellChar = anim[key].char;
            }
        }

        if (cell.isAtXY(selX, selY)) {
            if (styles.selectedCell) {
                cellClass = styles.selectedCell;
            }
            else {
                cellClass = 'cell-target-selected';
            }
        }

        if (!visibleToPlayer) {
            if (cell.isExplored()) {cellClass += ' cell-not-seen';}
        }

        const finishRLE = (cellClass !== prevClass) && prevClass
            || (cellChar !== prevChar) && prevChar;

        if (finishRLE) {
            cssClasses.push([classRL, prevClass]);
            classRL = 1;
            asciiChars.push([charRL, prevChar]);
            charRL = 1;
        }
        else {
            ++classRL;
            ++charRL;
        }

        prevChar = cellChar;
        prevClass = cellClass;
    }

    // Need to add the remaining cells
    if (classRL > 0) {cssClasses.push([classRL, cellClass]);}
    if (charRL > 0) {asciiChars.push([charRL, cellChar]);}

    return [cssClasses, asciiChars];
};

/* Same as above but optimized for showing the full map in the game editor.
*  Does not take into account cells seen by player. */
const getClassesAndCharsFullMap = function(cells, selCell) {
    const cssClasses = [];
    const asciiChars = [];

    let selX = -1;
    let selY = -1;

    if (selCell !== null) {
        selX = selCell.getX();
        selY = selCell.getY();
    }

    for (let i = 0; i < cells.length; i++) {
        const cell = cells[i];

        let cellClass = RG.getCssClassFullMap(cell);
        const cellChar = RG.getCharFullMap(cell);

        if (selX === cell.getX() && selY === cell.getY()) {
            cellClass = 'cell-target-selected';
        }

        cssClasses.push(cellClass);
        asciiChars.push(cellChar);
    }

    return [cssClasses, asciiChars];
};

/* Returns the CSS classes + characters to be rendered using RLE. */
const getClassesAndCharsFullMapWithRLE = function(cells, selCell) {
    let prevChar = null;
    let prevClass = null;
    let charRL = 0;
    let classRL = 0;

    const cssClasses = [];
    const asciiChars = [];

    let selMap = null;
    if (selCell) {
        selMap = new Map();
        selCell.forEach(cell => {
            selMap.set(cell.getX() + ',' + cell.getY(), cell);
        });
    }

    let cellClass = '';
    let cellChar = '';

    for (let i = 0; i < cells.length; i++) {
        const cell = cells[i];

        cellClass = RG.getCssClassFullMap(cell);
        cellChar = RG.getCharFullMap(cell);

        if (selMap) {
            const [x, y] = [cell.getX(), cell.getY()];
            if (selMap.has(x + ',' + y)) {
                cellClass = 'cell-target-selected';
            }
        }

        const finishRLE = (cellClass !== prevClass) && prevClass
            || (cellChar !== prevChar) && prevChar;

        if (finishRLE) {
            cssClasses.push([classRL, prevClass]);
            classRL = 1;
            asciiChars.push([charRL, prevChar]);
            charRL = 1;
        }
        else {
            ++classRL;
            ++charRL;
        }

        prevChar = cellChar;
        prevClass = cellClass;
    }

    // Need to add the remaining cells
    if (classRL > 0) {cssClasses.push([classRL, cellClass]);}
    if (charRL > 0) {asciiChars.push([charRL, cellChar]);}

    return [cssClasses, asciiChars];

};

/* Creates a screen with viewport set to given parameters. */
const Screen = function(viewX, viewY) {
    this.viewportX = viewX;
    this.viewportY = viewY;
    this.selectedCell = null;
    this.styles = {};
    let _charRows = [];
    let _classRows = [];
    let _mapShown = false;

    this.viewport = new Viewport(viewX, viewY);

    /* Returns the leftmost X-coordinate of the viewport. */
    this.getStartX = function() {
        return this.viewport.startX;
    };

    this.setSelectedCell = function(cell) {
        this.selectedCell = cell;
    };

    this.setViewportXY = function(x, y) {
        this.viewportX = x;
        this.viewportY = y;
        this.viewport.setViewportXY(x, y);

        _charRows = [];
        _classRows = [];
        for (let yy = 0; yy < y; yy++) {
            _charRows.push([]);
            _classRows.push([]);
        }
    };

    this.setMapShown = function(mapShown) {
        _mapShown = mapShown;
    };

    this.getCharRows = function() {
        return _charRows;
    };

    this.getClassRows = function() {
        return _classRows;
    };

    this._initRender = function(playX, playY, map) {
        if (!_mapShown) {
            this.setViewportXY(this.viewportX,
                this.viewportY);
        }
        else {
            this.setViewportXY(map.cols, map.rows);
        }
        this.viewport.getCellsInViewPort(playX, playY, map);

        this.startX = this.viewport.startX;
        this.endX = this.viewport.endX;
        this.startY = this.viewport.startY;
        this.endY = this.viewport.endY;
    };

    /* 'Renders' the ASCII screen and style classes based on player's
     * coordinate, map and visible cells. */
    this.render = function(playX, playY, map, visibleCells) {
        this._initRender(playX, playY, map);
        let yCount = 0;
        for (let y = this.viewport.startY; y <= this.viewport.endY; ++y) {
            const rowCellData = this.viewport.getCellRow(y);
            const classesChars = getClassesAndChars(visibleCells,
                rowCellData, this.selectedCell);

            _classRows[yCount] = classesChars[0];
            _charRows[yCount] = classesChars[1];
            ++yCount;
        }

    };

    this.renderWithRLE = function(playX, playY, map, visibleCells, anim) {
        this._initRender(playX, playY, map);
        let yCount = 0;
        for (let y = this.viewport.startY; y <= this.viewport.endY; ++y) {
            const rowCellData = this.viewport.getCellRow(y);
            const classesChars = getClassesAndCharsWithRLE(visibleCells,
                rowCellData, this.selectedCell, anim, this.styles);

            _classRows[yCount] = classesChars[0];
            _charRows[yCount] = classesChars[1];
            ++yCount;
        }
    };

    /* Renders the full map as visible. */
    this.renderFullMap = function(map) {
        this.startX = 0;
        this.endX = map.cols - 1;
        this.startY = 0;
        this.endY = map.rows - 1;

        for (let y = 0; y < map.rows; ++y) {
            const classesChars = getClassesAndCharsFullMap(
                map.getCellRowFast(y), this.selectedCell);

            _classRows[y] = classesChars[0];
            _charRows[y] = classesChars[1];
        }
    };

    this.renderFullMapWithRLE = function(map) {
        this.startX = 0;
        this.endX = map.cols - 1;
        this.startY = 0;
        this.endY = map.rows - 1;

        for (let y = 0; y < map.rows; ++y) {
            const classesChars = getClassesAndCharsFullMapWithRLE(
                map.getCellRowFast(y), this.selectedCell);

            _classRows[y] = classesChars[0];
            _charRows[y] = classesChars[1];
        }
    };

    this.clear = function() {
        _classRows = [];
        _charRows = [];
        this.selectedCell = null;
        this.startX = 0;
        this.endX = -1;
        this.startY = 0;
        this.endY = -1;
        this.styles = {};
    };

    this.setStyle = function(name, value) {
        this.styles[name] = value;
    };

};

module.exports = Screen;
<commit_msg>Added printRenderedChars.<commit_after>
const Viewport = require('./viewport');
const RG = require('../src/battles');

// TODO: Refactor out of this file
/* Builds and returns two arrays. First contains all CSS classNames of
 * cells to be rendered, and the second one all characters to be rendered.*/
const getClassesAndChars = function(seen, cells, selCell) {
    const cssClasses = [];
    const asciiChars = [];

    let selX = -1;
    let selY = -1;

    if (selCell !== null) {
        selX = selCell.getX();
        selY = selCell.getY();
    }

    // TODO: Prevents a bug, if player wants to see inventory right after
    // Load. Should render the visible cells properly though.
    if (!seen) {
        cssClasses.fill('cell-not-seen', 0, cells.length - 1);
        asciiChars.fill('X', 0, cells.length - 1);
        return [cssClasses, asciiChars];
    }

    for (let i = 0; i < cells.length; i++) {
        const cell = cells[i];
        const cellIndex = seen.indexOf(cell);
        const visibleToPlayer = cellIndex < 0 ? false : true;

        let cellClass = RG.getCssClassForCell(cell, visibleToPlayer);
        const cellChar = RG.getCharForCell(cell, visibleToPlayer);

        if (selX === cell.getX() && selY === cell.getY()) {
            cellClass = 'cell-target-selected';
        }

        if (!visibleToPlayer) {
            if (cell.isExplored()) {cellClass += ' cell-not-seen';}
        }
        cssClasses.push(cellClass);
        asciiChars.push(cellChar);
    }

    return [cssClasses, asciiChars];
};

const getClassesAndCharsWithRLE = function(seen, cells, selCell, anim, styles = {}) {
    let prevChar = null;
    let prevClass = null;
    let charRL = 0;
    let classRL = 0;

    const cssClasses = [];
    const asciiChars = [];

    let selX = -1;
    let selY = -1;

    if (selCell) {
        selX = selCell.getX();
        selY = selCell.getY();
    }

    // TODO: Prevents a bug, if player wants to see inventory right after
    // Load. Should render the visible cells properly though.
    if (!seen) {
        cssClasses.fill('cell-not-seen', 0, cells.length - 1);
        asciiChars.fill('X', 0, cells.length - 1);
        return [cssClasses, asciiChars];
    }

    let cellClass = '';
    let cellChar = '';

    for (let i = 0; i < cells.length; i++) {
        const cell = cells[i];
        const cellX = cell.getX();
        const cellY = cell.getY();

        const cellIndex = seen.indexOf(cell);
        const visibleToPlayer = cellIndex < 0 ? false : true;

        cellClass = RG.getCssClassForCell(cell, visibleToPlayer);
        cellChar = RG.getCharForCell(cell, visibleToPlayer);

        // Useless to animate non-visible cells
        if (visibleToPlayer && anim) {
            const key = cellX + ',' + cellY;
            if (anim[key]) {
                cellClass = anim[key].className;
                cellChar = anim[key].char;
            }
        }

        if (cell.isAtXY(selX, selY)) {
            if (styles.selectedCell) {
                cellClass = styles.selectedCell;
            }
            else {
                cellClass = 'cell-target-selected';
            }
        }

        if (!visibleToPlayer) {
            if (cell.isExplored()) {cellClass += ' cell-not-seen';}
        }

        const finishRLE = (cellClass !== prevClass) && prevClass
            || (cellChar !== prevChar) && prevChar;

        if (finishRLE) {
            cssClasses.push([classRL, prevClass]);
            classRL = 1;
            asciiChars.push([charRL, prevChar]);
            charRL = 1;
        }
        else {
            ++classRL;
            ++charRL;
        }

        prevChar = cellChar;
        prevClass = cellClass;
    }

    // Need to add the remaining cells
    if (classRL > 0) {cssClasses.push([classRL, cellClass]);}
    if (charRL > 0) {asciiChars.push([charRL, cellChar]);}

    return [cssClasses, asciiChars];
};

/* Same as above but optimized for showing the full map in the game editor.
*  Does not take into account cells seen by player. */
const getClassesAndCharsFullMap = function(cells, selCell) {
    const cssClasses = [];
    const asciiChars = [];

    let selX = -1;
    let selY = -1;

    if (selCell !== null) {
        selX = selCell.getX();
        selY = selCell.getY();
    }

    for (let i = 0; i < cells.length; i++) {
        const cell = cells[i];

        let cellClass = RG.getCssClassFullMap(cell);
        const cellChar = RG.getCharFullMap(cell);

        if (selX === cell.getX() && selY === cell.getY()) {
            cellClass = 'cell-target-selected';
        }

        cssClasses.push(cellClass);
        asciiChars.push(cellChar);
    }

    return [cssClasses, asciiChars];
};

/* Returns the CSS classes + characters to be rendered using RLE. */
const getClassesAndCharsFullMapWithRLE = function(cells, selCell) {
    let prevChar = null;
    let prevClass = null;
    let charRL = 0;
    let classRL = 0;

    const cssClasses = [];
    const asciiChars = [];

    let selMap = null;
    if (selCell) {
        selMap = new Map();
        selCell.forEach(cell => {
            selMap.set(cell.getX() + ',' + cell.getY(), cell);
        });
    }

    let cellClass = '';
    let cellChar = '';

    for (let i = 0; i < cells.length; i++) {
        const cell = cells[i];

        cellClass = RG.getCssClassFullMap(cell);
        cellChar = RG.getCharFullMap(cell);

        if (selMap) {
            const [x, y] = [cell.getX(), cell.getY()];
            if (selMap.has(x + ',' + y)) {
                cellClass = 'cell-target-selected';
            }
        }

        const finishRLE = (cellClass !== prevClass) && prevClass
            || (cellChar !== prevChar) && prevChar;

        if (finishRLE) {
            cssClasses.push([classRL, prevClass]);
            classRL = 1;
            asciiChars.push([charRL, prevChar]);
            charRL = 1;
        }
        else {
            ++classRL;
            ++charRL;
        }

        prevChar = cellChar;
        prevClass = cellClass;
    }

    // Need to add the remaining cells
    if (classRL > 0) {cssClasses.push([classRL, cellClass]);}
    if (charRL > 0) {asciiChars.push([charRL, cellChar]);}

    return [cssClasses, asciiChars];

};

/* Creates a screen with viewport set to given parameters. */
const Screen = function(viewX, viewY) {
    this.viewportX = viewX;
    this.viewportY = viewY;
    this.selectedCell = null;
    this.styles = {};
    let _charRows = [];
    let _classRows = [];
    let _mapShown = false;

    this.viewport = new Viewport(viewX, viewY);

    /* Returns the leftmost X-coordinate of the viewport. */
    this.getStartX = function() {
        return this.viewport.startX;
    };

    this.setSelectedCell = function(cell) {
        this.selectedCell = cell;
    };

    this.setViewportXY = function(x, y) {
        this.viewportX = x;
        this.viewportY = y;
        this.viewport.setViewportXY(x, y);

        _charRows = [];
        _classRows = [];
        for (let yy = 0; yy < y; yy++) {
            _charRows.push([]);
            _classRows.push([]);
        }
    };

    this.setMapShown = function(mapShown) {
        _mapShown = mapShown;
    };

    this.getCharRows = function() {
        return _charRows;
    };

    this.getClassRows = function() {
        return _classRows;
    };

    this._initRender = function(playX, playY, map) {
        if (!_mapShown) {
            this.setViewportXY(this.viewportX,
                this.viewportY);
        }
        else {
            this.setViewportXY(map.cols, map.rows);
        }
        this.viewport.getCellsInViewPort(playX, playY, map);

        this.startX = this.viewport.startX;
        this.endX = this.viewport.endX;
        this.startY = this.viewport.startY;
        this.endY = this.viewport.endY;
    };

    /* 'Renders' the ASCII screen and style classes based on player's
     * coordinate, map and visible cells. */
    this.render = function(playX, playY, map, visibleCells) {
        this._initRender(playX, playY, map);
        let yCount = 0;
        for (let y = this.viewport.startY; y <= this.viewport.endY; ++y) {
            const rowCellData = this.viewport.getCellRow(y);
            const classesChars = getClassesAndChars(visibleCells,
                rowCellData, this.selectedCell);

            _classRows[yCount] = classesChars[0];
            _charRows[yCount] = classesChars[1];
            ++yCount;
        }

    };

    this.renderWithRLE = function(playX, playY, map, visibleCells, anim) {
        this._initRender(playX, playY, map);
        let yCount = 0;
        for (let y = this.viewport.startY; y <= this.viewport.endY; ++y) {
            const rowCellData = this.viewport.getCellRow(y);
            const classesChars = getClassesAndCharsWithRLE(visibleCells,
                rowCellData, this.selectedCell, anim, this.styles);

            _classRows[yCount] = classesChars[0];
            _charRows[yCount] = classesChars[1];
            ++yCount;
        }
    };

    /* Renders the full map as visible. */
    this.renderFullMap = function(map) {
        this.startX = 0;
        this.endX = map.cols - 1;
        this.startY = 0;
        this.endY = map.rows - 1;

        for (let y = 0; y < map.rows; ++y) {
            const classesChars = getClassesAndCharsFullMap(
                map.getCellRowFast(y), this.selectedCell);

            _classRows[y] = classesChars[0];
            _charRows[y] = classesChars[1];
        }
    };

    this.renderFullMapWithRLE = function(map) {
        this.startX = 0;
        this.endX = map.cols - 1;
        this.startY = 0;
        this.endY = map.rows - 1;

        for (let y = 0; y < map.rows; ++y) {
            const classesChars = getClassesAndCharsFullMapWithRLE(
                map.getCellRowFast(y), this.selectedCell);

            _classRows[y] = classesChars[0];
            _charRows[y] = classesChars[1];
        }
    };

    this.clear = function() {
        _classRows = [];
        _charRows = [];
        this.selectedCell = null;
        this.startX = 0;
        this.endX = -1;
        this.startY = 0;
        this.endY = -1;
        this.styles = {};
    };

    this.setStyle = function(name, value) {
        this.styles[name] = value;
    };

    /* Prints the chars in screen. */
    this.printRenderedChars = () => {
      _charRows.forEach(row => {
        console.log(row.join(''));
      });
    };

};

module.exports = Screen;
<|endoftext|>


<commit_before>// Karma configuration file, see link for more information
// https://karma-runner.github.io/0.13/config/configuration-file.html

module.exports = function (config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine', 'angular-cli'],
    plugins: [
      require('karma-jasmine'),
      require('karma-chrome-launcher'),
      require('karma-remap-istanbul'),
      require('angular-cli/plugins/karma')
    ],
    files: [
      { pattern: './src/test.ts', watched: false }
    ],
    preprocessors: {
      './src/test.ts': ['angular-cli']
    },
    mime: {
      'text/x-typescript': ['ts','tsx']
    },
    remapIstanbulReporter: {
      reports: {
        html: 'coverage',
        lcovonly: './coverage/coverage.lcov'
      }
    },
    angularCli: {
      config: './angular-cli.json',
      environment: 'dev'
    },
    reporters: config.angularCli && config.angularCli.codeCoverage
              ? ['progress', 'karma-remap-istanbul']
              : ['progress'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['Chrome'],
    singleRun: false
  });
};
<commit_msg>Fix karma configuration to use @angular/cli instead of angular-cli<commit_after>// Karma configuration file, see link for more information
// https://karma-runner.github.io/0.13/config/configuration-file.html

module.exports = function (config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine', '@angular/cli'],
    plugins: [
      require('karma-jasmine'),
      require('karma-chrome-launcher'),
      require('karma-remap-istanbul'),
      require('@angular/cli/plugins/karma')
    ],
    files: [
      { pattern: './src/test.ts', watched: false }
    ],
    preprocessors: {
      './src/test.ts': ['@angular/cli']
    },
    mime: {
      'text/x-typescript': ['ts','tsx']
    },
    remapIstanbulReporter: {
      reports: {
        html: 'coverage',
        lcovonly: './coverage/coverage.lcov'
      }
    },
    angularCli: {
      config: './angular-cli.json',
      environment: 'dev'
    },
    reporters: config.angularCli && config.angularCli.codeCoverage
              ? ['progress', 'karma-remap-istanbul']
              : ['progress'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['Chrome'],
    singleRun: false
  });
};
<|endoftext|>


<commit_before>Meteor.startup(function() {
    return SEO.config({
        title: 'Ceerebro',
        meta: {
            'description': 'Ceerebro is a secure credentials storage platform',
            'viewport': 'width=device-width, initial-scale=1, maximum-scale=1',
            'mobile-web-app-capable': 'yes',
            'apple-mobile-web-app-capable': 'yes'
        },
        link: {
            'icon': 'img/icons/favicon.ico',
            'apple-touch-icon': 'img/icons/favicon.ico',
            'manifest': 'manifest.json'
        }
    });
});

// Autoform error hook
AutoForm.addHooks(null, {
    onError: function (formType, error) {
        //Alert is already displayed on form
        if (formType == 'pre-submit validation') {
            return;
        }

        log(error);
        throwAlert(error.toString());
    }
});

// Hide spinner with for NProgress bar
NProgress.configure({
    showSpinner: false
});<commit_msg>Updating SEO config<commit_after>Meteor.startup(function() {
    return SEO.config({
        title: 'Ceerebro',
        meta: {
            'description': 'Ceerebro is a secure credentials storage platform',
            'viewport': 'width=device-width, initial-scale=1, maximum-scale=1',
            'mobile-web-app-capable': 'yes',
            'apple-mobile-web-app-capable': 'yes'
        },
        link: {
            'icon': 'favicon.png',
            'apple-touch-icon': 'apple-touch-icon-precomposed.png',
            'manifest': 'manifest.json'
        }
    });
});

// Autoform error hook
AutoForm.addHooks(null, {
    onError: function (formType, error) {
        //Alert is already displayed on form
        if (formType == 'pre-submit validation') {
            return;
        }

        log(error);
        throwAlert(error.toString());
    }
});

// Hide spinner with for NProgress bar
NProgress.configure({
    showSpinner: false
});<|endoftext|>


<commit_before>import React, { Component } from 'react';
import { browserHistory } from 'react-router/es';
import { connect } from 'react-redux/es';
import { Card, Image, Loader } from '../commons';
import { fetchCategory } from '../modules';

@connect(
  state => ({
    photos: state.carousel.home
  }),
  { fetchCategory }
)
class Home extends Component {
  state = { loading: true }
  /**
   * componentDidMount
   * - calls for fetching of initial photos for Home.
   * - updates state.carousel.home
   * - changes state of loading to false.
   */
  componentDidMount() {
    (async () => {
        await this.props.fetchCategory('home');
        this.setState({ loading: false });
    })();
  }
  /**
   * _onClick(arg)
   * - @param {String} category
   * - @return {Promise}
   * - calls for fetch of category of photos by ${category} to /api/v1.
   * - updates state.carousel.
   * - redirects to /portfolio/${category}.
   */
  async _onClick(category) {
    await this.props.fetchCategory(category);
    browserHistory.push(`/portfolio/${category}`);
  }
  render() {
    const { photos } = this.props;
    console.log(photos);
    if (this.state.loading) {
      return <Loader />;
    } else if (photos.length === 0) {
      return
No Photos Found
; // TODO: Find a better handler.
    }
    return (

          <Card
            photos={photos.family} // pass to AppCarousel the exact array of images needed.
            onClick={() => this._onClick('family')}
          >
            <Image src={photos[0]} />
          </Card>
          <Card
            photos={photos.portrait}
            onClick={() => this._onClick('portrait')}
          >
            <Image src={photos[1]} />
          </Card>

          <Card
            photos={photos.travel}
            onClick={() => this._onClick('travel')}
          >
            <Image src={photos[2]} />
          </Card>
          <Card
            photos={photos.wedding}
            onClick={() => this._onClick('wedding')}
          >
            <Image src={photos[3]} />
          </Card>

    );
  }
}

export default Home;
<commit_msg>Cleaned.<commit_after>import React, { Component } from 'react';
import { browserHistory } from 'react-router/es';
import { connect } from 'react-redux/es';
import { Card, Image, Loader } from '../commons';
import { fetchCategory } from '../modules';

@connect(
  state => ({
    photos: state.carousel.home
  }),
  { fetchCategory }
)
class Home extends Component {
  state = { loading: true }
  /**
   * componentDidMount
   * - calls for fetching of initial photos for Home.
   * - updates state.carousel.home
   * - changes state of loading to false.
   */
  componentDidMount() {
    (async () => {
        await this.props.fetchCategory('home');
        this.setState({ loading: false });
    })();
  }
  /**
   * _onClick(arg)
   * - @param {String} category
   * - @return {Promise}
   * - calls for fetch of category of photos by ${category} to /api/v1.
   * - updates state.carousel.
   * - redirects to /portfolio/${category}.
   */
  async _onClick(category) {
    await this.props.fetchCategory(category);
    browserHistory.push(`/portfolio/${category}`);
  }
  render() {
    const { photos } = this.props;
    if (this.state.loading) {
      return <Loader />;
    } else if (photos.length === 0) {
      return
No Photos Found
; // TODO: Find a better handler.
    }
    return (

          <Card
            photos={photos.family} // pass to AppCarousel the exact array of images needed.
            onClick={() => this._onClick('family')}
          >
            <Image src={photos[0]} />
          </Card>
          <Card
            photos={photos.portrait}
            onClick={() => this._onClick('portrait')}
          >
            <Image src={photos[1]} />
          </Card>

          <Card
            photos={photos.travel}
            onClick={() => this._onClick('travel')}
          >
            <Image src={photos[2]} />
          </Card>
          <Card
            photos={photos.wedding}
            onClick={() => this._onClick('wedding')}
          >
            <Image src={photos[3]} />
          </Card>

    );
  }
}

export default Home;
<|endoftext|>


<commit_before>import React from 'react'
import App from 'next/app'
import Head from 'next/head'
import { MuiThemeProvider } from '@material-ui/core/styles'
import CssBaseline from '@material-ui/core/CssBaseline'
import JssProvider from 'react-jss/lib/JssProvider'
import getPageContext from 'client/src/getPageContext'
import { setReturnUrl } from 'client/src/urls'
import ReactGA from 'react-ga'

const initializeGoogleAnalytics = () => {
  if (!process.env.GA_TRACKING_ID) {
    console.log("Google Analytics disabled")
    return
  }
  ReactGA.initialize(process.env.GA_TRACKING_ID, { debug: process.env.DEBUG_GA })
  ReactGA.pageview(window.location.pathname + window.location.search)
}

class MyApp extends App {
  constructor(props) {
    super(props)
    this.pageContext = getPageContext()
  }

  componentDidMount() {
    // Make the CSRF token available
    document.cookie = `csrfToken=${this.props.pageProps.csrfToken}`
    setReturnUrl(window.location.pathname)
    // Remove the server-side injected CSS.
    const jssStyles = document.querySelector('#jss-server-side')
    if (jssStyles && jssStyles.parentNode) {
      jssStyles.parentNode.removeChild(jssStyles)
    }
    initializeGoogleAnalytics()
  }

  render() {
    const { Component, pageProps } = this.props
    return (
      <>
        <Head>
          <title>Robinʼs Photos</title>
        </Head>
        {/* Wrap every page in Jss and Theme providers */}
        <JssProvider
          registry={this.pageContext.sheetsRegistry}
          generateClassName={this.pageContext.generateClassName}
        >
          {/* MuiThemeProvider makes the theme available down the React
              tree thanks to React context. */}
          <MuiThemeProvider
            theme={this.pageContext.theme}
            sheetsManager={this.pageContext.sheetsManager}
          >
            {/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */}
            <CssBaseline />
            {/* Pass pageContext to the _document though the renderPage enhancer
                to render collected styles on server side. */}
            <Component pageContext={this.pageContext} {...pageProps} />
          </MuiThemeProvider>
        </JssProvider>
      </>
    )
  }
}

export default MyApp
<commit_msg>CSRF cookie includes path<commit_after>import React from 'react'
import App from 'next/app'
import Head from 'next/head'
import { MuiThemeProvider } from '@material-ui/core/styles'
import CssBaseline from '@material-ui/core/CssBaseline'
import JssProvider from 'react-jss/lib/JssProvider'
import getPageContext from 'client/src/getPageContext'
import { setReturnUrl } from 'client/src/urls'
import ReactGA from 'react-ga'

const initializeGoogleAnalytics = () => {
  if (!process.env.GA_TRACKING_ID) {
    console.log("Google Analytics disabled")
    return
  }
  ReactGA.initialize(process.env.GA_TRACKING_ID, { debug: process.env.DEBUG_GA })
  ReactGA.pageview(window.location.pathname + window.location.search)
}

class MyApp extends App {
  constructor(props) {
    super(props)
    this.pageContext = getPageContext()
  }

  componentDidMount() {
    // Make the CSRF token available
    document.cookie = `csrfToken=${this.props.pageProps.csrfToken};path=/`
    setReturnUrl(window.location.pathname)
    // Remove the server-side injected CSS.
    const jssStyles = document.querySelector('#jss-server-side')
    if (jssStyles && jssStyles.parentNode) {
      jssStyles.parentNode.removeChild(jssStyles)
    }
    initializeGoogleAnalytics()
  }

  render() {
    const { Component, pageProps } = this.props
    return (
      <>
        <Head>
          <title>Robinʼs Photos</title>
        </Head>
        {/* Wrap every page in Jss and Theme providers */}
        <JssProvider
          registry={this.pageContext.sheetsRegistry}
          generateClassName={this.pageContext.generateClassName}
        >
          {/* MuiThemeProvider makes the theme available down the React
              tree thanks to React context. */}
          <MuiThemeProvider
            theme={this.pageContext.theme}
            sheetsManager={this.pageContext.sheetsManager}
          >
            {/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */}
            <CssBaseline />
            {/* Pass pageContext to the _document though the renderPage enhancer
                to render collected styles on server side. */}
            <Component pageContext={this.pageContext} {...pageProps} />
          </MuiThemeProvider>
        </JssProvider>
      </>
    )
  }
}

export default MyApp
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import './App.css';
import { Link } from "react-router-dom";
import Player from './Player.js';
import { saveAs } from 'file-saver';
const LC = require('literallycanvas');

class Canvas extends Component {
  state = {
    isLoading: true,
    users: "Not this"
  };

  constructor(props) {
    super(props);
    this.state = { sent: false, players: [] };

    this.send = this.send.bind(this);
    this.saveDrawing = this.saveDrawing.bind(this);
    this.setLC = this.setLC.bind(this);
  }

  async componentDidMount() {
    this.setState({ players: ['marshal', 'ankha', 'sherb', 'audie', 'raymond',
      'bob', 'marina'], currentPlayerIndex: 2 });
  }

  send() {
    this.setState({ sent: true, currentPlayerIndex: this.state.currentPlayerIndex + 1});
  }

  saveDrawing() {
    var filename = "drawing.png";
    this.state.lc.getImage().toBlob(function(blob) {
      saveAs(blob, filename);
    });
  }

  setLC(lc) {
    this.setState({lc: lc});
  }

  render() {
    const { players } = this.state;
    console.log(players);

    return (

        <Link to="/"><button>Back to home</button></Link>

GAME 00001

          {/*
            Dynamically render the player chain with a name list. The 'status'
            indicates whether they are done with their turn.
            Renders an arrow after the name, if they are not the final player.
          */}
          {players.map((name, index) => (
            <Player name={name} status={index - this.state.currentPlayerIndex} />
            {(index !== players.length - 1) ? → : null}
          ))}

Draw something based on the left image!

            <LC.LiterallyCanvasReactComponent onInit={this.setLC} imageURLPrefix="lc-assets/img" />
            <button onClick={this.saveDrawing}>Download drawing</button>
            {!this.state.sent && <button className="send-drawing" onClick={this.send}>Send</button>}
            {this.state.sent &&
Drawing sent!
}

    );
  }
}

export default Canvas;
<commit_msg>Add navbar to game screen.<commit_after>import React, { Component } from 'react';
import './App.css';
import { Link } from "react-router-dom";
import Player from './Player.js';
import { saveAs } from 'file-saver';
import Banner from './Banner';
const LC = require('literallycanvas');

class Canvas extends Component {
  state = {
    isLoading: true,
    users: "Not this"
  };

  constructor(props) {
    super(props);
    this.state = { sent: false, players: [] };

    this.send = this.send.bind(this);
    this.saveDrawing = this.saveDrawing.bind(this);
    this.setLC = this.setLC.bind(this);
  }

  async componentDidMount() {
    this.setState({ players: ['marshal', 'ankha', 'sherb', 'audie', 'raymond',
      'bob', 'marina'], currentPlayerIndex: 2 });
  }

  send() {
    this.setState({ sent: true, currentPlayerIndex: this.state.currentPlayerIndex + 1});
  }

  saveDrawing() {
    var filename = "drawing.png";
    this.state.lc.getImage().toBlob(function(blob) {
      saveAs(blob, filename);
    });
  }

  setLC(lc) {
    this.setState({lc: lc});
  }

  render() {
    const { players } = this.state;
    console.log(players);

    return (

        <Banner />

GAME 00001

          {/*
            Dynamically render the player chain with a name list. The 'status'
            indicates whether they are done with their turn.
            Renders an arrow after the name, if they are not the final player.
          */}
          {players.map((name, index) => (
            <Player name={name} status={index - this.state.currentPlayerIndex} />
            {(index !== players.length - 1) ? → : null}
          ))}

Draw something based on the left image!

            <LC.LiterallyCanvasReactComponent onInit={this.setLC} imageURLPrefix="lc-assets/img" />
            <button onClick={this.saveDrawing}>Download drawing</button>
            {!this.state.sent && <button className="send-drawing" onClick={this.send}>Send</button>}
            {this.state.sent &&
Drawing sent!
}

    );
  }
}

export default Canvas;
<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';

var reactMountRootId = 'app';

var App = React.createClass({
    render: function(){
        return(

WTF

        );
    }
});

ReactDOM.render(
    <App />,
    document.getElementById(reactMountRootId)
);<commit_msg>react skeleton<commit_after>import React from 'react';
import ReactDOM from 'react-dom';

var reactMountRootId = 'app';

var App = React.createClass({
    getInitialState: function(){
        return {
            currentText: "You got arrested at a bus stop :(",
            currentChoices: [
                {"text": "Shit on the ground"},
                {"text": "Go quietly"},
                {"text": "Play dead"}
            ]
        };
    },
    componentDidMount: function(){
        this.loadStoryFromServer();
    },
    loadStoryFromServer: function(){
        this.state.story = {};
    },
    render: function(){
        return(

                <Visualization />
                <Exposition text={this.state.currentText} />
                <ChoiceList choices={this.state.currentChoices} />

        );
    }
});

var Visualization = React.createClass({
    getInitialState: function(){
        return {};
    },
    componentDidMount: function(){

    },
    render: function(){
        return(

        );
    }
});

var Exposition = React.createClass({
    render: function(){
        return (

                {this.props.text}

        );
    }
});

var ChoiceList = React.createClass({
    render: function(){
        var choiceNodes = this.props.choices.map(function(choice){
            return(
                <Choice data={choice} />
            )
        });
        return (

                {choiceNodes}

        );
    }
});

var Choice = React.createClass({
    render: function(){
        return(

                {this.props.data.text}

        );
    }
});

ReactDOM.render(
    <App />,
    document.getElementById(reactMountRootId)
);<|endoftext|>


<commit_before>
const RG = require('./rg.js');
RG.System = require('./system.js');
RG.Map = require('./map.js');
RG.Time = require('./time.js');

/* Game engine which handles turn scheduling, systems updates and in-game
 * messaging between objects. */
const Engine = function(eventPool) {

    // Ignore GUI commands by default
    this.isGUICommand = () => false;
    this.doGUICommand = null;

    this.nextActor = null;
    this.animation = null;
    this.animationCallback = null;

    this._levelMap = {}; // All levels, ID -> level
    this._activeLevels = []; // Only these levels are simulated
    this._scheduler = new RG.Time.Scheduler();
    this._msg = new RG.MessageHandler();
    this._eventPool = eventPool;

    this.visibleCells = [];

    this._cache = {};

    this.getMessages = () => this._msg.getMessages();
    this.hasNewMessages = () => this._msg.hasNew();
    this.clearMessages = () => { this._msg.clear();};

    //--------------------------------------------------------------
    // ECS SYSTEMS
    //--------------------------------------------------------------

    // These systems updated after each action. Order is important, for example,
    // animations should be seen before actors are killed
    this.systemOrder = ['Disability', 'SpiritBind', 'BaseAction',
        'Attack', 'Chat',
        'Shop', 'SpellCast',
        'SpellEffect', 'Missile', 'Movement', 'Animation', 'Damage',
        'Battle', 'Skills', 'ExpPoints', 'Communication',
        'Events'];

    this.systems = {};
    this.systems.Disability = new RG.System.Disability(
        ['Stun', 'Paralysis']);
    this.systems.SpiritBind = new RG.System.SpiritBind(['SpiritBind']);
    this.systems.BaseAction = new RG.System.BaseAction(['Pickup',
        'UseStairs', 'OpenDoor']);
    this.systems.Chat = new RG.System.Chat(['Chat']);
    this.systems.Shop = new RG.System.Shop(['Transaction']);
    this.systems.Attack = new RG.System.Attack(['Attack']);
    this.systems.Missile = new RG.System.Missile(['Missile']);
    this.systems.Movement = new RG.System.Movement(['Movement']);
    this.systems.SpellCast = new RG.System.SpellCast(['SpellCast',
        'PowerDrain']);
    this.systems.SpellEffect = new RG.System.SpellEffect(
        ['SpellRay', 'SpellCell', 'SpellMissile', 'SpellArea']);
    this.systems.Animation = new RG.System.Animation(
        ['Animation']);
    this.systems.Damage = new RG.System.Damage(['Damage', 'Health']);
    this.systems.Battle = new RG.System.Battle(['BattleOver', 'BattleOrder']);
    this.systems.Skills = new RG.System.Skills(['SkillsExp']);
    this.systems.ExpPoints = new RG.System.ExpPoints(
        ['ExpPoints', 'Experience']);
    this.systems.Communication = new RG.System.Communication(
        ['Communication']);
    this.systems.Events = new RG.System.Events(['Event']);

    // Systems updated once each game loop (once for each player action)
    this.loopSystemOrder = ['Hunger'];
    this.loopSystems = {};
    this.loopSystems.Hunger = new RG.System.Hunger(['Action', 'Hunger']);

    // Time-based systems are added to the scheduler directly
    this.timeSystems = {};

    const effects = new RG.System.TimeEffects(['Expiration', 'Poison']);

    this.updateSystems = function() {
        for (let i = 0; i < this.systemOrder.length; i++) {
            const sysName = this.systemOrder[i];
            this.systems[sysName].update();
        }
    };

    this.updateLoopSystems = function() {
        for (let i = 0; i < this.loopSystemOrder.length; i++) {
            const sysName = this.loopSystemOrder[i];
            this.loopSystems[sysName].update();
        }
    };

    //--------------------------------------------------------------
    // GAME LOOPS
    //--------------------------------------------------------------

    /* Main update command. Call this either with cmd to perform, or object
     * containing the pressed keycode. */
    this.update = function(obj) {
        if (!this.isGameOver()) {
            this.clearMessages();

            if (this.nextActor !== null) {
                if (obj.hasOwnProperty('code')) {
                    const code = obj.code;
                    if (this.isGUICommand(code)) {
                        this.doGUICommand(code);
                    }
                    else {
                        this.updateGameLoop({code});
                    }
                }
                else {
                    this.updateGameLoop(obj);
                }
            }

        }
        else {
            this.clearMessages();
            this._eventPool.emitEvent(RG.EVT_MSG, {msg: 'GAME OVER!'});
            this.simulateGame(100);
        }
    };

    /* Updates the loop by executing one player command, then looping until
     * next player command.*/
    this.updateGameLoop = function(obj) {
        this.playerCommand(obj);
        this.currPlayer = this.nextActor;
        this.nextActor = this.getNextActor();

        // Next/act until player found, then go back waiting for key...
        while (!this.nextActor.isPlayer() && !this.isGameOver()) {
            const action = this.nextActor.nextAction();
            this.doAction(action);

            this.updateSystems(); // All systems for each actor

            this.nextActor = this.getNextActor();
            if (RG.isNullOrUndef([this.nextActor])) {
                RG.err('Game.Engine', 'updateGameLoop',
                    'Game loop out of events! Fatal!');
                break; // if errors suppressed (testing), breaks the loop
            }
        }

        this.updateLoopSystems(); // Loop systems once per player action

    };

    /* Simulates the game without a player.*/
    this.simulateGame = function(nTurns = 1) {
        for (let i = 0; i < nTurns; i++) {
            this.nextActor = this.getNextActor();

            if (!this.nextActor.isPlayer()) {
                const action = this.nextActor.nextAction();
                this.doAction(action);
                this.updateSystems();
            }
            else {
                RG.err('Engine', 'simulateGame',
                    "Doesn't work with player.");
            }
        }
    };

    this.playerCommand = function(obj) {
        if (this.nextActor.isPlayer() === false) {
            let msg = '';
            if (this.nextActor.hasOwnProperty('isEvent')) {
                msg = 'Expected player, got an event: ';
            }
            else {
                msg = 'Expected player, got: ' + this.nextActor.getName();
            }
            msg += '\n' + JSON.stringify(this.nextActor);
            RG.err('Engine', 'playerCommand', msg);
        }
        const action = this.nextActor.nextAction(obj);
        this.doAction(action);
        this.updateSystems();
        this.playerCommandCallback(this.nextActor);
    };

    //--------------------------------------------------------------
    // MANAGING ACTIVE LEVELS
    //--------------------------------------------------------------

    this.numActiveLevels = () => this._activeLevels.length;

    this.hasLevel = function(level) {
        return this._levelMap.hasOwnProperty(level.getID());
    };

    this.getLevels = function() {
        return Object.values(this._levelMap);
    };

    /* Adds one level to the game database.*/
    this.addLevel = function(level) {
        const id = level.getID();
        if (!this._levelMap.hasOwnProperty(id)) {
            this._levelMap[level.getID()] = level;
        }
        else {
            RG.err('Game.Engine', 'addLevel',
                'Level ID ' + id + ' already exists!');
        }
    };

    this.removeLevels = function(levels) {
        levels.forEach(level => {
            const id = level.getID();
            if (this._levelMap.hasOwnProperty(id)) {
                const index = this._activeLevels.indexOf(id);
                if (index >= 0) {
                    this._activeLevels.splice(index, 1);

                    const removedLevel = this._levelMap[id];
                    if (removedLevel) {
                        const rmvActors = removedLevel.getActors();
                        for (let i = 0; i < rmvActors.length; i++) {
                            rmvActors[i].get('Action').disable();
                        }
                    }
                }
                delete this._levelMap[id];
            }
            else {
                RG.err('Game.Engine', 'removeLevels',
                    `No level with ID ${id}`);
            }
        });
    };

    /* Adds an active level. Only these levels are simulated.*/
    this.addActiveLevel = function(level) {
        const levelID = level.getID();
        const index = this._activeLevels.indexOf(levelID);

        // Check if a level must be removed
        if (this._activeLevels.length === (RG.MAX_ACTIVE_LEVELS)) {
            if (index === -1) { // No room for new level, pop one
                const removedLevelID = this._activeLevels.pop();
                const removedLevel = this._levelMap[removedLevelID];
                if (removedLevel) {
                    const rmvActors = removedLevel.getActors();
                    for (let i = 0; i < rmvActors.length; i++) {
                        rmvActors[i].get('Action').disable();
                    }
                    RG.debug(this, 'Removed active level to make space...');
                }
                else {
                    const levelIDs = Object.keys(this._levelMap).join(', ');
                    RG.err('Game.Engine', 'addActiveLevel',
                        `Failed to remove level ID ${removedLevelID}.
                        IDs: ${levelIDs}`);
                }
            }
            else { // Level already in actives, move to the front only
                this._activeLevels.splice(index, 1);
                this._activeLevels.unshift(levelID);
                RG.debug(this, 'Moved level to the front of active levels.');
            }
        }

        // This is a new level, enable all actors by enabling Action comp
        if (index === -1) {
            this._activeLevels.unshift(levelID);
            const actActors = level.getActors();
            for (let j = 0; j < actActors.length; j++) {
                actActors[j].get('Action').enable();
            }
        }
    };

    this.isGameOver = () => false;

    this.isActiveLevel = level => {
        const index = this._activeLevels.indexOf(level.getID());
        return index >= 0;
    };

    /* Adds a TimeSystem into the engine. Each system can be updated with given
     * intervals instead of every turn or loop.*/
    this.addTimeSystem = function(name, obj) {
        this.timeSystems[name] = obj;
        // Must schedule the system to activate it
        const updateEvent = new RG.Time.GameEvent(100,
            obj.update.bind(obj), true, 0);
        this.addEvent(updateEvent);
    };
    this.addTimeSystem('TimeEffects', effects);

    //--------------------------------------------------------------
    // EVENT LISTENING
    //--------------------------------------------------------------

    this.hasNotify = true;
    this.notify = function(evtName, args) {
        if (evtName === RG.EVT_DESTROY_ITEM) {
            const item = args.item;

            // chaining due to inventory container
            const owner = item.getOwner().getOwner();
            if (!owner.getInvEq().removeItem(item)) {
                RG.err('Game.Engine', 'notify - DESTROY_ITEM',
                    'Failed to remove item from inventory.');
            }
        }
        else if (evtName === RG.EVT_ACT_COMP_ADDED) {
            if (args.hasOwnProperty('actor')) {
                this.addActor(args.actor);
            }
            else {
                RG.err('Game.Engine', 'notify - ACT_COMP_ADDED',
                    'No actor specified for the event.');
            }
        }
        else if (evtName === RG.EVT_ACT_COMP_REMOVED) {
            if (args.hasOwnProperty('actor')) {
                this.removeActor(args.actor);
            }
            else {
                RG.err('Game.Engine', 'notify - ACT_COMP_REMOVED',
                    'No actor specified for the event.');
            }
        }
        else if (evtName === RG.EVT_ACT_COMP_ENABLED) {
            if (args.hasOwnProperty('actor')) {
                this.addActor(args.actor);
            }
            else {
                RG.err('Game.Engine', 'notify - ACT_COMP_ENABLED',
                    'No actor specified for the event.');
            }
        }
        else if (evtName === RG.EVT_ACT_COMP_DISABLED) {
            if (args.hasOwnProperty('actor')) {
                this.removeActor(args.actor);
            }
            else {
                RG.err('Game', 'notify - ACT_COMP_DISABLED',
                    'No actor specified for the event.');
            }
        }
        else if (evtName === RG.EVT_LEVEL_PROP_ADDED) {
            if (args.propType === 'actors') {
                if (this.isActiveLevel(args.level)) {
                    // args.obj is actor
                    args.obj.get('Action').enable();
                }
            }
        }
        else if (evtName === RG.EVT_LEVEL_CHANGED) {
            const actor = args.actor;
            if (actor.isPlayer()) {
                this.addActiveLevel(actor.getLevel());
                args.src.onExit();
                args.src.onFirstExit();
                args.target.onEnter();
                args.target.onFirstEnter();
            }
        }
        else if (evtName === RG.EVT_ANIMATION) {
            if (this.canPlayerSeeAnimation(args.animation)) {
                if (this.animationCallback) {
                    this.animation = args.animation;
                    this.animationCallback(this.animation);
                }
            }
        }
    };
    this._eventPool.listenEvent(RG.EVT_DESTROY_ITEM, this);
    this._eventPool.listenEvent(RG.EVT_ACT_COMP_ADDED, this);
    this._eventPool.listenEvent(RG.EVT_ACT_COMP_REMOVED, this);
    this._eventPool.listenEvent(RG.EVT_ACT_COMP_ENABLED, this);
    this._eventPool.listenEvent(RG.EVT_ACT_COMP_DISABLED, this);
    this._eventPool.listenEvent(RG.EVT_LEVEL_PROP_ADDED, this);
    this._eventPool.listenEvent(RG.EVT_LEVEL_CHANGED, this);
    this._eventPool.listenEvent(RG.EVT_ANIMATION, this);

    this.hasAnimation = function() {
        return this.animation !== null &&
            this.animation.hasFrames();
    };

    this.setVisibleArea = (level, cells) => {
        this.visibleLevelID = level.getID();
        this.visibleCells = cells;
        this._cache.visibleCoord = {};
    };

    /* Returns true if player can see the given animation. In general, true
     * whenever animation contains at least one cell visible to the player. */
    this.canPlayerSeeAnimation = animation => {
        if (animation.levelID === this.visibleLevelID) {
            if (Object.keys(this._cache.visibleCoord).length === 0) {
                this.visibleCells.forEach(cell => {
                    const [x, y] = [cell.getX(), cell.getY()];
                    this._cache.visibleCoord[x + ',' + y] = true;
                });
            }
            return animation.hasCoord(this._cache.visibleCoord);
        }
        return false;
    };

    this.enableAnimations = () => {
        this.systems['Animation'].disableAnimations();
    };

    this.disableAnimations = () => {
        this.systems['Animation'].disableAnimations();
    };

};

//--------------------------------------------------------------
// SCHEDULING/ACTIONS
//--------------------------------------------------------------

/* Returns next actor from the scheduling queue.*/
Engine.prototype.getNextActor = function() {
    return this._scheduler.next();
};

/* Adds an actor to the scheduler. */
Engine.prototype.addActor = function(actor) {
    this._scheduler.add(actor, true, 0);
};

/* Removes an actor from a scheduler.*/
Engine.prototype.removeActor = function(actor) {
    this._scheduler.remove(actor);
};

/* Adds an event to the scheduler.*/
Engine.prototype.addEvent = function(gameEvent) {
    const repeat = gameEvent.getRepeat();
    const offset = gameEvent.getOffset();
    this._scheduler.add(gameEvent, repeat, offset);
};

/* Performs one game action.*/
Engine.prototype.doAction = function(action) {
    this._scheduler.setAction(action);
    action.doAction();
    if (action.hasOwnProperty('energy')) {
        if (action.hasOwnProperty('actor')) {
            const actor = action.actor;
            if (actor.has('Action')) {
                actor.get('Action').addEnergy(action.energy);
            }
        }
    }
};

module.exports = Engine;
<commit_msg>Added System.AreaEffects.<commit_after>
const RG = require('./rg.js');
RG.System = require('./system.js');
RG.Map = require('./map.js');
RG.Time = require('./time.js');

/* Game engine which handles turn scheduling, systems updates and in-game
 * messaging between objects. */
const Engine = function(eventPool) {

    // Ignore GUI commands by default
    this.isGUICommand = () => false;
    this.doGUICommand = null;

    this.nextActor = null;
    this.animation = null;
    this.animationCallback = null;

    this._levelMap = {}; // All levels, ID -> level
    this._activeLevels = []; // Only these levels are simulated
    this._scheduler = new RG.Time.Scheduler();
    this._msg = new RG.MessageHandler();
    this._eventPool = eventPool;

    this.visibleCells = [];

    this._cache = {};

    this.getMessages = () => this._msg.getMessages();
    this.hasNewMessages = () => this._msg.hasNew();
    this.clearMessages = () => { this._msg.clear();};

    //--------------------------------------------------------------
    // ECS SYSTEMS
    //--------------------------------------------------------------

    // These systems updated after each action. Order is important, for example,
    // animations should be seen before actors are killed
    this.systemOrder = ['AreaEffects', 'Disability', 'SpiritBind', 'BaseAction',
        'Attack', 'Chat',
        'Shop', 'SpellCast',
        'SpellEffect', 'Missile', 'Movement', 'Animation', 'Damage',
        'Battle', 'Skills', 'ExpPoints', 'Communication',
        'Events'];

    this.systems = {};
    this.systems.Disability = new RG.System.Disability(
        ['Stun', 'Paralysis']);
    this.systems.SpiritBind = new RG.System.SpiritBind(['SpiritBind']);
    this.systems.BaseAction = new RG.System.BaseAction(['Pickup',
        'UseStairs', 'OpenDoor']);
    this.systems.Chat = new RG.System.Chat(['Chat']);
    this.systems.Shop = new RG.System.Shop(['Transaction']);
    this.systems.Attack = new RG.System.Attack(['Attack']);
    this.systems.Missile = new RG.System.Missile(['Missile']);
    this.systems.Movement = new RG.System.Movement(['Movement']);
    this.systems.SpellCast = new RG.System.SpellCast(['SpellCast',
        'PowerDrain']);
    this.systems.SpellEffect = new RG.System.SpellEffect(
        ['SpellRay', 'SpellCell', 'SpellMissile', 'SpellArea']);
    this.systems.Animation = new RG.System.Animation(
        ['Animation']);
    this.systems.Damage = new RG.System.Damage(['Damage', 'Health']);
    this.systems.Battle = new RG.System.Battle(['BattleOver', 'BattleOrder']);
    this.systems.Skills = new RG.System.Skills(['SkillsExp']);
    this.systems.ExpPoints = new RG.System.ExpPoints(
        ['ExpPoints', 'Experience']);
    this.systems.Communication = new RG.System.Communication(
        ['Communication']);
    this.systems.Events = new RG.System.Events(['Event']);
    this.systems.AreaEffects = new RG.System.AreaEffects(['Fire']);

    // Systems updated once each game loop (once for each player action)
    this.loopSystemOrder = ['Hunger'];
    this.loopSystems = {};
    this.loopSystems.Hunger = new RG.System.Hunger(['Action', 'Hunger']);

    // Time-based systems are added to the scheduler directly
    this.timeSystems = {};

    const effects = new RG.System.TimeEffects(['Expiration', 'Poison']);

    this.updateSystems = function() {
        for (let i = 0; i < this.systemOrder.length; i++) {
            const sysName = this.systemOrder[i];
            this.systems[sysName].update();
        }
    };

    this.updateLoopSystems = function() {
        for (let i = 0; i < this.loopSystemOrder.length; i++) {
            const sysName = this.loopSystemOrder[i];
            this.loopSystems[sysName].update();
        }
    };

    //--------------------------------------------------------------
    // GAME LOOPS
    //--------------------------------------------------------------

    /* Main update command. Call this either with cmd to perform, or object
     * containing the pressed keycode. */
    this.update = function(obj) {
        if (!this.isGameOver()) {
            this.clearMessages();

            if (this.nextActor !== null) {
                if (obj.hasOwnProperty('code')) {
                    const code = obj.code;
                    if (this.isGUICommand(code)) {
                        this.doGUICommand(code);
                    }
                    else {
                        this.updateGameLoop({code});
                    }
                }
                else {
                    this.updateGameLoop(obj);
                }
            }

        }
        else {
            this.clearMessages();
            this._eventPool.emitEvent(RG.EVT_MSG, {msg: 'GAME OVER!'});
            this.simulateGame(100);
        }
    };

    /* Updates the loop by executing one player command, then looping until
     * next player command.*/
    this.updateGameLoop = function(obj) {
        this.playerCommand(obj);
        this.currPlayer = this.nextActor;
        this.nextActor = this.getNextActor();

        // Next/act until player found, then go back waiting for key...
        while (!this.nextActor.isPlayer() && !this.isGameOver()) {
            const action = this.nextActor.nextAction();
            this.doAction(action);

            this.updateSystems(); // All systems for each actor

            this.nextActor = this.getNextActor();
            if (RG.isNullOrUndef([this.nextActor])) {
                RG.err('Game.Engine', 'updateGameLoop',
                    'Game loop out of events! Fatal!');
                break; // if errors suppressed (testing), breaks the loop
            }
        }

        this.updateLoopSystems(); // Loop systems once per player action

    };

    /* Simulates the game without a player.*/
    this.simulateGame = function(nTurns = 1) {
        for (let i = 0; i < nTurns; i++) {
            this.nextActor = this.getNextActor();

            if (!this.nextActor.isPlayer()) {
                const action = this.nextActor.nextAction();
                this.doAction(action);
                this.updateSystems();
            }
            else {
                RG.err('Engine', 'simulateGame',
                    "Doesn't work with player.");
            }
        }
    };

    this.playerCommand = function(obj) {
        if (this.nextActor.isPlayer() === false) {
            let msg = '';
            if (this.nextActor.hasOwnProperty('isEvent')) {
                msg = 'Expected player, got an event: ';
            }
            else {
                msg = 'Expected player, got: ' + this.nextActor.getName();
            }
            msg += '\n' + JSON.stringify(this.nextActor);
            RG.err('Engine', 'playerCommand', msg);
        }
        const action = this.nextActor.nextAction(obj);
        this.doAction(action);
        this.updateSystems();
        this.playerCommandCallback(this.nextActor);
    };

    //--------------------------------------------------------------
    // MANAGING ACTIVE LEVELS
    //--------------------------------------------------------------

    this.numActiveLevels = () => this._activeLevels.length;

    this.hasLevel = function(level) {
        return this._levelMap.hasOwnProperty(level.getID());
    };

    this.getLevels = function() {
        return Object.values(this._levelMap);
    };

    /* Adds one level to the game database.*/
    this.addLevel = function(level) {
        const id = level.getID();
        if (!this._levelMap.hasOwnProperty(id)) {
            this._levelMap[level.getID()] = level;
        }
        else {
            RG.err('Game.Engine', 'addLevel',
                'Level ID ' + id + ' already exists!');
        }
    };

    this.removeLevels = function(levels) {
        levels.forEach(level => {
            const id = level.getID();
            if (this._levelMap.hasOwnProperty(id)) {
                const index = this._activeLevels.indexOf(id);
                if (index >= 0) {
                    this._activeLevels.splice(index, 1);

                    const removedLevel = this._levelMap[id];
                    if (removedLevel) {
                        const rmvActors = removedLevel.getActors();
                        for (let i = 0; i < rmvActors.length; i++) {
                            rmvActors[i].get('Action').disable();
                        }
                    }
                }
                delete this._levelMap[id];
            }
            else {
                RG.err('Game.Engine', 'removeLevels',
                    `No level with ID ${id}`);
            }
        });
    };

    /* Adds an active level. Only these levels are simulated.*/
    this.addActiveLevel = function(level) {
        const levelID = level.getID();
        const index = this._activeLevels.indexOf(levelID);

        // Check if a level must be removed
        if (this._activeLevels.length === (RG.MAX_ACTIVE_LEVELS)) {
            if (index === -1) { // No room for new level, pop one
                const removedLevelID = this._activeLevels.pop();
                const removedLevel = this._levelMap[removedLevelID];
                if (removedLevel) {
                    const rmvActors = removedLevel.getActors();
                    for (let i = 0; i < rmvActors.length; i++) {
                        rmvActors[i].get('Action').disable();
                    }
                    RG.debug(this, 'Removed active level to make space...');
                }
                else {
                    const levelIDs = Object.keys(this._levelMap).join(', ');
                    RG.err('Game.Engine', 'addActiveLevel',
                        `Failed to remove level ID ${removedLevelID}.
                        IDs: ${levelIDs}`);
                }
            }
            else { // Level already in actives, move to the front only
                this._activeLevels.splice(index, 1);
                this._activeLevels.unshift(levelID);
                RG.debug(this, 'Moved level to the front of active levels.');
            }
        }

        // This is a new level, enable all actors by enabling Action comp
        if (index === -1) {
            this._activeLevels.unshift(levelID);
            const actActors = level.getActors();
            for (let j = 0; j < actActors.length; j++) {
                actActors[j].get('Action').enable();
            }
        }
    };

    this.isGameOver = () => false;

    this.isActiveLevel = level => {
        const index = this._activeLevels.indexOf(level.getID());
        return index >= 0;
    };

    /* Adds a TimeSystem into the engine. Each system can be updated with given
     * intervals instead of every turn or loop.*/
    this.addTimeSystem = function(name, obj) {
        this.timeSystems[name] = obj;
        // Must schedule the system to activate it
        const updateEvent = new RG.Time.GameEvent(100,
            obj.update.bind(obj), true, 0);
        this.addEvent(updateEvent);
    };
    this.addTimeSystem('TimeEffects', effects);

    //--------------------------------------------------------------
    // EVENT LISTENING
    //--------------------------------------------------------------

    this.hasNotify = true;
    this.notify = function(evtName, args) {
        if (evtName === RG.EVT_DESTROY_ITEM) {
            const item = args.item;

            // chaining due to inventory container
            const owner = item.getOwner().getOwner();
            if (!owner.getInvEq().removeItem(item)) {
                RG.err('Game.Engine', 'notify - DESTROY_ITEM',
                    'Failed to remove item from inventory.');
            }
        }
        else if (evtName === RG.EVT_ACT_COMP_ADDED) {
            if (args.hasOwnProperty('actor')) {
                this.addActor(args.actor);
            }
            else {
                RG.err('Game.Engine', 'notify - ACT_COMP_ADDED',
                    'No actor specified for the event.');
            }
        }
        else if (evtName === RG.EVT_ACT_COMP_REMOVED) {
            if (args.hasOwnProperty('actor')) {
                this.removeActor(args.actor);
            }
            else {
                RG.err('Game.Engine', 'notify - ACT_COMP_REMOVED',
                    'No actor specified for the event.');
            }
        }
        else if (evtName === RG.EVT_ACT_COMP_ENABLED) {
            if (args.hasOwnProperty('actor')) {
                this.addActor(args.actor);
            }
            else {
                RG.err('Game.Engine', 'notify - ACT_COMP_ENABLED',
                    'No actor specified for the event.');
            }
        }
        else if (evtName === RG.EVT_ACT_COMP_DISABLED) {
            if (args.hasOwnProperty('actor')) {
                this.removeActor(args.actor);
            }
            else {
                RG.err('Game', 'notify - ACT_COMP_DISABLED',
                    'No actor specified for the event.');
            }
        }
        else if (evtName === RG.EVT_LEVEL_PROP_ADDED) {
            if (args.propType === 'actors') {
                if (this.isActiveLevel(args.level)) {
                    // args.obj is actor
                    args.obj.get('Action').enable();
                }
            }
        }
        else if (evtName === RG.EVT_LEVEL_CHANGED) {
            const actor = args.actor;
            if (actor.isPlayer()) {
                this.addActiveLevel(actor.getLevel());
                args.src.onExit();
                args.src.onFirstExit();
                args.target.onEnter();
                args.target.onFirstEnter();
            }
        }
        else if (evtName === RG.EVT_ANIMATION) {
            if (this.canPlayerSeeAnimation(args.animation)) {
                if (this.animationCallback) {
                    this.animation = args.animation;
                    this.animationCallback(this.animation);
                }
            }
        }
    };
    this._eventPool.listenEvent(RG.EVT_DESTROY_ITEM, this);
    this._eventPool.listenEvent(RG.EVT_ACT_COMP_ADDED, this);
    this._eventPool.listenEvent(RG.EVT_ACT_COMP_REMOVED, this);
    this._eventPool.listenEvent(RG.EVT_ACT_COMP_ENABLED, this);
    this._eventPool.listenEvent(RG.EVT_ACT_COMP_DISABLED, this);
    this._eventPool.listenEvent(RG.EVT_LEVEL_PROP_ADDED, this);
    this._eventPool.listenEvent(RG.EVT_LEVEL_CHANGED, this);
    this._eventPool.listenEvent(RG.EVT_ANIMATION, this);

    this.hasAnimation = function() {
        return this.animation !== null &&
            this.animation.hasFrames();
    };

    this.setVisibleArea = (level, cells) => {
        this.visibleLevelID = level.getID();
        this.visibleCells = cells;
        this._cache.visibleCoord = {};
    };

    /* Returns true if player can see the given animation. In general, true
     * whenever animation contains at least one cell visible to the player. */
    this.canPlayerSeeAnimation = animation => {
        if (animation.levelID === this.visibleLevelID) {
            if (Object.keys(this._cache.visibleCoord).length === 0) {
                this.visibleCells.forEach(cell => {
                    const [x, y] = [cell.getX(), cell.getY()];
                    this._cache.visibleCoord[x + ',' + y] = true;
                });
            }
            return animation.hasCoord(this._cache.visibleCoord);
        }
        return false;
    };

    this.enableAnimations = () => {
        this.systems['Animation'].disableAnimations();
    };

    this.disableAnimations = () => {
        this.systems['Animation'].disableAnimations();
    };

};

//--------------------------------------------------------------
// SCHEDULING/ACTIONS
//--------------------------------------------------------------

/* Returns next actor from the scheduling queue.*/
Engine.prototype.getNextActor = function() {
    return this._scheduler.next();
};

/* Adds an actor to the scheduler. */
Engine.prototype.addActor = function(actor) {
    this._scheduler.add(actor, true, 0);
};

/* Removes an actor from a scheduler.*/
Engine.prototype.removeActor = function(actor) {
    this._scheduler.remove(actor);
};

/* Adds an event to the scheduler.*/
Engine.prototype.addEvent = function(gameEvent) {
    const repeat = gameEvent.getRepeat();
    const offset = gameEvent.getOffset();
    this._scheduler.add(gameEvent, repeat, offset);
};

/* Performs one game action.*/
Engine.prototype.doAction = function(action) {
    this._scheduler.setAction(action);
    action.doAction();
    if (action.hasOwnProperty('energy')) {
        if (action.hasOwnProperty('actor')) {
            const actor = action.actor;
            if (actor.has('Action')) {
                actor.get('Action').addEnergy(action.energy);
            }
        }
    }
};

module.exports = Engine;
<|endoftext|>


<commit_before>/* global rm, mkdir, exec, ls*/
require('shelljs/global');
var fs = require('fs');
var ms = require('ms');

var start = new Date();

console.log('Building config...');
exec('webpack --entry \'./config.app.js\' --output-library \'config\' --output-file \'config.[hash].js\' --colors --progress');

function getBundleFilename() {
  var matches = ls('dist/config.*.js');
  if (!(matches && matches.length)) {
    throw new Error('Expected to find "dist/config.[hash].js"');
  }
  return matches[0].replace('dist/', '');
}

console.log('Updating "dist/index.html"...');
var indexHtml = fs.readFileSync('dist/index.html', 'utf8');
indexHtml = indexHtml.replace('<!-- config -->',
  '<script type="text/javascript" src="' + getBundleFilename() + '"></script>'
);
indexHtml.to('dist/index.html');

var end = new Date();
console.log('Config built in ' + ms(end - start));
<commit_msg>Fix config file hashing on app start<commit_after>/* global rm, mkdir, exec, ls, mv*/
require('shelljs/global');
var fs = require('fs');
var crypto = require('crypto');
var ms = require('ms');

var start = new Date();

// NOTE: Webpack's hash also uses the absolute path on the filesystem
// Since config is built in `start.sh` and apps can be on different
// servers and directory, we implement our own hashing using the file's content

function getHash(str) {
	var hash = crypto.createHash('md5');
	hash.update(str);
	return hash.digest('hex').substr(0, 20);
}

console.log('Building config...');
exec('webpack --entry \'./config.app.js\' --output-library \'config\' --output-file \'config.js\' --colors --progress');

var hash = getHash(fs.readFileSync('dist/config.js'));
var filename = 'config.' + hash + '.js';
console.log('Renaming to ' + filename + '...');
mv('-f', 'dist/config.js', 'dist/' + filename);

console.log('Updating "dist/index.html"...');
var indexHtml = fs.readFileSync('dist/index.html', 'utf8');
indexHtml = indexHtml.replace('<!-- config -->',
  '<script type="text/javascript" src="' + filename + '"></script>'
);
indexHtml.to('dist/index.html');

var end = new Date();
console.log('Config built in ' + ms(end - start));
<|endoftext|>


<commit_before>// Select elements
var $connection = document.getElementById("connection");
var $host = document.getElementById("host");
var $port = document.getElementById("port");
var $connect = document.getElementById("connect");

var $canvas = document.getElementById("canvas");

var showInterface = function(showCanvas) {
    if (showCanvas == false) {
        $canvas.style.display = "none";
        $connection.style.display = "block";
    }
    else {
        $canvas.style.display = "inline-block";
        $connection.style.display = "none";
    }
};

showInterface(false);

// Connection stuff
var makeUrl = function(host, port) {
    return "ws://" + host + ":" + port + "/whiteboard";
};

socket = null;

// Canvas stuff
if (!$canvas.getContext || !window.WebSocket) {
    var body = document.getElementsByTagName("body");
    body[0].innerHTML = "
Oops! Your browser doesn't support canvas or WebSockets!
";
}

var CW = 1280;
var CH = 720;

$canvas.width = CW;
$canvas.height = CH;

var ctx = $canvas.getContext('2d');

ctx.clearRect(0, 0, $canvas.width, $canvas.height);

ctx.fillStyle = "#ffffff";
ctx.fillRect(0, 0, $canvas.width, $canvas.height);

var clearCanvas = function() {
    ctx.clearRect(0, 0, $canvas.width, $canvas.height);
    ctx.fillStyle = "#ffffff";
    ctx.fillRect(0, 0, $canvas.width, $canvas.height);
};

var painting = false;

var drawQueue = [];
var lineQueue = [];

var paint = function(x, y, isLine) {
    drawQueue.push([x, y]);
    lineQueue.push(isLine);
}

var update = function() {

    ctx.strokeStyle = "#000000";
    ctx.lineJoin = "round";
    ctx.lineWidth = 3;

    var length = Math.min(drawQueue.length, lineQueue.length);
    for (var i = 0; i < length; i++) {

        ctx.beginPath();

        if (lineQueue[i] && i) {
            ctx.moveTo(drawQueue[i - 1][0], drawQueue[i - 1][1]);

            socket.send(
                "l_" +
                drawQueue[i - 1][0]
                + "_" +
                drawQueue[i - 1][1]
                + "_" +
                drawQueue[i][0]
                + "_" +
                drawQueue[i][1]
                + "_0"
            );
        }
        else {
            ctx.moveTo(drawQueue[i][0] - 1, drawQueue[i][1]);

            socket.send("p_" + drawQueue[i][0] + "_" + drawQueue[i][1] + "_0");
        }

        ctx.lineTo(drawQueue[i][0], drawQueue[i][1]);
        ctx.closePath();
        ctx.stroke();

    }

    drawQueue = [];
    lineQueue = [];

}

$canvas.addEventListener("mousedown", function(event) {

    painting = true;

    var mouseX, mouseY;
    mouseX = event.pageX - this.offsetLeft;
    mouseY = event.pageY - this.offsetTop;

    paint(mouseX, mouseY);
    update();

}, false);

$canvas.addEventListener("mousemove", function(event) {

    if (painting) {
        var mouseX, mouseY;
        mouseX = event.pageX - this.offsetLeft;
        mouseY = event.pageY - this.offsetTop;

        paint(mouseX, mouseY, true);
        update();
    }

}, false);

$canvas.addEventListener("mouseup", function(event) {

    painting = false;

}, false);

// Connection stuff
var connect = function() {

    var host = $host.value;
    var port = $port.value;

    var url = makeUrl(host, port);

    try {
        socket = new WebSocket(url);

        socket.onopen = function() {
            console.log("connected to " + url);

            showInterface(true);
        }

        socket.onmessage = function(msg) {
            var cmd = msg.data;

            var paintRegex = /p_\d+_\d+_\d+/g;
            var lineRegex = /l_\d+_\d+_\d+_\d+_\d+/g;

            if (paintRegex.test(cmd)) {
                var data = cmd.split("_");
                if (data.length == 4) {
                    var x = data[1];
                    var y = data[2];
                    var c = data[3];

                    ctx.strokeStyle = "#000000";
                    ctx.lineJoin = "round";
                    ctx.lineWidth = 3;

                    ctx.beginPath();
                    ctx.moveTo(x - 1, y);
                    ctx.lineTo(x, y);
                    ctx.closePath();
                    ctx.stroke();
                }
            }
            else if (lineRegex.test(cmd)) {
                var data = cmd.split("_")
                if (data.length == 6) {
                    var x1 = data[1];
                    var y1 = data[2];
                    var x2 = data[3];
                    var y2 = data[4];
                    var c = data[5];

                    ctx.strokeStyle = "#000000";
                    ctx.lineJoin = "round";
                    ctx.lineWidth = 3;

                    ctx.beginPath();
                    ctx.moveTo(x1, y1);
                    ctx.lineTo(x, y);
                    ctx.closePath();
                    ctx.stroke();
                }
            }
            else if (cmd == "c") {
                clearCanvas();
            }
        }

        socket.onerror = function(error) {
            console.log("error:");
            console.log(error);

            alert("error");
        }

        socket.onclose = function() {
            console.log("connection closed");

            reset();
        }
    }
    catch (error) {
        console.log("can't connect to " + url);

        reset();
    }

};

$connect.addEventListener("click", connect, false);

// General stuff
var reset = function() {
    clearCanvas();
    showInterface(false);
    socket = null;

    drawQueue = [];
    lineQueue = [];
};
<commit_msg>Update whiteboard.js - fix #1<commit_after>// Select elements
var $connection = document.getElementById("connection");
var $host = document.getElementById("host");
var $port = document.getElementById("port");
var $connect = document.getElementById("connect");

var $canvas = document.getElementById("canvas");

var showInterface = function(showCanvas) {
    if (showCanvas == false) {
        $canvas.style.display = "none";
        $connection.style.display = "block";
    }
    else {
        $canvas.style.display = "inline-block";
        $connection.style.display = "none";
    }
};

showInterface(false);

// Connection stuff
var makeUrl = function(host, port) {
    return "ws://" + host + ":" + port + "/whiteboard";
};

socket = null;

// Canvas stuff
if (!$canvas.getContext || !window.WebSocket) {
    var body = document.getElementsByTagName("body");
    body[0].innerHTML = "
Oops! Your browser doesn't support canvas or WebSockets!
";
}

var CW = 1280;
var CH = 720;

$canvas.width = CW;
$canvas.height = CH;

var ctx = $canvas.getContext('2d');

ctx.clearRect(0, 0, $canvas.width, $canvas.height);

ctx.fillStyle = "#ffffff";
ctx.fillRect(0, 0, $canvas.width, $canvas.height);

var clearCanvas = function() {
    ctx.clearRect(0, 0, $canvas.width, $canvas.height);
    ctx.fillStyle = "#ffffff";
    ctx.fillRect(0, 0, $canvas.width, $canvas.height);
};

var painting = false;

var drawQueue = [];
var lineQueue = [];

var paint = function(x, y, isLine) {
    drawQueue.push([x, y]);
    lineQueue.push(isLine);
}

var update = function() {
    ctx.strokeStyle = "#000000";
    ctx.lineJoin = "round";
    ctx.lineWidth = 3;

    var length = drawQueue.length;
    for (var i = 0; i < length; i++) {

        ctx.beginPath();

        if (lineQueue[i] && i != 0) {
            ctx.moveTo(drawQueue[i - 1][0], drawQueue[i - 1][1]);

            socket.send(
                "l_" +
                drawQueue[i - 1][0]
                + "_" +
                drawQueue[i - 1][1]
                + "_" +
                drawQueue[i][0]
                + "_" +
                drawQueue[i][1]
                + "_0"
            );
        }
        else {
            ctx.moveTo(drawQueue[i][0] - 1, drawQueue[i][1]);

            socket.send("p_" + drawQueue[i][0] + "_" + drawQueue[i][1] + "_0");
        }

        ctx.lineTo(drawQueue[i][0], drawQueue[i][1]);
        ctx.closePath();
        ctx.stroke();

    }
}

$canvas.addEventListener("mousedown", function(event) {

    painting = true;

    var mouseX, mouseY;
    mouseX = event.pageX - this.offsetLeft;
    mouseY = event.pageY - this.offsetTop;

    paint(mouseX, mouseY, false);
    update();

}, false);

$canvas.addEventListener("mousemove", function(event) {

    if (painting) {
        var mouseX, mouseY;
        mouseX = event.pageX - this.offsetLeft;
        mouseY = event.pageY - this.offsetTop;

        paint(mouseX, mouseY, true);
        update();
    }
    else {
        if (drawQueue.length != 0) drawQueue = [];
        if (lineQueue.length != 0) lineQueue = [];
    }

}, false);

$canvas.addEventListener("mouseup", function(event) {

    painting = false;

}, false);

// Connection stuff
var connect = function() {

    var host = $host.value;
    var port = $port.value;

    var url = makeUrl(host, port);

    try {
        socket = new WebSocket(url);

        socket.onopen = function() {
            console.log("connected to " + url);

            showInterface(true);
        }

        socket.onmessage = function(msg) {
            var cmd = msg.data;

            var paintRegex = /p_\d+_\d+_\d+/g;
            var lineRegex = /l_\d+_\d+_\d+_\d+_\d+/g;

            if (paintRegex.test(cmd)) {
                var data = cmd.split("_");
                if (data.length == 4) {
                    var x = parseInt(data[1]);
                    var y = parseInt(data[2]);
                    var c = parseInt(data[3]);

                    ctx.strokeStyle = "#000000";
                    ctx.lineJoin = "round";
                    ctx.lineWidth = 3;

                    ctx.beginPath();
                    ctx.moveTo(x - 1, y);
                    ctx.lineTo(x, y);
                    ctx.closePath();
                    ctx.stroke();
                }
            }
            else if (lineRegex.test(cmd)) {
                var data = cmd.split("_")
                if (data.length == 6) {
                    var x1 = parseInt(data[1]);
                    var y1 = parseInt(data[2]);
                    var x2 = parseInt(data[3]);
                    var y2 = parseInt(data[4]);
                    var c = parseInt(data[5]);

                    ctx.strokeStyle = "#000000";
                    ctx.lineJoin = "round";
                    ctx.lineWidth = 3;

                    ctx.beginPath();
                    ctx.moveTo(x1, y1);
                    ctx.lineTo(x2, y2);
                    ctx.closePath();
                    ctx.stroke();
                }
            }
            else if (cmd == "c") {
                clearCanvas();
            }
        }

        socket.onerror = function(error) {
            console.log("error:");
            console.log(error);

            alert("error");
        }

        socket.onclose = function() {
            console.log("connection closed");

            reset();
        }
    }
    catch (error) {
        console.log("can't connect to " + url);

        reset();
    }

};

$connect.addEventListener("click", connect, false);

// General stuff
var reset = function() {
    clearCanvas();
    showInterface(false);
    socket = null;

    drawQueue = [];
    lineQueue = [];
};
<|endoftext|>


<commit_before>/**
 *  _    __               _                ____
 * | |  / /__  __________(_)___  ____     / __ )__  ______ ___  ____
 * | | / / _ \/ ___/ ___/ / __ \/ __ \   / __  / / / / __ `__ \/ __ \
 * | |/ /  __/ /  (__  ) / /_/ / / / /  / /_/ / /_/ / / / / / / /_/ /
 * |___/\___/_/  /____/_/\____/_/ /_/  /_____/\__,_/_/ /_/ /_/ .___/
 *                                                          /_/
 * Bumps version of specific files within the package
 * for readability and cross-checking purposes.
 */
var fs = require('fs');
var shell = require('shelljs');
var bump = require('bump-regex');

// Ensure git directory clean
console.log(shell.exec('[[ $(git diff --shortstat 2> /dev/null | tail -n1) != "" ]] && echo "*"').code);

// // Update the file list with all desired version files
// var fileList = [
//   './index.js',
// ]

// // There could be an options object for reach file depending
// // on version specificity
// var options = {
//   type: process.argv[2],
//   key: 'version',
// }

// // Loop through each file in the list, pass it through the bump
// // function, then return the result
// fileList.forEach(file => fs.readFile(file, 'utf8', (err, data) => {
//   if ( err ) {
//     console.log(`Error: ${err}`);
//   } else {
//     options.str = data;

//     // Bump version of all the strings
//     bump(options, (err, out) => {
//       if ( err) {
//         console.log(`Error: ${err}`);
//       } else {
//         fs.writeFile(file, out.str, err => {
//           if (err) {
//             console.log(`Error: ${err}`);
//           } else {
//             console.log(`File bumped: ${file}`);
//           }
//         });
//       }
//     });
//   }
// }));<commit_msg>sns: conditional git exit<commit_after>/**
 *  _    __               _                ____
 * | |  / /__  __________(_)___  ____     / __ )__  ______ ___  ____
 * | | / / _ \/ ___/ ___/ / __ \/ __ \   / __  / / / / __ `__ \/ __ \
 * | |/ /  __/ /  (__  ) / /_/ / / / /  / /_/ / /_/ / / / / / / /_/ /
 * |___/\___/_/  /____/_/\____/_/ /_/  /_____/\__,_/_/ /_/ /_/ .___/
 *                                                          /_/
 * Bumps version of specific files within the package
 * for readability and cross-checking purposes.
 */
var fs = require('fs');
var shell = require('shelljs');
var bump = require('bump-regex');

// Ensure git directory clean
var command = '[[ $(git diff --shortstat 2> /dev/null | tail -n1) != "" ]] && echo "*"';
if ( shell.exec(command).code === 0) {
  console.log('You have uncommitted changes. Please clean then try again.');
  process.exit(-1);
}

// // Update the file list with all desired version files
// var fileList = [
//   './index.js',
// ]

// // There could be an options object for reach file depending
// // on version specificity
// var options = {
//   type: process.argv[2],
//   key: 'version',
// }

// // Loop through each file in the list, pass it through the bump
// // function, then return the result
// fileList.forEach(file => fs.readFile(file, 'utf8', (err, data) => {
//   if ( err ) {
//     console.log(`Error: ${err}`);
//   } else {
//     options.str = data;

//     // Bump version of all the strings
//     bump(options, (err, out) => {
//       if ( err) {
//         console.log(`Error: ${err}`);
//       } else {
//         fs.writeFile(file, out.str, err => {
//           if (err) {
//             console.log(`Error: ${err}`);
//           } else {
//             console.log(`File bumped: ${file}`);
//           }
//         });
//       }
//     });
//   }
// }));<|endoftext|>


<commit_before>/*
	---THIS IS NOT PRODUCTION READY---
	---An algorithm to Group by date for an array within a time frame---
        ---This algorith is written by Yousef Wadi 27-Oct-2014---
	---twitter: @ywadi, github:ywadi ---

*/

exports.groupBy = groupBy;

function generateKey(groupBySeconds , timestamp, offset)
{
	var keyDiff = (timestamp % groupBySeconds);
	return [(timestamp - keyDiff)+offset,keyDiff];
}

function generateSlots(dateStart, dateEnd, groupBy)
{
	var startKeyGen = generateKey(groupBy, dateStart, 0);
	var startHeadKey = startKeyGen[0];
	var keyStep = startKeyGen[1];

	var endKeyGen = generateKey(groupBy, dateEnd,0);
	var endTailKey = endKeyGen[0];

	var endKey = startHeadKey;

	var shift = dateStart - startHeadKey;

	var grid = {};
	while(endKey <= endTailKey)
	{
		grid[endKey+shift] = [];
		endKey+=groupBy;
	}

	return {"grid":grid,"offset":shift};

}

function groupBy(data, startDate, endDate, tsKey,groupDurationSec)
{
	var slotsAndOffsets = generateSlots(startDate,endDate, groupDurationSec);
	var slots = slotsAndOffsets.grid;
	var offset = slotsAndOffsets.offset;
	for(item in data)
	{
		var key = generateKey(groupDurationSec,data[item][tsKey]-offset,offset)[0];
		console.log(new Date(data[item][tsKey])+"===>"+new Date(generateKey(groupDurationSec,data[item][tsKey],0)[0])+"===>"+new Date(key));
		if(slots[key] != undefined)
		{
			slots[key].push(data[item]);
		}
	}
	return(slots);
}
<commit_msg>Removing all logs<commit_after>/*
	---THIS IS NOT PRODUCTION READY---
	---An algorithm to Group by date for an array within a time frame---
        ---This algorith is written by Yousef Wadi 27-Oct-2014---
	---twitter: @ywadi, github:ywadi ---

*/

exports.groupBy = groupBy;

function generateKey(groupBySeconds , timestamp, offset)
{
	var keyDiff = (timestamp % groupBySeconds);
	return [(timestamp - keyDiff)+offset,keyDiff];
}

function generateSlots(dateStart, dateEnd, groupBy)
{
	var startKeyGen = generateKey(groupBy, dateStart, 0);
	var startHeadKey = startKeyGen[0];
	var keyStep = startKeyGen[1];

	var endKeyGen = generateKey(groupBy, dateEnd,0);
	var endTailKey = endKeyGen[0];

	var endKey = startHeadKey;

	var shift = dateStart - startHeadKey;

	var grid = {};
	while(endKey <= endTailKey)
	{
		grid[endKey+shift] = [];
		endKey+=groupBy;
	}

	return {"grid":grid,"offset":shift};

}

function groupBy(data, startDate, endDate, tsKey,groupDurationSec)
{
	var slotsAndOffsets = generateSlots(startDate,endDate, groupDurationSec);
	var slots = slotsAndOffsets.grid;
	var offset = slotsAndOffsets.offset;
	for(item in data)
	{
		var key = generateKey(groupDurationSec,data[item][tsKey]-offset,offset)[0];
		if(slots[key] != undefined)
		{
			slots[key].push(data[item]);
		}
	}
	return(slots);
}
<|endoftext|>


<commit_before>lively.Config.add('modulesOnWorldLoad', "lively.ide.codeeditor.BetterConfig");

// set uer based on cloxp assignment, also take care of the l2l connection
// which won't work over the proxy
var cookie = document.cookie.split(";").detect(function(ea) { return ea.include("cloxp-assignment"); });
var port = cookie && Number(cookie.split("=").last());
if (port) {
  lively.whenLoaded(function(w) { $world.setCurrentUser("cloxp-user-" + port); })
  lively.Config.addOption("nodeJSWebSocketURL", 'http://lively-web.org:' + port + '/nodejs');
}
<commit_msg>localconfig: ensure nodejswebsocket url<commit_after>lively.Config.add('modulesOnWorldLoad', "lively.ide.codeeditor.BetterConfig");

// set uer based on cloxp assignment, also take care of the l2l connection
// which won't work over the proxy
var cookie = document.cookie.split(";").filter(function(ea) { return ea.indexOf("cloxp-assignment") > -1; })[0];
var cookieKV = cookie && cookie.split("=")
var port = cookieKV && Number(cookieKV[1]);
if (port) {
  lively.whenLoaded(function(w) { $world.setCurrentUser("cloxp-user-" + port); })
  lively.Config.addOption("nodeJSWebSocketURL", 'http://lively-web.org:' + port + '/nodejs');
}<|endoftext|>