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

var logger = null;
var objName = '';
var geom = null;
var table = null;
var tableArr = [];
var geodataTable = null;
var geodataTableArr = [];
var areaArr = [];
var pointNumber = 0;
var pageHeight = 0;
var pageWidth = 0;
var paper;

function log(msg) {
    //$('.log').val($('.log').val() + '\n' + msg);
}

function createGeodataRepoprt() {
    paper = Snap("#svg");
    prepare();
    pageHeight = $('.pg-height').val();
    pageWidth = $('.pg-width').val();
    $('#svg').css('width:', pageHeight);
    $('#svg').css('height:' + pageHeight);
    paper.rect(0, 0, pageHeight, pageWidth).attr({
        fill: "#bada55",
        stroke: "#000",
        strokeWidth: 5
    });

    var newtable = '';
    for(var i=0; i < geodataTableArr.length; i++) {
        newtable += '
' + $(geodataTableArr[i]).html() + '
'+areaArr[i]+' кв.м

';
    }
    var geodataReport = window.open('geodata-svg.html', 'Geodata');

    geodataReport.onload = function () {
//        $('#h', geodataReport.document).text(pageHeight);
//        $('#w', geodataReport.document).text(pageWidth);
        var data = $('#data', geodataReport.document);
        //data.html(newtable);
        data.html($('#svg').toggleClass('hidden'));
    };
    geodataReport.focus();
}

function createReport() {
    prepare();
    var newtable = '';
    for(var i=0; i < tableArr.length; i++) {
        newtable += '
' + $(tableArr[i]).html() + '
'+areaArr[i]+' кв.м

';
    }
    var report = window.open('coordreport.html', 'Report');
    report.onload = function () {
        //report.document.getElementById('coord').innerHTML = '
' + newtable + '
';
        var data = $('#coord', report.document);
        data.html(newtable);
        return false;
    };
    report.focus();
}

function prepare() {
    // Разделитель - пустая строка \n\n
    var format = new ol.format.WKT();
    geodataTable = [];
    tableArr = [];
    areaArr = [];
    var parcels = $('.coord-area')[0].textContent.split('\n\n');
    for (var i=0; i < parcels.length; i++) {
        var data = parcels[i].split('_');
        objName = data[0];
        shape = format.readGeometry(data[1]);
        areaArr.push(shape.getArea().toFixed(2));
        //log('Площадь объекта: ' + shape.getArea().toFixed(2));
        table = $('

');
        table.prepend('
' + objName + '
');
        geodataTable = $('

');
        geodataTable.prepend('' + objName + '');
        parseGeom(shape);
    }
}

function parseGeom(geom) {
    if (geom.getType() === 'Polygon') {
        log('"Геометрия ol.geom.Polygon"');
        // Сквозная нумерация
        //pointNumber = 0;
        createTableHeader();
        createGeodataHeader();
        var coords = geom.getCoordinates();
        table.append('
');
        $.each(coords, function(idx, val) {
            parseLinearRing(idx, val);
        });
        tableArr.push(table);
        geodataTableArr.push(geodataTable);
    }
    else if (geom.getType() === 'MutliPolgon') {
        log('Геометрия ol.geom.MutliPolgon');
    }
    else {
        log('Геометрия не распознана.');
    }
}

// в openlayers у полигона первая точка дублируется в конце!
function parseLinearRing(index, ring) {
    log('Обрабатывается контур ' + (index + 1));
    var data1 = [];
    var data2 = [];
    var geodata1 = [];
    var geodata2 = [];
    var firstPointName = ++pointNumber;
    var prefix = 'н';

    if (index > 0) {
        data1.push('—');
        data1.push('—');
        data1.push('—');
        data1.push('—');
        data1.push('—');

        geodata1.push('—');
        geodata1.push('—');
        geodata1.push('—');
        createTableData(data1, data2);
        createGeodata(geodata1, geodata2);
        geodata1 = [];
        data1 = [];
        firstPointName = --pointNumber;
    }
    for (var i = 0; i < ring.length; i++) {
        if (i < ring.length-1) {
            data1.push(prefix + pointNumber);
            geodata1.push(prefix + pointNumber);
            ++pointNumber;
        }
        else {
            data1.push(prefix + firstPointName);
            geodata1.push(prefix + firstPointName);
        }
        data1.push(ring[i][0]);
        data1.push(ring[i][1]);
        data1.push(' ');
        data1.push(' ');
        geodata1.push(' ');
        geodata1.push(' ');

        if (i < ring.length-1) {
            data2.push(' ');
            data2.push(' ');
            data2.push(' ');
            geodata2.push('');
            geodata2.push(getDirectionalAngle(
                {
                    x: ring[i + 1][0],
                    y: ring[i + 1][1]
                },
                {
                    x: ring[i][0],
                    y: ring[i][1]
                }));
            data2.push(getDirectionalAngle(
                {
                    x: ring[i + 1][0],
                    y: ring[i + 1][1]
                },
                {
                    x: ring[i][0],
                    y: ring[i][1]
                }));
            geodata2.push(getLenth(
                {
                    x: ring[i + 1][0],
                    y: ring[i + 1][1]
                },
                {
                    x: ring[i][0],
                    y: ring[i][1]
                }))
            data2.push(getLenth(
                {
                    x: ring[i + 1][0],
                    y: ring[i + 1][1]
                },
                {
                    x: ring[i][0],
                    y: ring[i][1]
                }));
        }
        createTableData(data1, data2);
        createGeodata(geodata1, geodata2);
        data1 = [];
        data2 = [];
        geodata1 = [];
        geodata2 = [];
    }
}

function getLenth(point, nextPoint) {
    var dx = nextPoint.x - point.x;
    var dy = nextPoint.y - point.y;
    return Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2)).toFixed(2);
}

function getDirectionalAngle(point, nextPoint) {
    var dx = nextPoint.x - point.x;
    var dy = nextPoint.y - point.y;
    if (dx === 0) {
        if (ddy < 0) {
            return '270° 0,0\'';
        }
        else {
            return '90° 0,0\'';
        }
    }
    else {
        var alfa = Math.abs(Math.atan(dy/dx) * (180/Math.PI));
        var angle;
        if (dx > 0 && dy > 0) {
            angle = alfa;
            return getDegreeAndMinit(angle);
        }
        else if (dx < 0 && dy > 0) {
            angle = 180 - alfa;
            return getDegreeAndMinit(angle);
        }
        else if (dx < 0 && dy < 0) {
            angle = 180 + alfa;
            return getDegreeAndMinit(angle);
        }
        else if (dx > 0 && dy < 0) {
            angle = 360 - alfa;
            return getDegreeAndMinit(angle);
        }
        else if (dx > 0 && dy === 0) {
            return '0° 0\'';
        }
        else if (dx < 0 && dy === 0) {
            return '180° 0\'';
        }
    }
}

function getDegreeAndMinit (angle) {
    var a = Math.floor(angle);
    var minit = (angle - a) * 60;
    return a + '° ' + minit.toFixed(1) + '\'';
}

function createTableHeader() {
    var header = $('
');
    header.addClass('coord-table-header');
    header.append($('').html('№'));
    var x = $('');
    x.addClass('coord-td');
    header.append(x.html('X, м'));
    var y = $('');
    y.addClass('coord-td');
    header.append(y.html('Y, м'));
    header.append($('').html('Дирекционный угол, ° \''));
    header.append($('').html('Расстояние, м'));
    table.append(header);
}

function createTableData(data1, data2) {
    var row = $('
');
    row.addClass('coord-table-row');
    row.append($('').html('' + data1[0] + ''));
    row.append($('').html('' + data1[1] + ''));
    row.append($('').html('' + data1[2] + '</spanp>'));
    row.append($('').html('' + data1[3] + ''));
    row.append($('').html('' + data1[4] + ''));
    table.append(row);
    if (data2 && data2.length > 0) {
        var row1 = $('
');
        row1.addClass('coord-table-row');
        row1.append($('').html('' + data2[0] + ''));
        row1.append($('').html('' + data2[1] + ''));
        row1.append($('').html('' + data2[2] + ''));
        row1.append($('').html('' + data2[3] + ''));
        row1.append($('').html('' + data2[4] + ''));
        table.append(row1);
    }
}

function createGeodataHeader() {
    var header = $('
');
    header.append($('').html('№'));
    header.append($('').html('Дир. угол'));
    header.append($('').html('Расст, м'));
    geodataTable.append(header);
}

function createGeodata(geodata1, geodata2) {
    var row = $('
');
    row.addClass('coord-table-row');
    row.append($('').html('' + geodata1[0] + ''));
    row.append($('').html('' + geodata1[1] + ''));
    row.append($('').html('' + geodata1[2] + '</spanp>'));
    geodataTable.append(row);
    if (geodata2 && geodata2.length > 0) {
        var row1 = $('
');
        row1.addClass('coord-table-row');
        row1.append($('').html('' + geodata2[0] + ''));
        row1.append($('').html('' + geodata2[1] + ''));
        row1.append($('').html('' + geodata2[2] + ''));
        geodataTable.append(row1);
    }
}<commit_msg>hotfix<commit_after>/*
 * The MIT License
 *
 * Copyright 2014 filippov.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

var logger = null;
var objName = '';
var geom = null;
var table = null;
var tableArr = [];
var geodataTable = null;
var geodataTableArr = [];
var areaArr = [];
var pointNumber = 0;
var pageHeight = 0;
var pageWidth = 0;
var paper;

function log(msg) {
    //$('.log').val($('.log').val() + '\n' + msg);
}

function createGeodataRepoprt() {
    paper = Snap("#svg");
    prepare();
    pageHeight = $('.pg-height').val();
    pageWidth = $('.pg-width').val();
    $('#svg').css('width', pageHeight);
    $('#svg').css('height', pageHeight);
    paper.rect(0, 0, pageHeight, pageWidth).attr({
        fill: "#bada55",
        stroke: "#000",
        strokeWidth: 5
    });

    var newtable = '';
    for(var i=0; i < geodataTableArr.length; i++) {
        newtable += '
' + $(geodataTableArr[i]).html() + '
'+areaArr[i]+' кв.м

';
    }
    var geodataReport = window.open('geodata-svg.html', 'Geodata');

    geodataReport.onload = function () {
//        $('#h', geodataReport.document).text(pageHeight);
//        $('#w', geodataReport.document).text(pageWidth);
        var data = $('#data', geodataReport.document);
        //data.html(newtable);
        data.html($('#svg').toggleClass('hidden'));
    };
    geodataReport.focus();
}

function createReport() {
    prepare();
    var newtable = '';
    for(var i=0; i < tableArr.length; i++) {
        newtable += '
' + $(tableArr[i]).html() + '
'+areaArr[i]+' кв.м

';
    }
    var report = window.open('coordreport.html', 'Report');
    report.onload = function () {
        //report.document.getElementById('coord').innerHTML = '
' + newtable + '
';
        var data = $('#coord', report.document);
        data.html(newtable);
        return false;
    };
    report.focus();
}

function prepare() {
    // Разделитель - пустая строка \n\n
    var format = new ol.format.WKT();
    geodataTable = [];
    tableArr = [];
    areaArr = [];
    var parcels = $('.coord-area')[0].textContent.split('\n\n');
    for (var i=0; i < parcels.length; i++) {
        var data = parcels[i].split('_');
        objName = data[0];
        shape = format.readGeometry(data[1]);
        areaArr.push(shape.getArea().toFixed(2));
        //log('Площадь объекта: ' + shape.getArea().toFixed(2));
        table = $('

');
        table.prepend('
' + objName + '
');
        geodataTable = $('

');
        geodataTable.prepend('' + objName + '');
        parseGeom(shape);
    }
}

function parseGeom(geom) {
    if (geom.getType() === 'Polygon') {
        log('"Геометрия ol.geom.Polygon"');
        // Сквозная нумерация
        //pointNumber = 0;
        createTableHeader();
        createGeodataHeader();
        var coords = geom.getCoordinates();
        table.append('
');
        $.each(coords, function(idx, val) {
            parseLinearRing(idx, val);
        });
        tableArr.push(table);
        geodataTableArr.push(geodataTable);
    }
    else if (geom.getType() === 'MutliPolgon') {
        log('Геометрия ol.geom.MutliPolgon');
    }
    else {
        log('Геометрия не распознана.');
    }
}

// в openlayers у полигона первая точка дублируется в конце!
function parseLinearRing(index, ring) {
    log('Обрабатывается контур ' + (index + 1));
    var data1 = [];
    var data2 = [];
    var geodata1 = [];
    var geodata2 = [];
    var firstPointName = ++pointNumber;
    var prefix = 'н';

    if (index > 0) {
        data1.push('—');
        data1.push('—');
        data1.push('—');
        data1.push('—');
        data1.push('—');

        geodata1.push('—');
        geodata1.push('—');
        geodata1.push('—');
        createTableData(data1, data2);
        createGeodata(geodata1, geodata2);
        geodata1 = [];
        data1 = [];
        firstPointName = --pointNumber;
    }
    for (var i = 0; i < ring.length; i++) {
        if (i < ring.length-1) {
            data1.push(prefix + pointNumber);
            geodata1.push(prefix + pointNumber);
            ++pointNumber;
        }
        else {
            data1.push(prefix + firstPointName);
            geodata1.push(prefix + firstPointName);
        }
        data1.push(ring[i][0]);
        data1.push(ring[i][1]);
        data1.push(' ');
        data1.push(' ');
        geodata1.push(' ');
        geodata1.push(' ');

        if (i < ring.length-1) {
            data2.push(' ');
            data2.push(' ');
            data2.push(' ');
            geodata2.push('');
            geodata2.push(getDirectionalAngle(
                {
                    x: ring[i + 1][0],
                    y: ring[i + 1][1]
                },
                {
                    x: ring[i][0],
                    y: ring[i][1]
                }));
            data2.push(getDirectionalAngle(
                {
                    x: ring[i + 1][0],
                    y: ring[i + 1][1]
                },
                {
                    x: ring[i][0],
                    y: ring[i][1]
                }));
            geodata2.push(getLenth(
                {
                    x: ring[i + 1][0],
                    y: ring[i + 1][1]
                },
                {
                    x: ring[i][0],
                    y: ring[i][1]
                }))
            data2.push(getLenth(
                {
                    x: ring[i + 1][0],
                    y: ring[i + 1][1]
                },
                {
                    x: ring[i][0],
                    y: ring[i][1]
                }));
        }
        createTableData(data1, data2);
        createGeodata(geodata1, geodata2);
        data1 = [];
        data2 = [];
        geodata1 = [];
        geodata2 = [];
    }
}

function getLenth(point, nextPoint) {
    var dx = nextPoint.x - point.x;
    var dy = nextPoint.y - point.y;
    return Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2)).toFixed(2);
}

function getDirectionalAngle(point, nextPoint) {
    var dx = nextPoint.x - point.x;
    var dy = nextPoint.y - point.y;
    if (dx === 0) {
        if (ddy < 0) {
            return '270° 0,0\'';
        }
        else {
            return '90° 0,0\'';
        }
    }
    else {
        var alfa = Math.abs(Math.atan(dy/dx) * (180/Math.PI));
        var angle;
        if (dx > 0 && dy > 0) {
            angle = alfa;
            return getDegreeAndMinit(angle);
        }
        else if (dx < 0 && dy > 0) {
            angle = 180 - alfa;
            return getDegreeAndMinit(angle);
        }
        else if (dx < 0 && dy < 0) {
            angle = 180 + alfa;
            return getDegreeAndMinit(angle);
        }
        else if (dx > 0 && dy < 0) {
            angle = 360 - alfa;
            return getDegreeAndMinit(angle);
        }
        else if (dx > 0 && dy === 0) {
            return '0° 0\'';
        }
        else if (dx < 0 && dy === 0) {
            return '180° 0\'';
        }
    }
}

function getDegreeAndMinit (angle) {
    var a = Math.floor(angle);
    var minit = (angle - a) * 60;
    return a + '° ' + minit.toFixed(1) + '\'';
}

function createTableHeader() {
    var header = $('
');
    header.addClass('coord-table-header');
    header.append($('').html('№'));
    var x = $('');
    x.addClass('coord-td');
    header.append(x.html('X, м'));
    var y = $('');
    y.addClass('coord-td');
    header.append(y.html('Y, м'));
    header.append($('').html('Дирекционный угол, ° \''));
    header.append($('').html('Расстояние, м'));
    table.append(header);
}

function createTableData(data1, data2) {
    var row = $('
');
    row.addClass('coord-table-row');
    row.append($('').html('' + data1[0] + ''));
    row.append($('').html('' + data1[1] + ''));
    row.append($('').html('' + data1[2] + '</spanp>'));
    row.append($('').html('' + data1[3] + ''));
    row.append($('').html('' + data1[4] + ''));
    table.append(row);
    if (data2 && data2.length > 0) {
        var row1 = $('
');
        row1.addClass('coord-table-row');
        row1.append($('').html('' + data2[0] + ''));
        row1.append($('').html('' + data2[1] + ''));
        row1.append($('').html('' + data2[2] + ''));
        row1.append($('').html('' + data2[3] + ''));
        row1.append($('').html('' + data2[4] + ''));
        table.append(row1);
    }
}

function createGeodataHeader() {
    var header = $('
');
    header.append($('').html('№'));
    header.append($('').html('Дир. угол'));
    header.append($('').html('Расст, м'));
    geodataTable.append(header);
}

function createGeodata(geodata1, geodata2) {
    var row = $('
');
    row.addClass('coord-table-row');
    row.append($('').html('' + geodata1[0] + ''));
    row.append($('').html('' + geodata1[1] + ''));
    row.append($('').html('' + geodata1[2] + '</spanp>'));
    geodataTable.append(row);
    if (geodata2 && geodata2.length > 0) {
        var row1 = $('
');
        row1.addClass('coord-table-row');
        row1.append($('').html('' + geodata2[0] + ''));
        row1.append($('').html('' + geodata2[1] + ''));
        row1.append($('').html('' + geodata2[2] + ''));
        geodataTable.append(row1);
    }
}<|endoftext|>


<commit_before>import { app, BrowserWindow, Menu, shell } from 'electron';

let menu;
let template;
let mainWindow = null;
const DEBUG_PROD=true;

if (process.env.NODE_ENV === 'production') {
  const sourceMapSupport = require('source-map-support'); // eslint-disable-line
  sourceMapSupport.install();
}

if (process.env.NODE_ENV === 'development' || DEBUG_PROD) {
  require('electron-debug')(); // eslint-disable-line global-require
  const path = require('path'); // eslint-disable-line
  const p = path.join(__dirname, '..', 'app', 'node_modules'); // eslint-disable-line
  require('module').globalPaths.push(p); // eslint-disable-line
}

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit();
});

const installExtensions = async () => {
  if (process.env.NODE_ENV === 'development' || DEBUG_PROD) {
    const installer = require('electron-devtools-installer'); // eslint-disable-line global-require

    const extensions = [
      'REACT_DEVELOPER_TOOLS',
      'REDUX_DEVTOOLS'
    ];

    const forceDownload = !!process.env.UPGRADE_EXTENSIONS;

    // TODO: Use async interation statement.
    //       Waiting on https://github.com/tc39/proposal-async-iteration
    //       Promises will fail silently, which isn't what we want in development
    return Promise
      .all(extensions.map(name => installer.default(installer[name], forceDownload)))
      .catch(console.log);
  }
};

app.on('ready', async () => {
  await installExtensions();

  mainWindow = new BrowserWindow({
    show: false,
    width: 1024,
    height: 728
  });

  mainWindow.loadURL(`file://${__dirname}/app.html`);

  mainWindow.webContents.on('did-finish-load', () => {
    mainWindow.show();
    mainWindow.focus();
  });

  mainWindow.on('closed', () => {
    mainWindow = null;
  });

  if (process.env.NODE_ENV === 'development' || DEBUG_PROD) {
    mainWindow.openDevTools();
    mainWindow.webContents.on('context-menu', (e, props) => {
      const { x, y } = props;

      Menu.buildFromTemplate([{
        label: 'Inspect element',
        click() {
          mainWindow.inspectElement(x, y);
        }
      }]).popup(mainWindow);
    });
  }

  if (process.platform === 'darwin') {
    template = [{
      label: 'Electron',
      submenu: [{
        label: 'About ElectronReact',
        selector: 'orderFrontStandardAboutPanel:'
      }, {
        type: 'separator'
      }, {
        label: 'Services',
        submenu: []
      }, {
        type: 'separator'
      }, {
        label: 'Hide ElectronReact',
        accelerator: 'Command+H',
        selector: 'hide:'
      }, {
        label: 'Hide Others',
        accelerator: 'Command+Shift+H',
        selector: 'hideOtherApplications:'
      }, {
        label: 'Show All',
        selector: 'unhideAllApplications:'
      }, {
        type: 'separator'
      }, {
        label: 'Quit',
        accelerator: 'Command+Q',
        click() {
          app.quit();
        }
      }]
    }, {
      label: 'Edit',
      submenu: [{
        label: 'Undo',
        accelerator: 'Command+Z',
        selector: 'undo:'
      }, {
        label: 'Redo',
        accelerator: 'Shift+Command+Z',
        selector: 'redo:'
      }, {
        type: 'separator'
      }, {
        label: 'Cut',
        accelerator: 'Command+X',
        selector: 'cut:'
      }, {
        label: 'Copy',
        accelerator: 'Command+C',
        selector: 'copy:'
      }, {
        label: 'Paste',
        accelerator: 'Command+V',
        selector: 'paste:'
      }, {
        label: 'Select All',
        accelerator: 'Command+A',
        selector: 'selectAll:'
      }]
    }, {
      label: 'View',
      submenu: (process.env.NODE_ENV === 'development' || DEBUG_PROD) ? [{
        label: 'Reload',
        accelerator: 'Command+R',
        click() {
          mainWindow.webContents.reload();
        }
      }, {
        label: 'Toggle Full Screen',
        accelerator: 'Ctrl+Command+F',
        click() {
          mainWindow.setFullScreen(!mainWindow.isFullScreen());
        }
      }, {
        label: 'Toggle Developer Tools',
        accelerator: 'Alt+Command+I',
        click() {
          mainWindow.toggleDevTools();
        }
      }] : [{
        label: 'Toggle Full Screen',
        accelerator: 'Ctrl+Command+F',
        click() {
          mainWindow.setFullScreen(!mainWindow.isFullScreen());
        }
      }]
    }, {
      label: 'Window',
      submenu: [{
        label: 'Minimize',
        accelerator: 'Command+M',
        selector: 'performMiniaturize:'
      }, {
        label: 'Close',
        accelerator: 'Command+W',
        selector: 'performClose:'
      }, {
        type: 'separator'
      }, {
        label: 'Bring All to Front',
        selector: 'arrangeInFront:'
      }]
    }, {
      label: 'Help',
      submenu: [{
        label: 'Learn More',
        click() {
          shell.openExternal('http://electron.atom.io');
        }
      }, {
        label: 'Documentation',
        click() {
          shell.openExternal('https://github.com/atom/electron/tree/master/docs#readme');
        }
      }, {
        label: 'Community Discussions',
        click() {
          shell.openExternal('https://discuss.atom.io/c/electron');
        }
      }, {
        label: 'Search Issues',
        click() {
          shell.openExternal('https://github.com/atom/electron/issues');
        }
      }]
    }];

    menu = Menu.buildFromTemplate(template);
    Menu.setApplicationMenu(menu);
  } else {
    template = [{
      label: '&File',
      submenu: [{
        label: '&Open',
        accelerator: 'Ctrl+O'
      }, {
        label: '&Close',
        accelerator: 'Ctrl+W',
        click() {
          mainWindow.close();
        }
      }]
    }, {
      label: '&View',
      submenu: (process.env.NODE_ENV === 'development' || DEBUG_PROD) ? [{
        label: '&Reload',
        accelerator: 'Ctrl+R',
        click() {
          mainWindow.webContents.reload();
        }
      }, {
        label: 'Toggle &Full Screen',
        accelerator: 'F11',
        click() {
          mainWindow.setFullScreen(!mainWindow.isFullScreen());
        }
      }, {
        label: 'Toggle &Developer Tools',
        accelerator: 'Alt+Ctrl+I',
        click() {
          mainWindow.toggleDevTools();
        }
      }] : [{
        label: 'Toggle &Full Screen',
        accelerator: 'F11',
        click() {
          mainWindow.setFullScreen(!mainWindow.isFullScreen());
        }
      }]
    }, {
      label: 'Help',
      submenu: [{
        label: 'Learn More',
        click() {
          shell.openExternal('http://electron.atom.io');
        }
      }, {
        label: 'Documentation',
        click() {
          shell.openExternal('https://github.com/atom/electron/tree/master/docs#readme');
        }
      }, {
        label: 'Community Discussions',
        click() {
          shell.openExternal('https://discuss.atom.io/c/electron');
        }
      }, {
        label: 'Search Issues',
        click() {
          shell.openExternal('https://github.com/atom/electron/issues');
        }
      }]
    }];
    menu = Menu.buildFromTemplate(template);
    mainWindow.setMenu(menu);
  }
});
<commit_msg>Mute prod logging<commit_after>import { app, BrowserWindow, Menu, shell } from 'electron';

let menu;
let template;
let mainWindow = null;
const DEBUG_PROD=false;

if (process.env.NODE_ENV === 'production') {
  const sourceMapSupport = require('source-map-support'); // eslint-disable-line
  sourceMapSupport.install();
}

if (process.env.NODE_ENV === 'development' || DEBUG_PROD) {
  require('electron-debug')(); // eslint-disable-line global-require
  const path = require('path'); // eslint-disable-line
  const p = path.join(__dirname, '..', 'app', 'node_modules'); // eslint-disable-line
  require('module').globalPaths.push(p); // eslint-disable-line
}

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit();
});

const installExtensions = async () => {
  if (process.env.NODE_ENV === 'development' || DEBUG_PROD) {
    const installer = require('electron-devtools-installer'); // eslint-disable-line global-require

    const extensions = [
      'REACT_DEVELOPER_TOOLS',
      'REDUX_DEVTOOLS'
    ];

    const forceDownload = !!process.env.UPGRADE_EXTENSIONS;

    // TODO: Use async interation statement.
    //       Waiting on https://github.com/tc39/proposal-async-iteration
    //       Promises will fail silently, which isn't what we want in development
    return Promise
      .all(extensions.map(name => installer.default(installer[name], forceDownload)))
      .catch(console.log);
  }
};

app.on('ready', async () => {
  await installExtensions();

  mainWindow = new BrowserWindow({
    show: false,
    width: 1024,
    height: 728
  });

  mainWindow.loadURL(`file://${__dirname}/app.html`);

  mainWindow.webContents.on('did-finish-load', () => {
    mainWindow.show();
    mainWindow.focus();
  });

  mainWindow.on('closed', () => {
    mainWindow = null;
  });

  if (process.env.NODE_ENV === 'development' || DEBUG_PROD) {
    mainWindow.openDevTools();
    mainWindow.webContents.on('context-menu', (e, props) => {
      const { x, y } = props;

      Menu.buildFromTemplate([{
        label: 'Inspect element',
        click() {
          mainWindow.inspectElement(x, y);
        }
      }]).popup(mainWindow);
    });
  }

  if (process.platform === 'darwin') {
    template = [{
      label: 'Electron',
      submenu: [{
        label: 'About ElectronReact',
        selector: 'orderFrontStandardAboutPanel:'
      }, {
        type: 'separator'
      }, {
        label: 'Services',
        submenu: []
      }, {
        type: 'separator'
      }, {
        label: 'Hide ElectronReact',
        accelerator: 'Command+H',
        selector: 'hide:'
      }, {
        label: 'Hide Others',
        accelerator: 'Command+Shift+H',
        selector: 'hideOtherApplications:'
      }, {
        label: 'Show All',
        selector: 'unhideAllApplications:'
      }, {
        type: 'separator'
      }, {
        label: 'Quit',
        accelerator: 'Command+Q',
        click() {
          app.quit();
        }
      }]
    }, {
      label: 'Edit',
      submenu: [{
        label: 'Undo',
        accelerator: 'Command+Z',
        selector: 'undo:'
      }, {
        label: 'Redo',
        accelerator: 'Shift+Command+Z',
        selector: 'redo:'
      }, {
        type: 'separator'
      }, {
        label: 'Cut',
        accelerator: 'Command+X',
        selector: 'cut:'
      }, {
        label: 'Copy',
        accelerator: 'Command+C',
        selector: 'copy:'
      }, {
        label: 'Paste',
        accelerator: 'Command+V',
        selector: 'paste:'
      }, {
        label: 'Select All',
        accelerator: 'Command+A',
        selector: 'selectAll:'
      }]
    }, {
      label: 'View',
      submenu: (process.env.NODE_ENV === 'development' || DEBUG_PROD) ? [{
        label: 'Reload',
        accelerator: 'Command+R',
        click() {
          mainWindow.webContents.reload();
        }
      }, {
        label: 'Toggle Full Screen',
        accelerator: 'Ctrl+Command+F',
        click() {
          mainWindow.setFullScreen(!mainWindow.isFullScreen());
        }
      }, {
        label: 'Toggle Developer Tools',
        accelerator: 'Alt+Command+I',
        click() {
          mainWindow.toggleDevTools();
        }
      }] : [{
        label: 'Toggle Full Screen',
        accelerator: 'Ctrl+Command+F',
        click() {
          mainWindow.setFullScreen(!mainWindow.isFullScreen());
        }
      }]
    }, {
      label: 'Window',
      submenu: [{
        label: 'Minimize',
        accelerator: 'Command+M',
        selector: 'performMiniaturize:'
      }, {
        label: 'Close',
        accelerator: 'Command+W',
        selector: 'performClose:'
      }, {
        type: 'separator'
      }, {
        label: 'Bring All to Front',
        selector: 'arrangeInFront:'
      }]
    }, {
      label: 'Help',
      submenu: [{
        label: 'Learn More',
        click() {
          shell.openExternal('http://electron.atom.io');
        }
      }, {
        label: 'Documentation',
        click() {
          shell.openExternal('https://github.com/atom/electron/tree/master/docs#readme');
        }
      }, {
        label: 'Community Discussions',
        click() {
          shell.openExternal('https://discuss.atom.io/c/electron');
        }
      }, {
        label: 'Search Issues',
        click() {
          shell.openExternal('https://github.com/atom/electron/issues');
        }
      }]
    }];

    menu = Menu.buildFromTemplate(template);
    Menu.setApplicationMenu(menu);
  } else {
    template = [{
      label: '&File',
      submenu: [{
        label: '&Open',
        accelerator: 'Ctrl+O'
      }, {
        label: '&Close',
        accelerator: 'Ctrl+W',
        click() {
          mainWindow.close();
        }
      }]
    }, {
      label: '&View',
      submenu: (process.env.NODE_ENV === 'development' || DEBUG_PROD) ? [{
        label: '&Reload',
        accelerator: 'Ctrl+R',
        click() {
          mainWindow.webContents.reload();
        }
      }, {
        label: 'Toggle &Full Screen',
        accelerator: 'F11',
        click() {
          mainWindow.setFullScreen(!mainWindow.isFullScreen());
        }
      }, {
        label: 'Toggle &Developer Tools',
        accelerator: 'Alt+Ctrl+I',
        click() {
          mainWindow.toggleDevTools();
        }
      }] : [{
        label: 'Toggle &Full Screen',
        accelerator: 'F11',
        click() {
          mainWindow.setFullScreen(!mainWindow.isFullScreen());
        }
      }]
    }, {
      label: 'Help',
      submenu: [{
        label: 'Learn More',
        click() {
          shell.openExternal('http://electron.atom.io');
        }
      }, {
        label: 'Documentation',
        click() {
          shell.openExternal('https://github.com/atom/electron/tree/master/docs#readme');
        }
      }, {
        label: 'Community Discussions',
        click() {
          shell.openExternal('https://discuss.atom.io/c/electron');
        }
      }, {
        label: 'Search Issues',
        click() {
          shell.openExternal('https://github.com/atom/electron/issues');
        }
      }]
    }];
    menu = Menu.buildFromTemplate(template);
    mainWindow.setMenu(menu);
  }
});
<|endoftext|>


<commit_before>import { app, BrowserWindow, Menu, shell } from 'electron';

let menu;
let template;
let mainWindow = null;

if (process.env.NODE_ENV === 'production') {
  const sourceMapSupport = require('source-map-support'); // eslint-disable-line
  sourceMapSupport.install();
}

if (process.env.NODE_ENV === 'development') {
  require('electron-debug')(); // eslint-disable-line global-require
  const path = require('path'); // eslint-disable-line
  const p = path.join(__dirname, '..', 'app', 'node_modules'); // eslint-disable-line
  require('module').globalPaths.push(p); // eslint-disable-line
}

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit();
});

const installExtensions = async () => {
  if (process.env.NODE_ENV === 'development') {
    const installer = require('electron-devtools-installer'); // eslint-disable-line global-require

    const extensions = [
      'REACT_DEVELOPER_TOOLS',
      'REDUX_DEVTOOLS'
    ];

    const forceDownload = !!process.env.UPGRADE_EXTENSIONS;

    // TODO: Use async interation statement.
    //       Waiting on https://github.com/tc39/proposal-async-iteration
    //       Promises will fail silently, which isn't what we want in development
    return Promise
      .all(extensions.map(name => installer.default(installer[name], forceDownload)))
      .catch(console.log);
  }
};

app.on('ready', async () => {
  await installExtensions();

  mainWindow = new BrowserWindow({
    show: false,
    width: 1024,
    height: 728
  });

  mainWindow.loadURL(`file://${__dirname}/app.html`);

  mainWindow.webContents.on('did-finish-load', () => {
    mainWindow.show();
    mainWindow.focus();
  });

  mainWindow.on('closed', () => {
    mainWindow = null;
  });

  if (process.env.NODE_ENV === 'development') {
    mainWindow.openDevTools();
    mainWindow.webContents.on('context-menu', (e, props) => {
      const { x, y } = props;

      Menu.buildFromTemplate([{
        label: 'Inspect element',
        click() {
          mainWindow.inspectElement(x, y);
        }
      }]).popup(mainWindow);
    });
  }

  if (process.platform === 'darwin') {
    template = [{
      label: 'Electron',
      submenu: [{
        label: 'About ElectronReact',
        selector: 'orderFrontStandardAboutPanel:'
      }, {
        type: 'separator'
      }, {
        label: 'Services',
        submenu: []
      }, {
        type: 'separator'
      }, {
        label: 'Hide ElectronReact',
        accelerator: 'Command+H',
        selector: 'hide:'
      }, {
        label: 'Hide Others',
        accelerator: 'Command+Shift+H',
        selector: 'hideOtherApplications:'
      }, {
        label: 'Show All',
        selector: 'unhideAllApplications:'
      }, {
        type: 'separator'
      }, {
        label: 'Quit',
        accelerator: 'Command+Q',
        click() {
          app.quit();
        }
      }]
    }, {
      label: 'Edit',
      submenu: [{
        label: 'Undo',
        accelerator: 'Command+Z',
        selector: 'undo:'
      }, {
        label: 'Redo',
        accelerator: 'Shift+Command+Z',
        selector: 'redo:'
      }, {
        type: 'separator'
      }, {
        label: 'Cut',
        accelerator: 'Command+X',
        selector: 'cut:'
      }, {
        label: 'Copy',
        accelerator: 'Command+C',
        selector: 'copy:'
      }, {
        label: 'Paste',
        accelerator: 'Command+V',
        selector: 'paste:'
      }, {
        label: 'Select All',
        accelerator: 'Command+A',
        selector: 'selectAll:'
      }]
    }, {
      label: 'View',
      submenu: (process.env.NODE_ENV === 'development') ? [{
        label: 'Reload',
        accelerator: 'Command+R',
        click() {
          mainWindow.webContents.reload();
        }
      }, {
        label: 'Toggle Full Screen',
        accelerator: 'Ctrl+Command+F',
        click() {
          mainWindow.setFullScreen(!mainWindow.isFullScreen());
        }
      }, {
        label: 'Toggle Developer Tools',
        accelerator: 'Alt+Command+I',
        click() {
          mainWindow.toggleDevTools();
        }
      }] : [{
        label: 'Toggle Full Screen',
        accelerator: 'Ctrl+Command+F',
        click() {
          mainWindow.setFullScreen(!mainWindow.isFullScreen());
        }
      }]
    }, {
      label: 'Window',
      submenu: [{
        label: 'Minimize',
        accelerator: 'Command+M',
        selector: 'performMiniaturize:'
      }, {
        label: 'Close',
        accelerator: 'Command+W',
        selector: 'performClose:'
      }, {
        type: 'separator'
      }, {
        label: 'Bring All to Front',
        selector: 'arrangeInFront:'
      }]
    }, {
      label: 'Help',
      submenu: [{
        label: 'Learn More',
        click() {
          shell.openExternal('http://electron.atom.io');
        }
      }, {
        label: 'Documentation',
        click() {
          shell.openExternal('https://github.com/atom/electron/tree/master/docs#readme');
        }
      }, {
        label: 'Community Discussions',
        click() {
          shell.openExternal('https://discuss.atom.io/c/electron');
        }
      }, {
        label: 'Search Issues',
        click() {
          shell.openExternal('https://github.com/atom/electron/issues');
        }
      }]
    }];

    menu = Menu.buildFromTemplate(template);
    Menu.setApplicationMenu(menu);
  } else {
    template = [{
      label: '&File',
      submenu: [{
        label: '&Open',
        accelerator: 'Ctrl+O'
      }, {
        label: '&Close',
        accelerator: 'Ctrl+W',
        click() {
          mainWindow.close();
        }
      }]
    }, {
      label: '&View',
      submenu: (process.env.NODE_ENV === 'development') ? [{
        label: '&Reload',
        accelerator: 'Ctrl+R',
        click() {
          mainWindow.webContents.reload();
        }
      }, {
        label: 'Toggle &Full Screen',
        accelerator: 'F11',
        click() {
          mainWindow.setFullScreen(!mainWindow.isFullScreen());
        }
      }, {
        label: 'Toggle &Developer Tools',
        accelerator: 'Alt+Ctrl+I',
        click() {
          mainWindow.toggleDevTools();
        }
      }] : [{
        label: 'Toggle &Full Screen',
        accelerator: 'F11',
        click() {
          mainWindow.setFullScreen(!mainWindow.isFullScreen());
        }
      }]
    }, {
      label: 'Help',
      submenu: [{
        label: 'Learn More',
        click() {
          shell.openExternal('http://electron.atom.io');
        }
      }, {
        label: 'Documentation',
        click() {
          shell.openExternal('https://github.com/atom/electron/tree/master/docs#readme');
        }
      }, {
        label: 'Community Discussions',
        click() {
          shell.openExternal('https://discuss.atom.io/c/electron');
        }
      }, {
        label: 'Search Issues',
        click() {
          shell.openExternal('https://github.com/atom/electron/issues');
        }
      }]
    }];
    menu = Menu.buildFromTemplate(template);
    mainWindow.setMenu(menu);
  }
});
<commit_msg>Add debug flag to main.development.js [TODO] remove<commit_after>import { app, BrowserWindow, Menu, shell } from 'electron';

let menu;
let template;
let mainWindow = null;
const DEBUG_PROD=true;

if (process.env.NODE_ENV === 'production') {
  const sourceMapSupport = require('source-map-support'); // eslint-disable-line
  sourceMapSupport.install();
}

if (process.env.NODE_ENV === 'development' || DEBUG_PROD) {
  require('electron-debug')(); // eslint-disable-line global-require
  const path = require('path'); // eslint-disable-line
  const p = path.join(__dirname, '..', 'app', 'node_modules'); // eslint-disable-line
  require('module').globalPaths.push(p); // eslint-disable-line
}

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit();
});

const installExtensions = async () => {
  if (process.env.NODE_ENV === 'development' || DEBUG_PROD) {
    const installer = require('electron-devtools-installer'); // eslint-disable-line global-require

    const extensions = [
      'REACT_DEVELOPER_TOOLS',
      'REDUX_DEVTOOLS'
    ];

    const forceDownload = !!process.env.UPGRADE_EXTENSIONS;

    // TODO: Use async interation statement.
    //       Waiting on https://github.com/tc39/proposal-async-iteration
    //       Promises will fail silently, which isn't what we want in development
    return Promise
      .all(extensions.map(name => installer.default(installer[name], forceDownload)))
      .catch(console.log);
  }
};

app.on('ready', async () => {
  await installExtensions();

  mainWindow = new BrowserWindow({
    show: false,
    width: 1024,
    height: 728
  });

  mainWindow.loadURL(`file://${__dirname}/app.html`);

  mainWindow.webContents.on('did-finish-load', () => {
    mainWindow.show();
    mainWindow.focus();
  });

  mainWindow.on('closed', () => {
    mainWindow = null;
  });

  if (process.env.NODE_ENV === 'development' || DEBUG_PROD) {
    mainWindow.openDevTools();
    mainWindow.webContents.on('context-menu', (e, props) => {
      const { x, y } = props;

      Menu.buildFromTemplate([{
        label: 'Inspect element',
        click() {
          mainWindow.inspectElement(x, y);
        }
      }]).popup(mainWindow);
    });
  }

  if (process.platform === 'darwin') {
    template = [{
      label: 'Electron',
      submenu: [{
        label: 'About ElectronReact',
        selector: 'orderFrontStandardAboutPanel:'
      }, {
        type: 'separator'
      }, {
        label: 'Services',
        submenu: []
      }, {
        type: 'separator'
      }, {
        label: 'Hide ElectronReact',
        accelerator: 'Command+H',
        selector: 'hide:'
      }, {
        label: 'Hide Others',
        accelerator: 'Command+Shift+H',
        selector: 'hideOtherApplications:'
      }, {
        label: 'Show All',
        selector: 'unhideAllApplications:'
      }, {
        type: 'separator'
      }, {
        label: 'Quit',
        accelerator: 'Command+Q',
        click() {
          app.quit();
        }
      }]
    }, {
      label: 'Edit',
      submenu: [{
        label: 'Undo',
        accelerator: 'Command+Z',
        selector: 'undo:'
      }, {
        label: 'Redo',
        accelerator: 'Shift+Command+Z',
        selector: 'redo:'
      }, {
        type: 'separator'
      }, {
        label: 'Cut',
        accelerator: 'Command+X',
        selector: 'cut:'
      }, {
        label: 'Copy',
        accelerator: 'Command+C',
        selector: 'copy:'
      }, {
        label: 'Paste',
        accelerator: 'Command+V',
        selector: 'paste:'
      }, {
        label: 'Select All',
        accelerator: 'Command+A',
        selector: 'selectAll:'
      }]
    }, {
      label: 'View',
      submenu: (process.env.NODE_ENV === 'development' || DEBUG_PROD) ? [{
        label: 'Reload',
        accelerator: 'Command+R',
        click() {
          mainWindow.webContents.reload();
        }
      }, {
        label: 'Toggle Full Screen',
        accelerator: 'Ctrl+Command+F',
        click() {
          mainWindow.setFullScreen(!mainWindow.isFullScreen());
        }
      }, {
        label: 'Toggle Developer Tools',
        accelerator: 'Alt+Command+I',
        click() {
          mainWindow.toggleDevTools();
        }
      }] : [{
        label: 'Toggle Full Screen',
        accelerator: 'Ctrl+Command+F',
        click() {
          mainWindow.setFullScreen(!mainWindow.isFullScreen());
        }
      }]
    }, {
      label: 'Window',
      submenu: [{
        label: 'Minimize',
        accelerator: 'Command+M',
        selector: 'performMiniaturize:'
      }, {
        label: 'Close',
        accelerator: 'Command+W',
        selector: 'performClose:'
      }, {
        type: 'separator'
      }, {
        label: 'Bring All to Front',
        selector: 'arrangeInFront:'
      }]
    }, {
      label: 'Help',
      submenu: [{
        label: 'Learn More',
        click() {
          shell.openExternal('http://electron.atom.io');
        }
      }, {
        label: 'Documentation',
        click() {
          shell.openExternal('https://github.com/atom/electron/tree/master/docs#readme');
        }
      }, {
        label: 'Community Discussions',
        click() {
          shell.openExternal('https://discuss.atom.io/c/electron');
        }
      }, {
        label: 'Search Issues',
        click() {
          shell.openExternal('https://github.com/atom/electron/issues');
        }
      }]
    }];

    menu = Menu.buildFromTemplate(template);
    Menu.setApplicationMenu(menu);
  } else {
    template = [{
      label: '&File',
      submenu: [{
        label: '&Open',
        accelerator: 'Ctrl+O'
      }, {
        label: '&Close',
        accelerator: 'Ctrl+W',
        click() {
          mainWindow.close();
        }
      }]
    }, {
      label: '&View',
      submenu: (process.env.NODE_ENV === 'development' || DEBUG_PROD) ? [{
        label: '&Reload',
        accelerator: 'Ctrl+R',
        click() {
          mainWindow.webContents.reload();
        }
      }, {
        label: 'Toggle &Full Screen',
        accelerator: 'F11',
        click() {
          mainWindow.setFullScreen(!mainWindow.isFullScreen());
        }
      }, {
        label: 'Toggle &Developer Tools',
        accelerator: 'Alt+Ctrl+I',
        click() {
          mainWindow.toggleDevTools();
        }
      }] : [{
        label: 'Toggle &Full Screen',
        accelerator: 'F11',
        click() {
          mainWindow.setFullScreen(!mainWindow.isFullScreen());
        }
      }]
    }, {
      label: 'Help',
      submenu: [{
        label: 'Learn More',
        click() {
          shell.openExternal('http://electron.atom.io');
        }
      }, {
        label: 'Documentation',
        click() {
          shell.openExternal('https://github.com/atom/electron/tree/master/docs#readme');
        }
      }, {
        label: 'Community Discussions',
        click() {
          shell.openExternal('https://discuss.atom.io/c/electron');
        }
      }, {
        label: 'Search Issues',
        click() {
          shell.openExternal('https://github.com/atom/electron/issues');
        }
      }]
    }];
    menu = Menu.buildFromTemplate(template);
    mainWindow.setMenu(menu);
  }
});
<|endoftext|>


<commit_before>ig.module('game.entities.playerL2').requires('ig.entities.player').defines(function() {
	EntityPlayerL2 = EntityPlayer.extend({
		type: ig.Entity.TYPE.A,
		collides: ig.Entity.COLLIDES.ACTIVE,
		checkAgainst: ig.Entity.TYPE.B
	});
});<commit_msg>Added animSheet for car<commit_after>ig.module('game.entities.playerL2').requires('ig.entities.player').defines(function() {
	EntityPlayerL2 = EntityPlayer.extend({
		type: ig.Entity.TYPE.A,
		collides: ig.Entity.COLLIDES.ACTIVE,
		checkAgainst: ig.Entity.TYPE.B,

		animSheet: new ig.AnimationSheet( 'media/car.png', 294, 600 )
	});
});<|endoftext|>


<commit_before>'use strict'
const client = require('./redis.js');
const logger = require('./logger.js');

module.exports = {
  /**
   *
   *
   * @param {any} key
   * @param {Function} getData
   * @param {Integer} time
   * @returns
   */
  async get(key, getData, time) {
    let t = Date.now();
    let data = JSON.parse(await client.getAsync(key));
    logger.debug('Cache', 'get', key, ((Date.now() - t) + 'ms').green);
    if (!data && typeof getData === 'function') {
      await this.set(key, await getData(), time);
    }

    return data;
  },
  /**
   *
   *
   * @param {any} key
   * @param {any} value
   * @param {Integer} time
   */
  async set(key, value, time) {
    let t = Date.now();
    value = JSON.stringify(value);

    if (time) await client.setAsync(key, value, 'EX', time);
    await client.setAsync(key, value);

    logger.debug("Cache", "set", key, ((Date.now() - t) + 'ms').green);
  },

  /**
   *
   *
   * @param {any} key
   * @returns
   */
  del(key) {
    return client.destroyAsync(key);
  }
}
<commit_msg>update cache.js<commit_after>'use strict'
const client = require('./redis.js');
const logger = require('./logger.js');

module.exports = {
  /**
   *
   *
   * @param {any} key
   * @param {Function} getData
   * @param {Integer} time
   * @returns
   */
  async get(key, getData, time) {
    let t = Date.now();
    let data = JSON.parse(await client.getAsync(key));
    logger.debug('Cache', 'get', key, ((Date.now() - t) + 'ms').green);
    if (!data && typeof getData === 'function') {
      await this.set(key, await getData(), time);
    }

    return data;
  },
  /**
   *
   *
   * @param {any} key
   * @param {any} value
   * @param {Integer} time
   */
  async set(key, value, time) {
    let t = Date.now();
    value = JSON.stringify(value);

    if (time) await client.setAsync(key, value, 'EX', time);
    await client.setAsync(key, value);

    logger.debug("Cache", "set", key, ((Date.now() - t) + 'ms').green);
  },

  /**
   *
   *
   * @param {any} key
   * @returns
   */
  del(key) {
    return client.delAsync(key);
  }
}
<|endoftext|>


<commit_before>var fun_p64 = 0;
var zen     = 0;
var store   = 0;
var eth     = 0;
var api_key = "";
var ip      = "";
var url0    = "";
function post_opts () {
    // Default options are marked with *
    return {
        method: "POST", // *GET, POST, PUT, DELETE, etc.
        mode: "no-cors", // no-cors, cors, *same-origin
        cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
        headers: {
            "Content-Type": "text/plain"  // avoid preflight request
            //"Content-Type": "application/json",
            //"Content-Type": "application/x-www-form-urlencoded",
        },
        credentials : "omit",
        //redirect: "follow", // manual, *follow, error
        //referrer: "no-referrer", // no-referrer, *client
        body: JSON.stringify({ "api_key": api_key }) // body data type must match "Content-Type" header
    }
};

function status () {
    fetch(url0 + "/status", post_opts()).then(function (response) {
        return response.json();
    }).then(function (json) {
        console.log(json);
        fun_p64 = json.fun_p64;
        zen = json.zen;
        store = json.store;
        eth = json.eth;
        //swx_visibility("get-status");
        //swx_visibility("controls");
        swx_ctl_state();
    });
};
function swx_ctl_state () {
    fun_p64 ? document.getElementById('fun-p64').checked = true : document.getElementById('fun-p64').checked = false;
    zen     ? document.getElementById('zen').checked     = true : document.getElementById('zen').checked     = false;
    store   ? document.getElementById('store').checked   = true : document.getElementById('store').checked   = false;
    eth     ? document.getElementById('eth').checked     = true : document.getElementById('eth').checked     = false;
};
function swx_visibility (id = 'undefined') {
    var e = document.getElementById(id);
    if (e.style.display == 'block')
        e.style.display = 'none';
    else
        e.style.display = 'block';
};
function swx (x = 'undefined') {
    var url = url0;
    function swx_ctl (c = -1) {
        if (c == 0) { c = 1; url += "/on"; }
        else        { c = 0; url += "/off"; }
    };
    if (x == 'fun-p64')    { url += "/1"; swx_ctl(fun_p64); }
    else if (x == 'zen')   { url += "/3"; swx_ctl(zen); }
    else if (x == 'store') { url += "/2"; swx_ctl(store); }
    else if (x == 'eth')   { url += "/4"; swx_ctl(eth); }
    else { return -1; }

    fetch(url, post_opts()).then(function (response) {
        return {};
    }).then(function (_) {
        fetch(url0 + "/status", post_opts()).then(function (response) {
            return response.json();
        }).then(function (json) {
            console.log(json);
            fun_p64 = json.fun_p64;
            zen = json.zen;
            store = json.store;
            eth = json.eth;
            swx_ctl_state();
        });
    });
};
function swx1 () { swx('fun-p64'); };
function swx2 () { swx('zen'); };
function swx3 () { swx('store'); };
function swx4 () { swx('eth'); };

function refresh () {
    ip = document.getElementById("ip").value;
    api_key = document.getElementById("api_key").value;
    url0    = "https://" + ip;
    status ();
};
<commit_msg>Revet to 'cors'<commit_after>var fun_p64 = 0;
var zen     = 0;
var store   = 0;
var eth     = 0;
var api_key = "";
var ip      = "";
var url0    = "";
function post_opts () {
    // Default options are marked with *
    return {
        method: "POST", // *GET, POST, PUT, DELETE, etc.
        mode: "cors", // no-cors, cors, *same-origin
        cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
        headers: {
            "Content-Type": "text/plain"  // avoid preflight request
            //"Content-Type": "application/json",
            //"Content-Type": "application/x-www-form-urlencoded",
        },
        credentials : "omit",
        //redirect: "follow", // manual, *follow, error
        //referrer: "no-referrer", // no-referrer, *client
        body: JSON.stringify({ "api_key": api_key }) // body data type must match "Content-Type" header
    }
};

function status () {
    fetch(url0 + "/status", post_opts()).then(function (response) {
        return response.json();
    }).then(function (json) {
        console.log(json);
        fun_p64 = json.fun_p64;
        zen = json.zen;
        store = json.store;
        eth = json.eth;
        //swx_visibility("get-status");
        //swx_visibility("controls");
        swx_ctl_state();
    });
};
function swx_ctl_state () {
    fun_p64 ? document.getElementById('fun-p64').checked = true : document.getElementById('fun-p64').checked = false;
    zen     ? document.getElementById('zen').checked     = true : document.getElementById('zen').checked     = false;
    store   ? document.getElementById('store').checked   = true : document.getElementById('store').checked   = false;
    eth     ? document.getElementById('eth').checked     = true : document.getElementById('eth').checked     = false;
};
function swx_visibility (id = 'undefined') {
    var e = document.getElementById(id);
    if (e.style.display == 'block')
        e.style.display = 'none';
    else
        e.style.display = 'block';
};
function swx (x = 'undefined') {
    var url = url0;
    function swx_ctl (c = -1) {
        if (c == 0) { c = 1; url += "/on"; }
        else        { c = 0; url += "/off"; }
    };
    if (x == 'fun-p64')    { url += "/1"; swx_ctl(fun_p64); }
    else if (x == 'zen')   { url += "/3"; swx_ctl(zen); }
    else if (x == 'store') { url += "/2"; swx_ctl(store); }
    else if (x == 'eth')   { url += "/4"; swx_ctl(eth); }
    else { return -1; }

    fetch(url, post_opts()).then(function (response) {
        return {};
    }).then(function (_) {
        fetch(url0 + "/status", post_opts()).then(function (response) {
            return response.json();
        }).then(function (json) {
            console.log(json);
            fun_p64 = json.fun_p64;
            zen = json.zen;
            store = json.store;
            eth = json.eth;
            swx_ctl_state();
        });
    });
};
function swx1 () { swx('fun-p64'); };
function swx2 () { swx('zen'); };
function swx3 () { swx('store'); };
function swx4 () { swx('eth'); };

function refresh () {
    ip = document.getElementById("ip").value;
    api_key = document.getElementById("api_key").value;
    url0    = "https://" + ip;
    status ();
};
<|endoftext|>


<commit_before>"use strict"
var HOST = process.env.HOST || process.argv[2] || '127.0.0.1'
var BASES = (process.env.BASES || process.argv[3] || '').split(',')
var SILENT = process.env.SILENT || process.argv[4] || 'true'

var Hapi = require('hapi')
var Rif = require('rif')

var server = new Hapi.Server()
var rif = Rif()

var host = rif(HOST) || HOST

server.connection({
  port: 8000 // test with http://localhost:8000/api/ping
})

server.register(require('inert'))

server.register({
  register: require('wo'),
  options: {
    bases: BASES,
      sneeze: {
	host: host,
	silent: JSON.parse(SILENT),
        swim: {interval: 1111}
      }
  }
})

server.route({
  method: 'GET', path: '/api/ping',
  handler: {
    wo: {}
  }
})

server.route({
  method: 'POST', path: '/api/post/{user}',
  handler: {
    wo: {
      passThrough: true
    }
  }
})

server.route({
  method: 'POST', path: '/api/follow/{user}',
  handler: {
    wo: {
      passThrough: true
    }
  }
})

server.route({
  method: 'GET', path: '/mine/{user}',
  handler: {
    wo: {}
  }
})

server.route({
  method: ['GET','POST'], path: '/search/{user}',
  handler: {
    wo: {}
  }
})

server.route({
  method: 'GET', path: '/{user}',
  handler: {
    wo: {}
  }
})

server.route({
  path: '/favicon.ico',
  method: 'get',
  config: {
    cache: {
      expiresIn: 1000*60*60*24*21
    }
  },
  handler: function(request, reply) {
    reply().code(200).type('image/x-icon')
  }
})

server.route({
  method: 'GET',
  path: '/res/{path*}',
  handler: {
    directory: {
      path: __dirname + '/www/res',
    }
  }
})

server.start(function(){
  console.log('front',server.info.uri)
})
<commit_msg>add student post method to front<commit_after>"use strict"
var HOST = process.env.HOST || process.argv[2] || '127.0.0.1'
var BASES = (process.env.BASES || process.argv[3] || '').split(',')
var SILENT = process.env.SILENT || process.argv[4] || 'true'

var Hapi = require('hapi')
var Rif = require('rif')

var server = new Hapi.Server()
var rif = Rif()

var host = rif(HOST) || HOST

server.connection({
  port: 8000 // test with http://localhost:8000/api/ping
})

server.register(require('inert'))

server.register({
  register: require('wo'),
  options: {
    bases: BASES,
      sneeze: {
	host: host,
	silent: JSON.parse(SILENT),
        swim: {interval: 1111}
      }
  }
})

server.route({
  method: 'GET', path: '/api/ping',
  handler: {
    wo: {}
  }
})

server.route({
    method: 'POST', path: '/api/student',
    handler: {
        wo: {
            passThrough: true
        }
    }
})

server.route({
  method: 'POST', path: '/api/post/{user}',
  handler: {
    wo: {
      passThrough: true
    }
  }
})

server.route({
  method: 'POST', path: '/api/follow/{user}',
  handler: {
    wo: {
      passThrough: true
    }
  }
})

server.route({
  method: 'GET', path: '/mine/{user}',
  handler: {
    wo: {}
  }
})

server.route({
  method: ['GET','POST'], path: '/search/{user}',
  handler: {
    wo: {}
  }
})

server.route({
  method: 'GET', path: '/{user}',
  handler: {
    wo: {}
  }
})

server.route({
  path: '/favicon.ico',
  method: 'get',
  config: {
    cache: {
      expiresIn: 1000*60*60*24*21
    }
  },
  handler: function(request, reply) {
    reply().code(200).type('image/x-icon')
  }
})

server.route({
  method: 'GET',
  path: '/res/{path*}',
  handler: {
    directory: {
      path: __dirname + '/www/res',
    }
  }
})

server.start(function(){
  console.log('front',server.info.uri)
})
<|endoftext|>


<commit_before>var scope = angular.element('body').scope();
var game = scope.game;
var units = game.units();
var buyMeat = true;
var buyTerr = true;
var autobuy = 0;
var fasterUpgrades = [];

var autoSpeed = 10000;
var mothN4 = 2013;
var mothEnd = 5546;
var batCount = 393;

game.unitlist().forEach(function(u) {
  var upgrade = u.upgrades.byName[u.name + 'prod'];
  if (upgrade != null) {
    fasterUpgrades.push(upgrade);
  }
});

var empowerList = units.territory._parents().map(function(u) {return game.upgrade(u.name + 'empower')});

function unitRatio(u) {
  if (u._producerPath.getCoefficients().length > 1) {
    return u._producerPath.getCoefficientsNow()[1].dividedBy(u.maxCostMetOfVelocity().times(u.twinMult())).toNumber();
  } else {
    return 0;
  }
}

function currentMeat(unit) {
  if (unitRatio(unit) > 2) {
    return currentMeat(unit.next);
  } else {
    return unit;
  }
}

function buyMeatTwin(unit) {
  var twin = game.upgrade(unit.name + 'twin');
  if (twin) {
    var parentCost = twin.totalCost()[0].val;
    var parent = twin.totalCost()[0].unit;
    var unitCost = parent.costByName[unit.name].val.dividedBy(parent.twinMult());
    var totalUnitCost = unitCost.times(parentCost);

    if (unit.maxCostMet(1).times(unit.twinMult()).greaterThan(totalUnitCost.times(1.5))) {
      if (!twin.isBuyable()) {
        if (unit.count().lessThan(totalUnitCost)) {
          console.log('Twinning-Bought', totalUnitCost.minus(unit.count()).toExponential(2), unit.unittype.slug);
          unit.buy(unitCost.times(parentCost).minus(unit.count()));
        }
        console.log('Twinning-Bought', parentCost.toExponential(2), parent.unittype.slug);
        parent.buy(parentCost);
      }
      if (twin.isBuyable()) {
        twin.buy(1);
        console.log('Bought Twin', unit.unittype.slug);
        buyMeatTwin(unit);
      }
    } else {
      console.log('Bought', unit.maxCostMet(1).times(unit.twinMult()).toExponential(2), unit.unittype.slug);
      unit.buyMax(1);
    }
  }
}

function currentTerritory() {
  return _.max(units.territory._parents(), function(u) {return u.maxCostMet(1).times(u.twinMult()).times(u.eachProduction().territory).toNumber()});
}

function unitCostAsPercentOfVelocity (unit, cost) {
  var MAX = new Decimal(9999.99);
  var count = cost.unit.velocity();
  if (count.lessThanOrEqualTo(0)) {
    return MAX;
  }
  return Decimal.min(MAX, cost.val.times(unit.maxCostMetOfVelocity()).dividedBy(count));
}

// var buyList = [game.upgrade('expansion')].concat(units.nexus.upgrades.list);
var buyListProto = _.flatten([units.larva.upgrades.list, units.nexus.upgrades.list, units.meat.upgrades.list, units.territory._parents().map(function(p){return game.upgrade(p.name + 'twin')})]);
var buyList = buyListProto.slice(0);

var buyFunc = function() {
  buyList.forEach(function(u) {
    if (u.isBuyable()) {
      console.log('Bought', u.maxCostMet(1).toNumber(), u.name);
      u.buyMax(1);
    }
  });
  fasterUpgrades.forEach(function(u) {
    if (u.isBuyable() && u.totalCost()[0].val.times(2).lessThan(u.totalCost()[0].unit.count())) {
      console.log('Bought Faster', u.unit.unittype.slug, u.maxCostMet(1).toNumber(), 'times');
      u.buyMax(1);
    }
  });

  var currTerr = currentTerritory();

  empowerList.forEach(function(u) {
    if (u.isBuyable() && currTerr.costByName.meat.lessThan(u.unit.costByName.meat) && u.unit.totalProduction().territory.times(1000).lessThan(units.territory.velocity())) {
      console.log('Bought Empower', u.unit.unittype.slug);
      u.buy(1);
    }
  });

  currTerr = currentTerritory();

  if (buyTerr && currTerr.isBuyable()) {
    setTimeout(function() {
	  console.log('Bought', currTerr.maxCostMet(1).times(currTerr.twinMult()).toExponential(2), currTerr.unittype.slug);
	  currTerr.buyMax(1);
	}, 1000);
  }

  var currMeat = currentMeat(units.drone);
  var meatList = unitRatio(currMeat) > 0.01 ? [currMeat.next, currMeat] : [currMeat];

  meatList.forEach(function(m) {
    if (buyMeat && m.isBuyable()) {
      setTimeout(function() {
        buyMeatTwin(m);
      }, 2000)
    }
  });
  autobuy = setTimeout(buyFunc, autoSpeed);
};

var autoEnergy = 0;
var autoEnergyF = function() {
  buyList = buyListProto.slice(0);
  if (units.moth.count().toNumber() >= mothN4) {
    if (game.upgrade('nexus5').count().toNumber() == 0) {
      buyList = buyList.concat(game.upgrade('nexus5'));
    } else if (units.moth.count().toNumber() < mothEnd) {
      buyList = buyList.concat(units.moth);
    } else if (units.bat.count().toNumber() < batCount) {
      buyList = buyList.concat(units.bat);
    } else {
      return 0;
    }
  } else {
    buyList = buyList.concat(units.moth);
  }

  autoEnergy = setTimeout(autoEnergyF, autoSpeed);
};
<commit_msg>Update to make current territory work for big numbers<commit_after>var scope = angular.element('body').scope();
var game = scope.game;
var units = game.units();
var buyMeat = true;
var buyTerr = true;
var autobuy = 0;
var fasterUpgrades = [];

var autoSpeed = 10000;
var mothN4 = 2013;
var mothEnd = 5546;
var batCount = 393;

game.unitlist().forEach(function(u) {
  var upgrade = u.upgrades.byName[u.name + 'prod'];
  if (upgrade != null) {
    fasterUpgrades.push(upgrade);
  }
});

var empowerList = units.territory._parents().map(function(u) {return game.upgrade(u.name + 'empower')});

function unitRatio(u) {
  if (u._producerPath.getCoefficients().length > 1) {
    return u._producerPath.getCoefficientsNow()[1].dividedBy(u.maxCostMetOfVelocity().times(u.twinMult())).toNumber();
  } else {
    return 0;
  }
}

function currentMeat(unit) {
  if (unitRatio(unit) > 2) {
    return currentMeat(unit.next);
  } else {
    return unit;
  }
}

function buyMeatTwin(unit) {
  var twin = game.upgrade(unit.name + 'twin');
  if (twin) {
    var parentCost = twin.totalCost()[0].val;
    var parent = twin.totalCost()[0].unit;
    var unitCost = parent.costByName[unit.name].val.dividedBy(parent.twinMult());
    var totalUnitCost = unitCost.times(parentCost);

    if (unit.maxCostMet(1).times(unit.twinMult()).greaterThan(totalUnitCost.times(1.5))) {
      if (!twin.isBuyable()) {
        if (unit.count().lessThan(totalUnitCost)) {
          console.log('Twinning-Bought', totalUnitCost.minus(unit.count()).toExponential(2), unit.unittype.slug);
          unit.buy(unitCost.times(parentCost).minus(unit.count()));
        }
        console.log('Twinning-Bought', parentCost.toExponential(2), parent.unittype.slug);
        parent.buy(parentCost);
      }
      if (twin.isBuyable()) {
        twin.buy(1);
        console.log('Bought Twin', unit.unittype.slug);
        buyMeatTwin(unit);
      }
    } else {
      console.log('Bought', unit.maxCostMet(1).times(unit.twinMult()).toExponential(2), unit.unittype.slug);
      unit.buyMax(1);
    }
  }
}

function currentTerritory() {
  current = null;
  currentProd = 0;
  units.territory._parents().forEach(function(u) {
    uProd = u.maxCostMet(1).times(u.twinMult()).times(u.eachProduction().territory);
    if (uProd.greaterThan(currentProd)) {
      currentProd = uProd;
      current = u;
    }
  });
  return current;
}

function unitCostAsPercentOfVelocity (unit, cost) {
  var MAX = new Decimal(9999.99);
  var count = cost.unit.velocity();
  if (count.lessThanOrEqualTo(0)) {
    return MAX;
  }
  return Decimal.min(MAX, cost.val.times(unit.maxCostMetOfVelocity()).dividedBy(count));
}

// var buyList = [game.upgrade('expansion')].concat(units.nexus.upgrades.list);
var buyListProto = _.flatten([units.larva.upgrades.list, units.nexus.upgrades.list, units.meat.upgrades.list, units.territory._parents().map(function(p){return game.upgrade(p.name + 'twin')})]);
var buyList = buyListProto.slice(0);

var buyFunc = function() {
  buyList.forEach(function(u) {
    if (u.isBuyable()) {
      console.log('Bought', u.maxCostMet(1).toNumber(), u.name);
      u.buyMax(1);
    }
  });
  fasterUpgrades.forEach(function(u) {
    if (u.isBuyable() && u.totalCost()[0].val.times(2).lessThan(u.totalCost()[0].unit.count())) {
      console.log('Bought Faster', u.unit.unittype.slug, u.maxCostMet(1).toNumber(), 'times');
      u.buyMax(1);
    }
  });

  var currTerr = currentTerritory();

  empowerList.forEach(function(u) {
    if (u.isBuyable() && currTerr.costByName.meat.val.greaterThan(u.unit.costByName.meat.val) && u.unit.totalProduction().territory.times(1000).lessThan(units.territory.velocity())) {
      console.log('Bought Empower', u.unit.unittype.slug);
      u.buy(1);
    }
  });

  currTerr = currentTerritory();

  if (buyTerr && currTerr.isBuyable()) {
    setTimeout(function() {
	  console.log('Bought', currTerr.maxCostMet(1).times(currTerr.twinMult()).toExponential(2), currTerr.unittype.slug);
	  currTerr.buyMax(1);
	}, 1000);
  }

  var currMeat = currentMeat(units.drone);
  var meatList = unitRatio(currMeat) > 0.01 ? [currMeat.next, currMeat] : [currMeat];

  meatList.forEach(function(m) {
    if (buyMeat && m.isBuyable()) {
      setTimeout(function() {
        buyMeatTwin(m);
      }, 2000)
    }
  });
  autobuy = setTimeout(buyFunc, autoSpeed);
};

var autoEnergy = 0;
var autoEnergyF = function() {
  buyList = buyListProto.slice(0);
  if (units.moth.count().toNumber() >= mothN4) {
    if (game.upgrade('nexus5').count().toNumber() == 0) {
      buyList = buyList.concat(game.upgrade('nexus5'));
    } else if (units.moth.count().toNumber() < mothEnd) {
      buyList = buyList.concat(units.moth);
    } else if (units.bat.count().toNumber() < batCount) {
      buyList = buyList.concat(units.bat);
    } else {
      return 0;
    }
  } else {
    buyList = buyList.concat(units.moth);
  }

  autoEnergy = setTimeout(autoEnergyF, autoSpeed);
};
<|endoftext|>


<commit_before>// We can't use goog.color or goog.color.alpha because they interally use a hex
// string representation that encodes each channel in a single byte.  This
// causes occasional loss of precision and rounding errors, especially in the
// alpha channel.

goog.provide('ol.color');

goog.require('goog.array');
goog.require('goog.asserts');
goog.require('goog.color');
goog.require('goog.color.names');
goog.require('goog.math');
goog.require('goog.vec.Mat4');

/**
 * @define {boolean} Enable named colors.
 * Enabling named colors adds about 3KB uncompressed / 1.5KB compressed to the
 * final build size.
 */
ol.color.ENABLE_NAMED_COLORS = true;

/**
 * A color represented as a short array [red, green, blue, alpha].
 * red, green, and blue should be integers in the range 0..255 inclusive.
 * alpha should be a float in the range 0..1 inclusive.
 * @typedef {Array.<number>}
 */
ol.Color;

/**
 * This RegExp matches # followed by 3 or 6 hex digits.
 * @const
 * @type {RegExp}
 * @private
 */
ol.color.hexColorRe_ = /^#(?:[0-9a-f]{3}){1,2}$/i;

/**
 * @see goog.color.rgbColorRe_
 * @const
 * @type {RegExp}
 * @private
 */
ol.color.rgbColorRe_ =
    /^(?:rgb)?\((0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2})\)$/i;

/**
 * @see goog.color.alpha.rgbaColorRe_
 * @const
 * @type {RegExp}
 * @private
 */
ol.color.rgbaColorRe_ =
    /^(?:rgba)?\((0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2}),\s?(0|1|0\.\d{0,10})\)$/i;

/**
 * @param {ol.Color} dst Destination.
 * @param {ol.Color} src Source.
 * @param {ol.Color=} opt_color Color.
 * @return {ol.Color} Color.
 */
ol.color.blend = function(dst, src, opt_color) {
  // http://en.wikipedia.org/wiki/Alpha_compositing
  // FIXME do we need to scale by 255?
  var out = goog.isDef(opt_color) ? opt_color : [];
  var dstA = dst[3];
  var srcA = dst[3];
  if (dstA == 1) {
    out[0] = (src[0] * srcA + dst[0] * (1 - srcA) + 0.5) | 0;
    out[1] = (src[1] * srcA + dst[1] * (1 - srcA) + 0.5) | 0;
    out[2] = (src[2] * srcA + dst[2] * (1 - srcA) + 0.5) | 0;
    out[4] = 1;
  } else if (srcA === 0) {
    out[0] = dst[0];
    out[1] = dst[1];
    out[2] = dst[2];
    out[3] = dstA;
  } else {
    var outA = srcA + dstA * (1 - srcA);
    if (outA === 0) {
      out[0] = 0;
      out[1] = 0;
      out[2] = 0;
      out[3] = 0;
    } else {
      out[0] = ((src[0] * srcA + dst[0] * dstA * (1 - srcA)) / outA + 0.5) | 0;
      out[1] = ((src[1] * srcA + dst[1] * dstA * (1 - srcA)) / outA + 0.5) | 0;
      out[2] = ((src[2] * srcA + dst[2] * dstA * (1 - srcA)) / outA + 0.5) | 0;
      out[3] = outA;
    }
  }
  goog.asserts.assert(ol.color.isValid(out));
  return out;
};

/**
 * @param {ol.Color|string} color Color.
 * @return {ol.Color} Color.
 */
ol.color.asArray = function(color) {
  if (goog.isArray(color)) {
    return color;
  } else {
    goog.asserts.assert(goog.isString(color));
    return ol.color.fromString(color);
  }
};

/**
 * @param {ol.Color|string} color Color.
 * @return {string} String.
 */
ol.color.asString = function(color) {
  if (goog.isString(color)) {
    return color;
  } else {
    goog.asserts.assert(goog.isArray(color));
    return ol.color.toString(color);
  }
};

/**
 * @param {ol.Color} color1 Color1.
 * @param {ol.Color} color2 Color2.
 * @return {boolean} Equals.
 */
ol.color.equals = function(color1, color2) {
  return color1 === color2 || (
      color1[0] == color2[0] && color1[1] == color2[1] &&
      color1[2] == color2[2] && color1[3] == color2[3]);
};

/**
 * @param {string} s String.
 * @param {ol.Color=} opt_color Color.
 * @return {ol.Color} Color.
 */
ol.color.fromString = (
    /**
     * @return {function(string, ol.Color=): ol.Color}
     */
    function() {

      // We maintain a small cache of parsed strings.  To provide cheap LRU-like
      // semantics, whenever the cache grows too large we simply delete an
      // arbitrary 25% of the entries.

      /**
       * @const
       * @type {number}
       */
      var MAX_CACHE_SIZE = 1024;

      /**
       * @type {Object.<string, ol.Color>}
       */
      var cache = {};

      /**
       * @type {number}
       */
      var cacheSize = 0;

      return (
          /**
           * @param {string} s String.
           * @param {ol.Color=} opt_color Color.
           * @return {ol.Color} Color.
           */
          function(s, opt_color) {
            var color;
            if (cache.hasOwnProperty(s)) {
              color = cache[s];
            } else {
              if (cacheSize >= MAX_CACHE_SIZE) {
                var i = 0;
                var key;
                for (key in cache) {
                  if (i++ & 3 === 0) {
                    delete cache[key];
                    --cacheSize;
                  }
                }
              }
              color = ol.color.fromStringInternal_(s);
              cache[s] = color;
              ++cacheSize;
            }
            return ol.color.returnOrUpdate(color, opt_color);
          });

    })();

/**
 * @param {string} s String.
 * @private
 * @return {ol.Color} Color.
 */
ol.color.fromStringInternal_ = function(s) {

  var isHex = false;
  if (ol.color.ENABLE_NAMED_COLORS && goog.color.names.hasOwnProperty(s)) {
    // goog.color.names does not have a type declaration, so add a typecast
    s = /** @type {string} */ (goog.color.names[s]);
    isHex = true;
  }

  var r, g, b, a, color, match;
  if (isHex || (match = ol.color.hexColorRe_.exec(s))) { // hex
    var n = s.length - 1; // number of hex digits
    goog.asserts.assert(n == 3 || n == 6);
    var d = n == 3 ? 1 : 2; // number of digits per channel
    r = parseInt(s.substr(1 + 0 * d, d), 16);
    g = parseInt(s.substr(1 + 1 * d, d), 16);
    b = parseInt(s.substr(1 + 2 * d, d), 16);
    if (d == 1) {
      r = (r << 4) + r;
      g = (g << 4) + g;
      b = (b << 4) + b;
    }
    a = 1;
    color = [r, g, b, a];
    goog.asserts.assert(ol.color.isValid(color));
    return color;
  } else if ((match = ol.color.rgbaColorRe_.exec(s))) { // rgba()
    r = Number(match[1]);
    g = Number(match[2]);
    b = Number(match[3]);
    a = Number(match[4]);
    color = [r, g, b, a];
    return ol.color.normalize(color, color);
  } else if ((match = ol.color.rgbColorRe_.exec(s))) { // rgb()
    r = Number(match[1]);
    g = Number(match[2]);
    b = Number(match[3]);
    color = [r, g, b, 1];
    return ol.color.normalize(color, color);
  } else {
    throw new Error(s + ' is not a valid color');
  }

};

/**
 * @param {ol.Color} color Color.
 * @return {boolean} Is valid.
 */
ol.color.isValid = function(color) {
  return 0 <= color[0] && color[0] < 256 &&
      0 <= color[1] && color[1] < 256 &&
      0 <= color[2] && color[2] < 256 &&
      0 <= color[3] && color[3] <= 1;
};

/**
 * @param {ol.Color} color Color.
 * @param {ol.Color=} opt_color Color.
 * @return {ol.Color} Clamped color.
 */
ol.color.normalize = function(color, opt_color) {
  var result = goog.isDef(opt_color) ? opt_color : [];
  result[0] = goog.math.clamp((color[0] + 0.5) | 0, 0, 255);
  result[1] = goog.math.clamp((color[1] + 0.5) | 0, 0, 255);
  result[2] = goog.math.clamp((color[2] + 0.5) | 0, 0, 255);
  result[3] = goog.math.clamp(color[3], 0, 1);
  return result;
};

/**
 * @param {ol.Color} color Color.
 * @param {ol.Color=} opt_color Color.
 * @return {ol.Color} Color.
 */
ol.color.returnOrUpdate = function(color, opt_color) {
  if (goog.isDef(opt_color)) {
    opt_color[0] = color[0];
    opt_color[1] = color[1];
    opt_color[2] = color[2];
    opt_color[3] = color[3];
    return opt_color;
  } else {
    return color;
  }
};

/**
 * @param {ol.Color} color Color.
 * @return {string} String.
 */
ol.color.toString = function(color) {
  var r = color[0];
  if (r != (r | 0)) {
    r = (r + 0.5) | 0;
  }
  var g = color[1];
  if (g != (g | 0)) {
    g = (g + 0.5) | 0;
  }
  var b = color[2];
  if (b != (b | 0)) {
    b = (b + 0.5) | 0;
  }
  var a = color[3];
  return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';
};

/**
 * @param {ol.Color} color Color.
 * @param {goog.vec.Mat4.Number} transform Transform.
 * @param {ol.Color=} opt_color Color.
 * @return {ol.Color} Transformed color.
 */
ol.color.transform = function(color, transform, opt_color) {
  var result = goog.isDef(opt_color) ? opt_color : [];
  result = goog.vec.Mat4.multVec3(transform, color, result);
  goog.asserts.assert(goog.isArray(result));
  result[3] = color[3];
  return ol.color.normalize(result, result);
};

/**
 * @param {ol.Color|string} color1 Color2.
 * @param {ol.Color|string} color2 Color2.
 * @return {boolean} Equals.
 */
ol.color.stringOrColorEquals = function(color1, color2) {
  if (color1 === color2 || color1 == color2) {
    return true;
  }
  if (goog.isString(color1)) {
    color1 = ol.color.fromString(color1);
  }
  if (goog.isString(color2)) {
    color2 = ol.color.fromString(color2);
  }
  return ol.color.equals(color1, color2);
};
<commit_msg>Fix handling of the color cache<commit_after>// We can't use goog.color or goog.color.alpha because they interally use a hex
// string representation that encodes each channel in a single byte.  This
// causes occasional loss of precision and rounding errors, especially in the
// alpha channel.

goog.provide('ol.color');

goog.require('goog.array');
goog.require('goog.asserts');
goog.require('goog.color');
goog.require('goog.color.names');
goog.require('goog.math');
goog.require('goog.vec.Mat4');

/**
 * @define {boolean} Enable named colors.
 * Enabling named colors adds about 3KB uncompressed / 1.5KB compressed to the
 * final build size.
 */
ol.color.ENABLE_NAMED_COLORS = true;

/**
 * A color represented as a short array [red, green, blue, alpha].
 * red, green, and blue should be integers in the range 0..255 inclusive.
 * alpha should be a float in the range 0..1 inclusive.
 * @typedef {Array.<number>}
 */
ol.Color;

/**
 * This RegExp matches # followed by 3 or 6 hex digits.
 * @const
 * @type {RegExp}
 * @private
 */
ol.color.hexColorRe_ = /^#(?:[0-9a-f]{3}){1,2}$/i;

/**
 * @see goog.color.rgbColorRe_
 * @const
 * @type {RegExp}
 * @private
 */
ol.color.rgbColorRe_ =
    /^(?:rgb)?\((0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2})\)$/i;

/**
 * @see goog.color.alpha.rgbaColorRe_
 * @const
 * @type {RegExp}
 * @private
 */
ol.color.rgbaColorRe_ =
    /^(?:rgba)?\((0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2}),\s?(0|1|0\.\d{0,10})\)$/i;

/**
 * @param {ol.Color} dst Destination.
 * @param {ol.Color} src Source.
 * @param {ol.Color=} opt_color Color.
 * @return {ol.Color} Color.
 */
ol.color.blend = function(dst, src, opt_color) {
  // http://en.wikipedia.org/wiki/Alpha_compositing
  // FIXME do we need to scale by 255?
  var out = goog.isDef(opt_color) ? opt_color : [];
  var dstA = dst[3];
  var srcA = dst[3];
  if (dstA == 1) {
    out[0] = (src[0] * srcA + dst[0] * (1 - srcA) + 0.5) | 0;
    out[1] = (src[1] * srcA + dst[1] * (1 - srcA) + 0.5) | 0;
    out[2] = (src[2] * srcA + dst[2] * (1 - srcA) + 0.5) | 0;
    out[4] = 1;
  } else if (srcA === 0) {
    out[0] = dst[0];
    out[1] = dst[1];
    out[2] = dst[2];
    out[3] = dstA;
  } else {
    var outA = srcA + dstA * (1 - srcA);
    if (outA === 0) {
      out[0] = 0;
      out[1] = 0;
      out[2] = 0;
      out[3] = 0;
    } else {
      out[0] = ((src[0] * srcA + dst[0] * dstA * (1 - srcA)) / outA + 0.5) | 0;
      out[1] = ((src[1] * srcA + dst[1] * dstA * (1 - srcA)) / outA + 0.5) | 0;
      out[2] = ((src[2] * srcA + dst[2] * dstA * (1 - srcA)) / outA + 0.5) | 0;
      out[3] = outA;
    }
  }
  goog.asserts.assert(ol.color.isValid(out));
  return out;
};

/**
 * @param {ol.Color|string} color Color.
 * @return {ol.Color} Color.
 */
ol.color.asArray = function(color) {
  if (goog.isArray(color)) {
    return color;
  } else {
    goog.asserts.assert(goog.isString(color));
    return ol.color.fromString(color);
  }
};

/**
 * @param {ol.Color|string} color Color.
 * @return {string} String.
 */
ol.color.asString = function(color) {
  if (goog.isString(color)) {
    return color;
  } else {
    goog.asserts.assert(goog.isArray(color));
    return ol.color.toString(color);
  }
};

/**
 * @param {ol.Color} color1 Color1.
 * @param {ol.Color} color2 Color2.
 * @return {boolean} Equals.
 */
ol.color.equals = function(color1, color2) {
  return color1 === color2 || (
      color1[0] == color2[0] && color1[1] == color2[1] &&
      color1[2] == color2[2] && color1[3] == color2[3]);
};

/**
 * @param {string} s String.
 * @param {ol.Color=} opt_color Color.
 * @return {ol.Color} Color.
 */
ol.color.fromString = (
    /**
     * @return {function(string, ol.Color=): ol.Color}
     */
    function() {

      // We maintain a small cache of parsed strings.  To provide cheap LRU-like
      // semantics, whenever the cache grows too large we simply delete an
      // arbitrary 25% of the entries.

      /**
       * @const
       * @type {number}
       */
      var MAX_CACHE_SIZE = 1024;

      /**
       * @type {Object.<string, ol.Color>}
       */
      var cache = {};

      /**
       * @type {number}
       */
      var cacheSize = 0;

      return (
          /**
           * @param {string} s String.
           * @param {ol.Color=} opt_color Color.
           * @return {ol.Color} Color.
           */
          function(s, opt_color) {
            var color;
            if (cache.hasOwnProperty(s)) {
              color = cache[s];
            } else {
              if (cacheSize >= MAX_CACHE_SIZE) {
                var i = 0;
                var key;
                for (key in cache) {
                  if ((i++ & 3) === 0) {
                    delete cache[key];
                    --cacheSize;
                  }
                }
              }
              color = ol.color.fromStringInternal_(s);
              cache[s] = color;
              ++cacheSize;
            }
            return ol.color.returnOrUpdate(color, opt_color);
          });

    })();

/**
 * @param {string} s String.
 * @private
 * @return {ol.Color} Color.
 */
ol.color.fromStringInternal_ = function(s) {

  var isHex = false;
  if (ol.color.ENABLE_NAMED_COLORS && goog.color.names.hasOwnProperty(s)) {
    // goog.color.names does not have a type declaration, so add a typecast
    s = /** @type {string} */ (goog.color.names[s]);
    isHex = true;
  }

  var r, g, b, a, color, match;
  if (isHex || (match = ol.color.hexColorRe_.exec(s))) { // hex
    var n = s.length - 1; // number of hex digits
    goog.asserts.assert(n == 3 || n == 6);
    var d = n == 3 ? 1 : 2; // number of digits per channel
    r = parseInt(s.substr(1 + 0 * d, d), 16);
    g = parseInt(s.substr(1 + 1 * d, d), 16);
    b = parseInt(s.substr(1 + 2 * d, d), 16);
    if (d == 1) {
      r = (r << 4) + r;
      g = (g << 4) + g;
      b = (b << 4) + b;
    }
    a = 1;
    color = [r, g, b, a];
    goog.asserts.assert(ol.color.isValid(color));
    return color;
  } else if ((match = ol.color.rgbaColorRe_.exec(s))) { // rgba()
    r = Number(match[1]);
    g = Number(match[2]);
    b = Number(match[3]);
    a = Number(match[4]);
    color = [r, g, b, a];
    return ol.color.normalize(color, color);
  } else if ((match = ol.color.rgbColorRe_.exec(s))) { // rgb()
    r = Number(match[1]);
    g = Number(match[2]);
    b = Number(match[3]);
    color = [r, g, b, 1];
    return ol.color.normalize(color, color);
  } else {
    throw new Error(s + ' is not a valid color');
  }

};

/**
 * @param {ol.Color} color Color.
 * @return {boolean} Is valid.
 */
ol.color.isValid = function(color) {
  return 0 <= color[0] && color[0] < 256 &&
      0 <= color[1] && color[1] < 256 &&
      0 <= color[2] && color[2] < 256 &&
      0 <= color[3] && color[3] <= 1;
};

/**
 * @param {ol.Color} color Color.
 * @param {ol.Color=} opt_color Color.
 * @return {ol.Color} Clamped color.
 */
ol.color.normalize = function(color, opt_color) {
  var result = goog.isDef(opt_color) ? opt_color : [];
  result[0] = goog.math.clamp((color[0] + 0.5) | 0, 0, 255);
  result[1] = goog.math.clamp((color[1] + 0.5) | 0, 0, 255);
  result[2] = goog.math.clamp((color[2] + 0.5) | 0, 0, 255);
  result[3] = goog.math.clamp(color[3], 0, 1);
  return result;
};

/**
 * @param {ol.Color} color Color.
 * @param {ol.Color=} opt_color Color.
 * @return {ol.Color} Color.
 */
ol.color.returnOrUpdate = function(color, opt_color) {
  if (goog.isDef(opt_color)) {
    opt_color[0] = color[0];
    opt_color[1] = color[1];
    opt_color[2] = color[2];
    opt_color[3] = color[3];
    return opt_color;
  } else {
    return color;
  }
};

/**
 * @param {ol.Color} color Color.
 * @return {string} String.
 */
ol.color.toString = function(color) {
  var r = color[0];
  if (r != (r | 0)) {
    r = (r + 0.5) | 0;
  }
  var g = color[1];
  if (g != (g | 0)) {
    g = (g + 0.5) | 0;
  }
  var b = color[2];
  if (b != (b | 0)) {
    b = (b + 0.5) | 0;
  }
  var a = color[3];
  return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';
};

/**
 * @param {ol.Color} color Color.
 * @param {goog.vec.Mat4.Number} transform Transform.
 * @param {ol.Color=} opt_color Color.
 * @return {ol.Color} Transformed color.
 */
ol.color.transform = function(color, transform, opt_color) {
  var result = goog.isDef(opt_color) ? opt_color : [];
  result = goog.vec.Mat4.multVec3(transform, color, result);
  goog.asserts.assert(goog.isArray(result));
  result[3] = color[3];
  return ol.color.normalize(result, result);
};

/**
 * @param {ol.Color|string} color1 Color2.
 * @param {ol.Color|string} color2 Color2.
 * @return {boolean} Equals.
 */
ol.color.stringOrColorEquals = function(color1, color2) {
  if (color1 === color2 || color1 == color2) {
    return true;
  }
  if (goog.isString(color1)) {
    color1 = ol.color.fromString(color1);
  }
  if (goog.isString(color2)) {
    color2 = ol.color.fromString(color2);
  }
  return ol.color.equals(color1, color2);
};
<|endoftext|>