<commit_before>define(["sprd/data/SprdModel", "sprd/entity/Size", "sprd/entity/PrintTypeColor", "js/data/Entity"], function (SprdModel, Size, PrintTypeColor, Entity) {

    var PrintType = SprdModel.inherit("sprd.model.PrintType", {

        defaults: {
            dpi: null
        },

        schema: {
            dpi: String,
            size: Size,
            colors: [PrintTypeColor]
        },

        isScaleable: function() {
            var scaleability = this.get("restrictions.scaleability");
            return scaleability !== SCALEABILITY.UNUSABLE && scaleability === SCALEABILITY.UNSCALABLE;
        },

        isEnlargeable: function() {
            return this.get("restrictions.scaleability") === SCALEABILITY.ENLARGEABLE;
        },

        isShrinkable: function () {
            return this.get("restrictions.scaleability") === SCALEABILITY.SHRINKABLE;
        },

        containsPrintTypeColor: function(printTypeColor) {

        }
    });

    var SCALEABILITY = {
        ENLARGEABLE: "enlargeable",
        SHRINKABLE: "shrinkable",
        UNUSABLE: "unusable",
        UNSCALABLE: "unscalable"
    };

    PrintType.Restrictions = Entity.inherit("sprd.model.PrintType.Restrictions", {

        defaults: {
            colorSpace: "print_colors",
            whiteSupported: true,
            transparencySupported: true,
            scaleability: SCALEABILITY.ENLARGEABLE,
            maxPrintColorLayers: 3
        },

        schema: {
            colorSpace: String,
            whiteSupported: Boolean,
            transparencySupported: Boolean,
            scaleability: String,
            maxPrintColorLayers: Number,

            printableAlongWithPrintTypes: [PrintType],
            printableAbovePrintTypes: [PrintType]
        }

    });

    // extend schema, because circular dependency between PrintType and Restriction
    PrintType.prototype.schema.restrictions = PrintType.Restrictions;

    PrintType.Restrictions.SCALEABILITY = SCALEABILITY;

    return PrintType;
});
<commit_msg>renamed isScaleable to isScalable<commit_after>define(["sprd/data/SprdModel", "sprd/entity/Size", "sprd/entity/PrintTypeColor", "js/data/Entity"], function (SprdModel, Size, PrintTypeColor, Entity) {

    var PrintType = SprdModel.inherit("sprd.model.PrintType", {

        defaults: {
            dpi: null
        },

        schema: {
            dpi: String,
            size: Size,
            colors: [PrintTypeColor]
        },

        isScalable: function() {
            var scaleability = this.get("restrictions.scaleability");
            return scaleability !== SCALEABILITY.UNUSABLE && scaleability !== SCALEABILITY.UNSCALABLE;

        },

        isEnlargeable: function() {
            return this.get("restrictions.scaleability") === SCALEABILITY.ENLARGEABLE;
        },

        isShrinkable: function () {
            return this.get("restrictions.scaleability") === SCALEABILITY.SHRINKABLE;
        },

        containsPrintTypeColor: function(printTypeColor) {

        }
    });

    var SCALEABILITY = {
        ENLARGEABLE: "enlargeable",
        SHRINKABLE: "shrinkable",
        UNUSABLE: "unusable",
        UNSCALABLE: "unscalable"
    };

    PrintType.Restrictions = Entity.inherit("sprd.model.PrintType.Restrictions", {

        defaults: {
            colorSpace: "print_colors",
            whiteSupported: true,
            transparencySupported: true,
            scaleability: SCALEABILITY.ENLARGEABLE,
            maxPrintColorLayers: 3
        },

        schema: {
            colorSpace: String,
            whiteSupported: Boolean,
            transparencySupported: Boolean,
            scaleability: String,
            maxPrintColorLayers: Number,

            printableAlongWithPrintTypes: [PrintType],
            printableAbovePrintTypes: [PrintType]
        }

    });

    // extend schema, because circular dependency between PrintType and Restriction
    PrintType.prototype.schema.restrictions = PrintType.Restrictions;

    PrintType.Restrictions.SCALEABILITY = SCALEABILITY;

    return PrintType;
});
<|endoftext|>


<commit_before>'use strict';
var React = require('react');

var paths = require('../paths');
var _ = require('lodash');
var config = require('config');

module.exports = {
  contextTypes: {
    router: React.PropTypes.func
  },

  getPathPrefix: function(pathName) {
    var prefix = '';

    // skip root paths
    if(pathName[1] !== '/') {
      prefix = pathName.split('/').map(function() {
        return '';
      }).join('../');
    }

    return prefix;
  },

  getAllItems: function () {
    return paths.allItems();
  },
  getSection: function () {
    var sectionName = this.getSectionName();
    var ret = config.paths[sectionName];

    if(!ret) {
      console.warn('Failed to find section ' +  sectionName + ' within ' +
        Object.keys(config.paths).join(', '));

      return {};
    }

    return ret;
  },
  getSectionTitle: function () {
    return this.getSection().title || '';
  },
  getSectionName: function () {
    let item = this.getItem();

    if(item.section) {
      return item.section;
    }

    // strip /
    return this.context.router.getCurrentPath().slice(1);
  },
  getSectionItems: function () {
    let section = this.getSectionName();

    return _.filter(this.getAllItems(), function (item) {
      return item.section == section;
    });
  },
  getItem: function() {
    let router = this.context.router;
    let params = router.getCurrentParams();
    let item = params.item;
    let splat = params.splat;

    if(splat) {
      return this.getItemForPath(splat + '/' + item);
    }

    return this.getItemForPath(item ? item : '/index');
  },
  getItemForPath: function(path) {
    var ret = paths.itemForPath(path);

    if(!ret) {
      console.warn('No item was found for path ' + path + '!');
    }

    return ret;
  },
  // TODO: rename as getItemTitle?
  getPageTitle: function() {
    let item = this.getItem();

    if(item && item.title) {
      return item.title;
    }

    let router = this.context.router;
    let routes = router.getCurrentRoutes();

    let routeName = routes[routes.length - 1].name;

    if(routeName) {
      return routeName.replace('/', '');
    }

    return '';
  },
};
<commit_msg>Allow section items to be get by section name<commit_after>'use strict';
var React = require('react');

var paths = require('../paths');
var _ = require('lodash');
var config = require('config');

module.exports = {
  contextTypes: {
    router: React.PropTypes.func
  },

  getPathPrefix: function(pathName) {
    var prefix = '';

    // skip root paths
    if(pathName[1] !== '/') {
      prefix = pathName.split('/').map(function() {
        return '';
      }).join('../');
    }

    return prefix;
  },

  getAllItems: function () {
    return paths.allItems();
  },
  getSection: function () {
    var sectionName = this.getSectionName();
    var ret = config.paths[sectionName];

    if(!ret) {
      console.warn('Failed to find section ' +  sectionName + ' within ' +
        Object.keys(config.paths).join(', '));

      return {};
    }

    return ret;
  },
  getSectionTitle: function () {
    return this.getSection().title || '';
  },
  getSectionName: function () {
    let item = this.getItem();

    if(item.section) {
      return item.section;
    }

    // strip /
    return this.context.router.getCurrentPath().slice(1);
  },
  getSectionItems: function (sectionName) {
    sectionName = sectionName || this.getSectionName();

    return _.filter(this.getAllItems(), function (item) {
      return item.section == sectionName;
    });
  },
  getItem: function() {
    let router = this.context.router;
    let params = router.getCurrentParams();
    let item = params.item;
    let splat = params.splat;

    if(splat) {
      return this.getItemForPath(splat + '/' + item);
    }

    return this.getItemForPath(item ? item : '/index');
  },
  getItemForPath: function(path) {
    var ret = paths.itemForPath(path);

    if(!ret) {
      console.warn('No item was found for path ' + path + '!');
    }

    return ret;
  },
  // TODO: rename as getItemTitle?
  getPageTitle: function() {
    let item = this.getItem();

    if(item && item.title) {
      return item.title;
    }

    let router = this.context.router;
    let routes = router.getCurrentRoutes();

    let routeName = routes[routes.length - 1].name;

    if(routeName) {
      return routeName.replace('/', '');
    }

    return '';
  },
};
<|endoftext|>


<commit_before>//Translated from board_analyser.rb using babyruby2js
'use strict';

var main = require('./main');
var Grid = require('./Grid');
var Group = require('./Group');
//require 'set';
var Goban = require('./Goban');
var ZoneFiller = require('./ZoneFiller');

/** @class Class used by BoardAnalyser class.
 *  A void in an empty zone surrounded by (and including) various groups.
 *  NB: when a void has a single color around; we call this an eye. Can be discussed...
 *  public read-only attribute: code, i, j, vcount, groups, eyeColor, owner
 *  code is the void code (like a color but higher index)
 *  neighbors is an array of n arrays, with n == number of colors
 */
function Void(analyser, code, i, j, vcount, neighbors) {
    this.analyzer = analyser;
    this.goban = analyser.goban;
    this.code = code;
    this.i = i;
    this.j = j;
    this.vcount = vcount;
    this.groups = neighbors; // neighboring groups (array of arrays; 1st index is color)
    this.eyeColor = null; // stays nil if not an eye
    this.owner = null;
}
module.exports = Void;

// Call it once. Populates @eye_color
// @eye_color stays nil if there is more than 1 color around (not an eye) or full board empty
Void.prototype.eyeCheck = function () {
    var oneColor = null;
    for (var c = 1; c <= this.groups.length; c++) {
        // is there 1 or more groups of this color?
        if (this.groups[c].length >= 1) {
            if (oneColor) { // we already had groups in another color
                oneColor = null;
                break;
            }
            oneColor = c;
        }
    }
    this.eyeColor = oneColor;
    // Now tell the groups about this void
    if (oneColor) {
        this.setOwner(oneColor);
        for (var n, n_array = this.groups, n_ndx = 0; n=n_array[n_ndx], n_ndx < n_array.length; n_ndx++) {
            for (var g, g_array = n, g_ndx = 0; g=g_array[g_ndx], g_ndx < g_array.length; g_ndx++) {
                g.addVoid(this, true);
            }
        }
        if (main.debug) {
            return main.log.debug('Color ' + oneColor + ' surrounds ' + this + ' (eye)');
        }
    } else {
        for (n, n_array = this.groups, n_ndx = 0; n=n_array[n_ndx], n_ndx < n_array.length; n_ndx++) {
            for (g, g_array = n, g_ndx = 0; g=g_array[g_ndx], g_ndx < g_array.length; g_ndx++) {
                g.addVoid(this);
            }
        }
        if (main.debug) {
            return main.log.debug(this + ' has to be sorted out...');
        }
    }
};

Void.prototype.setOwner = function (color) {
    this.owner = color;
};

Void.prototype.toString = function () {
    var s = 'void ' + this.code + ' (' + Grid.colorToChar(this.code) + '/' + this.i + ',' + this.j + '), vcount ' + this.vcount;
    for (var color = 1; color <= this.groups.length; color++) {
        s += ', ' + this.groups[color].length + ' ' + Grid.COLOR_NAMES[color] + ' neighbors';
    }
    return s;
};

Void.prototype.debugDump = function () {
    console.log(this.toString());
    for (var color = 1; color <= this.groups.length; color++) {
        console.log('    Color ' + color + ' (' + Grid.colorToChar(color) + '):');
        for (var neighbor, neighbor_array = this.groups[color], neighbor_ndx = 0; neighbor=neighbor_array[neighbor_ndx], neighbor_ndx < neighbor_array.length; neighbor_ndx++) {
            console.log(' #' + neighbor.ndx);
        }
    }
    console.log('\n');
};

/** @class public read-only attribute: goban, scores, prisoners
 */
function BoardAnalyser() {
    this.goban = null;
    this.voids = [];
    this.allGroups = new main.Set();
}
module.exports = BoardAnalyser;

// Calling this method updates the goban to show the detected result.
BoardAnalyser.prototype.countScore = function (goban, grid) {
    if (grid === undefined) grid = null;
    if (main.debug) {
        main.log.debug('Counting score...');
    }
    this.goban = goban;
    this.scores = [0, 0];
    this.prisoners = Group.prisoners(this.goban);
    this.filler = new ZoneFiller(this.goban, grid);
    this.findVoids();
    this.findEyes();
    this.findStrongerOwners();
    this.findDyingGroups();
    this.findDameVoids();
    this.colorVoids();
    for (var v, v_array = this.voids, v_ndx = 0; v=v_array[v_ndx], v_ndx < v_array.length; v_ndx++) {
        if (v.owner) {
            this.scores[v.owner] += v.vcount;
        }
    }
    if (main.debug) {
        return this.debugDump();
    }
};

BoardAnalyser.prototype.image = function () {
    return this.filler.grid.image();
};

BoardAnalyser.prototype.debugDump = function () {
    console.log(this.filler.grid.toText(function (c) {
        return Grid.colorToChar(c);
    }));
    for (var v, v_array = this.voids, v_ndx = 0; v=v_array[v_ndx], v_ndx < v_array.length; v_ndx++) {
        v.debugDump();
    }
    if (this.scores) {
        console.log('\nGroups with 2 eyes or more: ');
        for (var g, g_array = this.allGroups, g_ndx = 0; g=g_array[g_ndx], g_ndx < g_array.length; g_ndx++) {
            if (g.eyes.length >= 2) {
                console.log(g.ndx + ',');
            }
        }
        console.log('\nGroups with 1 eye: ');
        for (g, g_array = this.allGroups, g_ndx = 0; g=g_array[g_ndx], g_ndx < g_array.length; g_ndx++) {
            if (g.eyes.length === 1) {
                console.log(g.ndx + ',');
            }
        }
        console.log('\nGroups with no eye: ');
        for (g, g_array = this.allGroups, g_ndx = 0; g=g_array[g_ndx], g_ndx < g_array.length; g_ndx++) {
            if (g.eyes.length === 0) {
                console.log(g.ndx + ',');
            }
        }
        console.log('\nScore:\n');
        for (var i = 1; i <= this.scores.length; i++) {
            console.log('Player ' + i + ': ' + this.scores[i] + ' points');
        }
    }
};

//private;
BoardAnalyser.prototype.findVoids = function () {
    if (main.debug) {
        main.log.debug('Find voids...');
    }
    var voidCode = Grid.ZONE_CODE;
    for (var g, g_array = this.allGroups, g_ndx = 0; g=g_array[g_ndx], g_ndx < g_array.length; g_ndx++) {
        g.resetAnalysis();
    }
    this.allGroups.clear();
    this.voids.clear();
    var neighbors = [[], []];
    for (var j = 1; j <= this.goban.gsize; j++) {
        for (var i = 1; i <= this.goban.gsize; i++) {
            var vcount;
            if ((vcount = this.filler.fillWithColor(i, j, main.EMPTY, voidCode, neighbors)) > 0) {
                this.voids.push(new Void(this, voidCode, i, j, vcount, neighbors));
                voidCode += 1;
                // keep all the groups
                for (var n, n_array = neighbors, n_ndx = 0; n=n_array[n_ndx], n_ndx < n_array.length; n_ndx++) {
                    for (g, g_array = n, g_ndx = 0; g=g_array[g_ndx], g_ndx < g_array.length; g_ndx++) {
                        this.allGroups.add(g);
                    }
                }
                neighbors = [[], []];
            }
        }
    }
};

// Find voids surrounded by a single color -> eyes
BoardAnalyser.prototype.findEyes = function () {
    for (var v, v_array = this.voids, v_ndx = 0; v=v_array[v_ndx], v_ndx < v_array.length; v_ndx++) {
        v.eyeCheck();
    }
};

// Decides who owns a void by comparing the "liveness" of each side
BoardAnalyser.prototype.findStrongerOwners = function () {
    for (var v, v_array = this.voids, v_ndx = 0; v=v_array[v_ndx], v_ndx < v_array.length; v_ndx++) {
        if (v.eyeColor) {
            continue;
        }
        var lives = [0, 0];
        for (var c = 1; c <= 2; c++) {
            for (var g, g_array = v.groups[c], g_ndx = 0; g=g_array[g_ndx], g_ndx < g_array.length; g_ndx++) {
                lives[c] += g.lives;
            }
        }
        var moreLives = Math.max.apply(Math, lives);
        if (lives.count(function (l) {
            return l === moreLives;
        }) === 1) { // make sure we have a winner, not a tie
            c = lives.findIndex(moreLives);
            v.setOwner(c);
            if (main.debug) {
                main.log.debug('It looks like color ' + c + ', with ' + moreLives + ' lives, owns ' + v + ' (this might change once we identify dead groups)');
            }
        }
    }
};

// Reviews the groups and declare "dead" the ones who do not own any void
BoardAnalyser.prototype.findDyingGroups = function () {
    var ownedVoids, vcount, oneOwner, myVoid;
    for (var g, g_array = this.allGroups, g_ndx = 0; g=g_array[g_ndx], g_ndx < g_array.length; g_ndx++) {
        if (g.eyes.length >= 2) {
            continue;
        }
        if (g.eyes.length === 1 && g.eyes[0].vcount + g.extraLives >= 3) { // actually not enough if gote but well...
            continue;
        }
        var color = g.color;
        if (g.eyes.length === 1 && g.eyes[0].groups[color].length > 1) { // connected by eye
            continue;
        }
        // we need to look at voids around (fake eyes, etc.)
        ownedVoids = vcount = 0;
        oneOwner = myVoid = null;
        for (var v, v_array = g.voids, v_ndx = 0; v=v_array[v_ndx], v_ndx < v_array.length; v_ndx++) {
            if (v.owner) {
                oneOwner = v.owner;
                if (v.owner === color) {
                    myVoid = v;
                    ownedVoids += 1;
                    vcount += v.vcount;
                }
            }
        }
        if (g.eyes.length === 1 && ownedVoids >= 1) { // TODO: this is too lenient
            continue;
        }
        if (ownedVoids >= 2) { // TODO later: here is the horror we read about on the web
            continue;
        }
        if (ownedVoids === 1 && vcount + g.extraLives >= 3) {
            continue;
        }
        if (ownedVoids === 1 && myVoid.groups[color].length > 1) { // TODO: check also lives of ally
            continue;
        }
        // find if the only void around is owned (e.g. lost stones inside big territory)
        // if we don't know who owns the voids around g, leave g as alive (unfinished game)
        if (g.voids.length !== 0 && !oneOwner) {
            continue;
        }
        // g is dead!
        var stone = g.stones[0];
        var taken = this.filler.fillWithColor(stone.i, stone.j, color, Grid.DEAD_COLOR + color);
        this.prisoners[color] += taken;
        this.scores[1 - color] += taken;
        g.countAsDead();
        if (main.debug) {
            main.log.debug('Hence ' + g + ' is considered dead (' + taken + ' prisoners; 1st stone ' + stone + ')');
        }
        if (main.debug) {
            main.log.debug('eyes:' + g.eyes.length + ' owned_voids:' + ownedVoids + ' vcount-voids:' + vcount);
        }
    }
};

// Looks for "dame" = neutral voids (if alive groups from more than one color are around)
BoardAnalyser.prototype.findDameVoids = function () {
    for (var v, v_array = this.voids, v_ndx = 0; v=v_array[v_ndx], v_ndx < v_array.length; v_ndx++) {
        if (v.eyeColor) {
            continue;
        }
        var aliveColors = [];
        for (var c = 1; c <= 2; c++) {
            for (var g, g_array = v.groups[c], g_ndx = 0; g=g_array[g_ndx], g_ndx < g_array.length; g_ndx++) {
                if (this.groupLiveliness(g) >= 1) {
                    aliveColors.push(c);
                    break;
                }
            }
        }
        if (aliveColors.length >= 2) {
            v.setOwner(null);
            if (main.debug) {
                main.log.debug('Void ' + v + ' is considered neutral ("dame")');
            }
        }
    }
};

// Colors the voids with owner's color
BoardAnalyser.prototype.colorVoids = function () {
    for (var v, v_array = this.voids, v_ndx = 0; v=v_array[v_ndx], v_ndx < v_array.length; v_ndx++) {
        var c = (( v.owner ? Grid.TERRITORY_COLOR + v.owner : Grid.DAME_COLOR ));
        this.filler.fillWithColor(v.i, v.j, v.code, c);
    }
};

// Returns a number telling how "alive" a group is. TODO: review this
// Really basic logic for now.
// (instead we should determine if the shape of a single eye is right to make 2 eyes)
// - eyes and owned voids count for 1 point each
// - non-owned voids (undetermined owner or enemy-owned void) count for 0
// NB: for end-game counting, this logic is enough because undetermined situations
// have usually all been resolved (or this means both players cannot see it...)
BoardAnalyser.prototype.groupLiveliness = function (g) {
    return g.eyes.length + g.voids.count(function (z) {
        return z.owner === g.color;
    });
};

// W02: Unknown class supposed to be attached to main: Set
// E02: unknown method add(...)
// E02: unknown method find_index(...)<commit_msg>Manual fix Set in BoardAnalyser<commit_after>//Translated from board_analyser.rb using babyruby2js
'use strict';

var main = require('./main');
var Grid = require('./Grid');
var Group = require('./Group');
//require 'set';
var Goban = require('./Goban');
var ZoneFiller = require('./ZoneFiller');

/** @class Class used by BoardAnalyser class.
 *  A void in an empty zone surrounded by (and including) various groups.
 *  NB: when a void has a single color around; we call this an eye. Can be discussed...
 *  public read-only attribute: code, i, j, vcount, groups, eyeColor, owner
 *  code is the void code (like a color but higher index)
 *  neighbors is an array of n arrays, with n == number of colors
 */
function Void(analyser, code, i, j, vcount, neighbors) {
    this.analyzer = analyser;
    this.goban = analyser.goban;
    this.code = code;
    this.i = i;
    this.j = j;
    this.vcount = vcount;
    this.groups = neighbors; // neighboring groups (array of arrays; 1st index is color)
    this.eyeColor = null; // stays nil if not an eye
    this.owner = null;
}
module.exports = Void;

// Call it once. Populates @eye_color
// @eye_color stays nil if there is more than 1 color around (not an eye) or full board empty
Void.prototype.eyeCheck = function () {
    var oneColor = null;
    for (var c = 1; c <= this.groups.length; c++) {
        // is there 1 or more groups of this color?
        if (this.groups[c].length >= 1) {
            if (oneColor) { // we already had groups in another color
                oneColor = null;
                break;
            }
            oneColor = c;
        }
    }
    this.eyeColor = oneColor;
    // Now tell the groups about this void
    if (oneColor) {
        this.setOwner(oneColor);
        for (var n, n_array = this.groups, n_ndx = 0; n=n_array[n_ndx], n_ndx < n_array.length; n_ndx++) {
            for (var g, g_array = n, g_ndx = 0; g=g_array[g_ndx], g_ndx < g_array.length; g_ndx++) {
                g.addVoid(this, true);
            }
        }
        if (main.debug) {
            return main.log.debug('Color ' + oneColor + ' surrounds ' + this + ' (eye)');
        }
    } else {
        for (n, n_array = this.groups, n_ndx = 0; n=n_array[n_ndx], n_ndx < n_array.length; n_ndx++) {
            for (g, g_array = n, g_ndx = 0; g=g_array[g_ndx], g_ndx < g_array.length; g_ndx++) {
                g.addVoid(this);
            }
        }
        if (main.debug) {
            return main.log.debug(this + ' has to be sorted out...');
        }
    }
};

Void.prototype.setOwner = function (color) {
    this.owner = color;
};

Void.prototype.toString = function () {
    var s = 'void ' + this.code + ' (' + Grid.colorToChar(this.code) + '/' + this.i + ',' + this.j + '), vcount ' + this.vcount;
    for (var color = 1; color <= this.groups.length; color++) {
        s += ', ' + this.groups[color].length + ' ' + Grid.COLOR_NAMES[color] + ' neighbors';
    }
    return s;
};

Void.prototype.debugDump = function () {
    console.log(this.toString());
    for (var color = 1; color <= this.groups.length; color++) {
        console.log('    Color ' + color + ' (' + Grid.colorToChar(color) + '):');
        for (var neighbor, neighbor_array = this.groups[color], neighbor_ndx = 0; neighbor=neighbor_array[neighbor_ndx], neighbor_ndx < neighbor_array.length; neighbor_ndx++) {
            console.log(' #' + neighbor.ndx);
        }
    }
    console.log('\n');
};

/** @class public read-only attribute: goban, scores, prisoners
 */
function BoardAnalyser() {
    this.goban = null;
    this.voids = [];
    this.allGroups = new Set();
}
module.exports = BoardAnalyser;

// Calling this method updates the goban to show the detected result.
BoardAnalyser.prototype.countScore = function (goban, grid) {
    if (grid === undefined) grid = null;
    if (main.debug) {
        main.log.debug('Counting score...');
    }
    this.goban = goban;
    this.scores = [0, 0];
    this.prisoners = Group.prisoners(this.goban);
    this.filler = new ZoneFiller(this.goban, grid);
    this.findVoids();
    this.findEyes();
    this.findStrongerOwners();
    this.findDyingGroups();
    this.findDameVoids();
    this.colorVoids();
    for (var v, v_array = this.voids, v_ndx = 0; v=v_array[v_ndx], v_ndx < v_array.length; v_ndx++) {
        if (v.owner) {
            this.scores[v.owner] += v.vcount;
        }
    }
    if (main.debug) {
        return this.debugDump();
    }
};

BoardAnalyser.prototype.image = function () {
    return this.filler.grid.image();
};

BoardAnalyser.prototype.debugDump = function () {
    console.log(this.filler.grid.toText(function (c) {
        return Grid.colorToChar(c);
    }));
    for (var v, v_array = this.voids, v_ndx = 0; v=v_array[v_ndx], v_ndx < v_array.length; v_ndx++) {
        v.debugDump();
    }
    if (this.scores) {
        console.log('\nGroups with 2 eyes or more: ');
        this.allGroups.forEach(function (g) {
            if (g.eyes.length >= 2) {
                console.log(g.ndx + ',');
            }
        });
        console.log('\nGroups with 1 eye: ');
        this.allGroups.forEach(function (g) {
            if (g.eyes.length === 1) {
                console.log(g.ndx + ',');
            }
        });
        console.log('\nGroups with no eye: ');
        this.allGroups.forEach(function (g) {
            if (g.eyes.length === 0) {
                console.log(g.ndx + ',');
            }
        });
        console.log('\nScore:\n');
        for (var i = 1; i <= this.scores.length; i++) {
            console.log('Player ' + i + ': ' + this.scores[i] + ' points');
        }
    }
};

//private;
BoardAnalyser.prototype.findVoids = function () {
    if (main.debug) {
        main.log.debug('Find voids...');
    }
    var voidCode = Grid.ZONE_CODE;
    this.allGroups.forEach(function (g) {
        g.resetAnalysis();
    });
    this.allGroups.clear();
    this.voids.clear();
    var neighbors = [[], []];
    for (var j = 1; j <= this.goban.gsize; j++) {
        for (var i = 1; i <= this.goban.gsize; i++) {
            var vcount;
            if ((vcount = this.filler.fillWithColor(i, j, main.EMPTY, voidCode, neighbors)) > 0) {
                this.voids.push(new Void(this, voidCode, i, j, vcount, neighbors));
                voidCode += 1;
                // keep all the groups
                for (var n, n_array = neighbors, n_ndx = 0; n=n_array[n_ndx], n_ndx < n_array.length; n_ndx++) {
                    for (g, g_array = n, g_ndx = 0; g=g_array[g_ndx], g_ndx < g_array.length; g_ndx++) {
                        this.allGroups.add(g);
                    }
                }
                neighbors = [[], []];
            }
        }
    }
};

// Find voids surrounded by a single color -> eyes
BoardAnalyser.prototype.findEyes = function () {
    for (var v, v_array = this.voids, v_ndx = 0; v=v_array[v_ndx], v_ndx < v_array.length; v_ndx++) {
        v.eyeCheck();
    }
};

// Decides who owns a void by comparing the "liveness" of each side
BoardAnalyser.prototype.findStrongerOwners = function () {
    for (var v, v_array = this.voids, v_ndx = 0; v=v_array[v_ndx], v_ndx < v_array.length; v_ndx++) {
        if (v.eyeColor) {
            continue;
        }
        var lives = [0, 0];
        for (var c = 1; c <= 2; c++) {
            for (var g, g_array = v.groups[c], g_ndx = 0; g=g_array[g_ndx], g_ndx < g_array.length; g_ndx++) {
                lives[c] += g.lives;
            }
        }
        var moreLives = Math.max.apply(Math, lives);
        if (lives.count(function (l) {
            return l === moreLives;
        }) === 1) { // make sure we have a winner, not a tie
            c = lives.findIndex(moreLives);
            v.setOwner(c);
            if (main.debug) {
                main.log.debug('It looks like color ' + c + ', with ' + moreLives + ' lives, owns ' + v + ' (this might change once we identify dead groups)');
            }
        }
    }
};

// Reviews the groups and declare "dead" the ones who do not own any void
BoardAnalyser.prototype.findDyingGroups = function () {
    var ownedVoids, vcount, oneOwner, myVoid;
    this.allGroups.forEach(function (g) {
        if (g.eyes.length >= 2) {
            return;
        }
        if (g.eyes.length === 1 && g.eyes[0].vcount + g.extraLives >= 3) { // actually not enough if gote but well...
            return;
        }
        var color = g.color;
        if (g.eyes.length === 1 && g.eyes[0].groups[color].length > 1) { // connected by eye
            return;
        }
        // we need to look at voids around (fake eyes, etc.)
        ownedVoids = vcount = 0;
        oneOwner = myVoid = null;
        for (var v, v_array = g.voids, v_ndx = 0; v=v_array[v_ndx], v_ndx < v_array.length; v_ndx++) {
            if (v.owner) {
                oneOwner = v.owner;
                if (v.owner === color) {
                    myVoid = v;
                    ownedVoids += 1;
                    vcount += v.vcount;
                }
            }
        }
        if (g.eyes.length === 1 && ownedVoids >= 1) { // TODO: this is too lenient
            return;
        }
        if (ownedVoids >= 2) { // TODO later: here is the horror we read about on the web
            return;
        }
        if (ownedVoids === 1 && vcount + g.extraLives >= 3) {
            return;
        }
        if (ownedVoids === 1 && myVoid.groups[color].length > 1) { // TODO: check also lives of ally
            return;
        }
        // find if the only void around is owned (e.g. lost stones inside big territory)
        // if we don't know who owns the voids around g, leave g as alive (unfinished game)
        if (g.voids.length !== 0 && !oneOwner) {
            return;
        }
        // g is dead!
        var stone = g.stones[0];
        var taken = this.filler.fillWithColor(stone.i, stone.j, color, Grid.DEAD_COLOR + color);
        this.prisoners[color] += taken;
        this.scores[1 - color] += taken;
        g.countAsDead();
        if (main.debug) {
            main.log.debug('Hence ' + g + ' is considered dead (' + taken + ' prisoners; 1st stone ' + stone + ')');
        }
        if (main.debug) {
            main.log.debug('eyes:' + g.eyes.length + ' owned_voids:' + ownedVoids + ' vcount-voids:' + vcount);
        }
    });
};

// Looks for "dame" = neutral voids (if alive groups from more than one color are around)
BoardAnalyser.prototype.findDameVoids = function () {
    for (var v, v_array = this.voids, v_ndx = 0; v=v_array[v_ndx], v_ndx < v_array.length; v_ndx++) {
        if (v.eyeColor) {
            continue;
        }
        var aliveColors = [];
        for (var c = 1; c <= 2; c++) {
            for (var g, g_array = v.groups[c], g_ndx = 0; g=g_array[g_ndx], g_ndx < g_array.length; g_ndx++) {
                if (this.groupLiveliness(g) >= 1) {
                    aliveColors.push(c);
                    break;
                }
            }
        }
        if (aliveColors.length >= 2) {
            v.setOwner(null);
            if (main.debug) {
                main.log.debug('Void ' + v + ' is considered neutral ("dame")');
            }
        }
    }
};

// Colors the voids with owner's color
BoardAnalyser.prototype.colorVoids = function () {
    for (var v, v_array = this.voids, v_ndx = 0; v=v_array[v_ndx], v_ndx < v_array.length; v_ndx++) {
        var c = (( v.owner ? Grid.TERRITORY_COLOR + v.owner : Grid.DAME_COLOR ));
        this.filler.fillWithColor(v.i, v.j, v.code, c);
    }
};

// Returns a number telling how "alive" a group is. TODO: review this
// Really basic logic for now.
// (instead we should determine if the shape of a single eye is right to make 2 eyes)
// - eyes and owned voids count for 1 point each
// - non-owned voids (undetermined owner or enemy-owned void) count for 0
// NB: for end-game counting, this logic is enough because undetermined situations
// have usually all been resolved (or this means both players cannot see it...)
BoardAnalyser.prototype.groupLiveliness = function (g) {
    return g.eyes.length + g.voids.count(function (z) {
        return z.owner === g.color;
    });
};

// W02: Unknown class supposed to be attached to main: Set
// E02: unknown method add(...)
// E02: unknown method find_index(...)<|endoftext|>


<commit_before>// get path to this script, to link to json data files
var ___thisPath = document.getElementsByTagName('script')[document.getElementsByTagName('script').length - 1].src.split('?')[0].split('/').slice(0, -1).join('/') + '/';

$(function () {
    "use strict";

    $.widget("capesean.mapper", {
        // default options
        options: {
            fillColor: "rgb(248,92,92)",
            fillOpacity: 0.5,
            strokeColor: "#000",
            strokeWeight: 1,
            strokeOpacity: 0.7,
            data: [],
            dataType: "",
            province: "",
            allowAllWards: false,
            drawAll: false
        },

        // init variables
        _minLat: null,
        _maxLat: null,
        _minLng: null,
        _maxLng: null,

        // load data
        _getData: function () {

            var url;
            switch (this.options.dataType) {
                case "provinces":
                    url = "provinces.js";
                    break;
                case "districts":
                    url = "districts.js";
                    break;
                case "municipalities":
                    url = "municipalities.js";
                    break;
                case "wards":
                    // province filter not supplied
                    if (!this.options.province)
                        // error if not specifically requesting full wards file
                        if (!this.options.allowAllWards)
                            throw ("Error: Ward dataType requires either the province filter or the allowAllWards option enabled");
                        else
                            url = "wards.js";
                    else {
                        switch (this.options.province) {
                            case "Eastern Cape": url = "wards-ec.js"; break;
                            case "Free State": url = "wards-fs.js"; break;
                            case "Gauteng": url = "wards-gt.js"; break;
                            case "KwaZulu-Natal": url = "wards-kzn.js"; break;
                            case "Limpopo": url = "wards-lp.js"; break;
                            case "Mpumalanga": url = "wards-mp.js"; break;
                            case "North West": url = "wards-nw.js"; break;
                            case "Northern Cape": url = "wards-nc.js"; break;
                            case "Western Cape": url = "wards-wc.js"; break;
                            default:
                                throw ("Error: Invalid province filter: " + this.options.province);
                        }
                    }
                    break;
                default:
                    throw ("Error: Not Implemented dataType option in _getData: " + this.options.dataType);
            }

            var json = null;
            $.ajax({
                'async': false,
                'global': false,
                'url': ___thisPath + url,
                'dataType': "json",
                'success': function (data) {
                    json = data;
                }
            });
            return json;

        },

        // get bound limits by looping through all points
        _getBounds: function (data) {

            for (var e = 0; e < data.length; e++) { //entity
                for (var sh = 0; sh < data[e].shapes.length; sh++) { //shape
                    var coords = data[e].shapes[sh].coords;
                    for (var c = 0; c < coords.length; c++) { // coord
                        var coord = coords[c];
                        if (this._minLat === null || coord.lat < this._minLat) this._minLat = coord.lat;
                        if (this._maxLat === null || coord.lat > this._maxLat) this._maxLat = coord.lat;
                        if (this._minLng === null || coord.lng < this._minLng) this._minLng = coord.lng;
                        if (this._maxLng === null || coord.lng > this._maxLng) this._maxLng = coord.lng;
                    }
                }
            }

        },

        // shifts elements in an array
        _moveArrayElement: function (arr, oldIndex, newIndex) {

            if (newIndex >= arr.length) newIndex = arr.length;
            arr.splice(newIndex, 0, arr.splice(oldIndex, 1)[0]);

        },

        // prepares the list - filtering, ordering, etc
        _prepareList: function (data) {

            // check if no data was supplied as an option
            if (!this.options.data || this.options.data.length == 0) return;

            // for each item in the full list
            for (var m = data.length - 1; m >= 0; m--) {

                var item = data[m];

                // try get it from the options list
                var option = $.grep(this.options.data, function (e) { return e.id == item.id; })[0];

                if (!option) {
                    // wasn't supplied, so remove from the list (unless drawAll == true)
                    if (!this.options.drawAll)
                        data.splice(m, 1);
                } else {
                    // was supplied, so move to end of array (so the lines are drawn on top / last)
                    this._moveArrayElement(data, m, data.length);
                    // copy the styles & other properties, eg html info window
                    $.extend(item, option);
                }
            }
        },

        // the constructor
        _create: function () {

            // can only handle these data entities:
            if (['provinces', 'districts', 'municipalities', 'wards'].indexOf(this.options.dataType) < 0) {
                alert("Invalid dataType option");
                return false;
            }

            // load the data
            var data = this._getData();

            // prepare the list
            this._prepareList(data);

            // find the min/max coords
            this._getBounds(data);

            // setup map
            var mapOptions = {
                zoom: 9,
                center: new google.maps.LatLng(-33.9694, 18.5972),
                mapTypeId: google.maps.MapTypeId.ROADMAP,
                scrollwheel: false
            };
            var map = new google.maps.Map(this.element[0], mapOptions),
                bounds = new google.maps.LatLngBounds();

            // setup a global infoWindow
            var infoWindow = new google.maps.InfoWindow();

            // drawing.... for each item
            for (var m = 0; m < data.length; m++) {
                var item = data[m];

                // for each shape
                for (var sh = 0; sh < item.shapes.length; sh++) {
                    var coords = item.shapes[sh].coords,
                        polygon,
                        paths = [];

                    // foreach point/coord
                    for (var c = 0; c < coords.length; c++) {
                        var latLng = new google.maps.LatLng(coords[c].lat, coords[c].lng);
                        paths.push(latLng);
                        bounds.extend(latLng);
                    }

                    // setup the polygon
                    polygon = new google.maps.Polygon({
                        paths: paths,
                        strokeColor: item.strokeColor || this.options.strokeColor,
                        strokeOpacity: item.strokeOpacity || this.options.strokeOpacity,
                        strokeWeight: item.strokeWeight || this.options.strokeWeight,
                        fillColor: item.fillColor || this.options.fillColor,
                        fillOpacity: item.fillOpacity || this.options.fillOpacity,
                        html: item.html,
                        // include these properties so the click event handler can access them
                        dataType: this.options.dataType,
                        id: item.id,
                        ward_no: item.ward_no,
                        councillor: item.councillor,
                        description: item.description
                    });

                    // set on map
                    polygon.setMap(map);

                    // if there's html for a popup, add the listener
                    if (polygon.html) {
                        google.maps.event.addListener(polygon, 'click', function (event) {
                            infoWindow.setContent(this.html);
                            infoWindow.setPosition(event.latLng);
                            infoWindow.open(map);
                        });
                    }

                    // if there's a click event handler, add the listener
                    if (this.options.click) {
                        google.maps.event.addListener(polygon, 'click', this.options.click); // function(event)
                    }

                    // change opacity on mouseover & revert it on mouseout
                    google.maps.event.addListener(polygon, 'mouseover', function(event){
                        this.setOptions({fillOpacity: 0.8});
                    });
                    google.maps.event.addListener(polygon, 'mouseout', function(event){
                        this.setOptions({fillOpacity: 0.5});
                    });
                }
            }

            // zoom to fit the bounds
//            map.fitBounds(bounds);
        }
    });
});

<commit_msg>Thinner lines on plot, and lower opacity.<commit_after>// get path to this script, to link to json data files
var ___thisPath = document.getElementsByTagName('script')[document.getElementsByTagName('script').length - 1].src.split('?')[0].split('/').slice(0, -1).join('/') + '/';

$(function () {
    "use strict";

    $.widget("capesean.mapper", {
        // default options
        options: {
            fillColor: "rgb(248,92,92)",
            fillOpacity: 0.3,
            strokeColor: "#000",
            strokeWeight: 0.3,
            strokeOpacity: 0.7,
            data: [],
            dataType: "",
            province: "",
            allowAllWards: false,
            drawAll: false
        },

        // init variables
        _minLat: null,
        _maxLat: null,
        _minLng: null,
        _maxLng: null,

        // load data
        _getData: function () {

            var url;
            switch (this.options.dataType) {
                case "provinces":
                    url = "provinces.js";
                    break;
                case "districts":
                    url = "districts.js";
                    break;
                case "municipalities":
                    url = "municipalities.js";
                    break;
                case "wards":
                    // province filter not supplied
                    if (!this.options.province)
                        // error if not specifically requesting full wards file
                        if (!this.options.allowAllWards)
                            throw ("Error: Ward dataType requires either the province filter or the allowAllWards option enabled");
                        else
                            url = "wards.js";
                    else {
                        switch (this.options.province) {
                            case "Eastern Cape": url = "wards-ec.js"; break;
                            case "Free State": url = "wards-fs.js"; break;
                            case "Gauteng": url = "wards-gt.js"; break;
                            case "KwaZulu-Natal": url = "wards-kzn.js"; break;
                            case "Limpopo": url = "wards-lp.js"; break;
                            case "Mpumalanga": url = "wards-mp.js"; break;
                            case "North West": url = "wards-nw.js"; break;
                            case "Northern Cape": url = "wards-nc.js"; break;
                            case "Western Cape": url = "wards-wc.js"; break;
                            default:
                                throw ("Error: Invalid province filter: " + this.options.province);
                        }
                    }
                    break;
                default:
                    throw ("Error: Not Implemented dataType option in _getData: " + this.options.dataType);
            }

            var json = null;
            $.ajax({
                'async': false,
                'global': false,
                'url': ___thisPath + url,
                'dataType': "json",
                'success': function (data) {
                    json = data;
                }
            });
            return json;

        },

        // get bound limits by looping through all points
        _getBounds: function (data) {

            for (var e = 0; e < data.length; e++) { //entity
                for (var sh = 0; sh < data[e].shapes.length; sh++) { //shape
                    var coords = data[e].shapes[sh].coords;
                    for (var c = 0; c < coords.length; c++) { // coord
                        var coord = coords[c];
                        if (this._minLat === null || coord.lat < this._minLat) this._minLat = coord.lat;
                        if (this._maxLat === null || coord.lat > this._maxLat) this._maxLat = coord.lat;
                        if (this._minLng === null || coord.lng < this._minLng) this._minLng = coord.lng;
                        if (this._maxLng === null || coord.lng > this._maxLng) this._maxLng = coord.lng;
                    }
                }
            }

        },

        // shifts elements in an array
        _moveArrayElement: function (arr, oldIndex, newIndex) {

            if (newIndex >= arr.length) newIndex = arr.length;
            arr.splice(newIndex, 0, arr.splice(oldIndex, 1)[0]);

        },

        // prepares the list - filtering, ordering, etc
        _prepareList: function (data) {

            // check if no data was supplied as an option
            if (!this.options.data || this.options.data.length == 0) return;

            // for each item in the full list
            for (var m = data.length - 1; m >= 0; m--) {

                var item = data[m];

                // try get it from the options list
                var option = $.grep(this.options.data, function (e) { return e.id == item.id; })[0];

                if (!option) {
                    // wasn't supplied, so remove from the list (unless drawAll == true)
                    if (!this.options.drawAll)
                        data.splice(m, 1);
                } else {
                    // was supplied, so move to end of array (so the lines are drawn on top / last)
                    this._moveArrayElement(data, m, data.length);
                    // copy the styles & other properties, eg html info window
                    $.extend(item, option);
                }
            }
        },

        // the constructor
        _create: function () {

            // can only handle these data entities:
            if (['provinces', 'districts', 'municipalities', 'wards'].indexOf(this.options.dataType) < 0) {
                alert("Invalid dataType option");
                return false;
            }

            // load the data
            var data = this._getData();

            // prepare the list
            this._prepareList(data);

            // find the min/max coords
            this._getBounds(data);

            // setup map
            var mapOptions = {
                zoom: 9,
                center: new google.maps.LatLng(-33.9694, 18.5972),
                mapTypeId: google.maps.MapTypeId.ROADMAP,
                scrollwheel: false
            };
            var map = new google.maps.Map(this.element[0], mapOptions),
                bounds = new google.maps.LatLngBounds();

            // setup a global infoWindow
            var infoWindow = new google.maps.InfoWindow();

            // drawing.... for each item
            for (var m = 0; m < data.length; m++) {
                var item = data[m];

                // for each shape
                for (var sh = 0; sh < item.shapes.length; sh++) {
                    var coords = item.shapes[sh].coords,
                        polygon,
                        paths = [];

                    // foreach point/coord
                    for (var c = 0; c < coords.length; c++) {
                        var latLng = new google.maps.LatLng(coords[c].lat, coords[c].lng);
                        paths.push(latLng);
                        bounds.extend(latLng);
                    }

                    // setup the polygon
                    polygon = new google.maps.Polygon({
                        paths: paths,
                        strokeColor: item.strokeColor || this.options.strokeColor,
                        strokeOpacity: item.strokeOpacity || this.options.strokeOpacity,
                        strokeWeight: item.strokeWeight || this.options.strokeWeight,
                        fillColor: item.fillColor || this.options.fillColor,
                        fillOpacity: item.fillOpacity || this.options.fillOpacity,
                        html: item.html,
                        // include these properties so the click event handler can access them
                        dataType: this.options.dataType,
                        id: item.id,
                        ward_no: item.ward_no,
                        councillor: item.councillor,
                        description: item.description
                    });

                    // set on map
                    polygon.setMap(map);

                    // if there's html for a popup, add the listener
                    if (polygon.html) {
                        google.maps.event.addListener(polygon, 'click', function (event) {
                            infoWindow.setContent(this.html);
                            infoWindow.setPosition(event.latLng);
                            infoWindow.open(map);
                        });
                    }

                    // if there's a click event handler, add the listener
                    if (this.options.click) {
                        google.maps.event.addListener(polygon, 'click', this.options.click); // function(event)
                    }

                    // change opacity on mouseover & revert it on mouseout
                    google.maps.event.addListener(polygon, 'mouseover', function(event){
                        this.setOptions({fillOpacity: 0.6});
                    });
                    google.maps.event.addListener(polygon, 'mouseout', function(event){
                        this.setOptions({fillOpacity: 0.3});
                    });
                }
            }

            // zoom to fit the bounds
//            map.fitBounds(bounds);
        }
    });
});

<|endoftext|>


<commit_before>/*jslint indent: 2, nomen: true, maxlen: 100, vars: true, white: true, plusplus: true*/
/*global Backbone, $, _, window, templateEngine, arangoHelper*/

(function() {
  "use strict";

  window.GraphManagementView = Backbone.View.extend({
    el: '#content',
    template: templateEngine.createTemplate("graphManagementView.ejs"),
    edgeDefintionTemplate: templateEngine.createTemplate("edgeDefinitionTable.ejs"),

    events: {
      "click #deleteGraph"                  : "deleteGraph",
      "click .icon_arangodb_settings2"      : "editGraph",
      "click .icon_arangodb_info"           : "info",
      "click #createGraph"                  : "addNewGraph",
      "keyup #graphManagementSearchInput"   : "search",
      "click #graphManagementSearchSubmit"  : "search"
    },

    addNewGraph: function(e) {
      e.preventDefault();
      this.createNewGraphModal2();
    },

    deleteGraph: function(e) {
      var self = this;
      var name = $('#editGraphName').html();
      this.collection.get(name).destroy({
        success: function() {
          self.updateGraphManagementView();
          window.modalView.hide();
        },
        error: function(xhr, err) {
          var response = JSON.parse(err.responseText),
            msg = response.errorMessage;
          arangoHelper.arangoError(msg);
          window.modalView.hide();
        }
      });
    },

    render: function() {
      this.collection.fetch({
        async: false
      });

      $(this.el).html(this.template.render({
        graphs: this.collection,
        searchString : ''
      }));
      this.events["click .tableRow"] = this.showHideDefinition.bind(this);
      this.events["click .graphViewer-icon-button"] = this.addRemoveDefinition.bind(this);
      return this;
    },

    editGraph : function(e) {
      this.collection.fetch();
      this.graphToEdit = this.evaluateGraphName($(e.currentTarget).attr("id"), '_settings');
      var graph = this.collection.findWhere({_key: this.graphToEdit});
      this.createEditGraphModal(this.graphToEdit, graph.get("vertices"), graph.get("edges"));
    },

    info : function(e) {
      this.collection.fetch();
      var graph = this.collection.findWhere(
        {_key: this.evaluateGraphName($(e.currentTarget).attr("id"), '_info')}
      );
      this.createInfoGraphModal(
        graph.get('_key'),
        graph.get('vertices'),
        graph.get('edges')
      );
    },

    evaluateGraphName : function(str, substr) {
      var index = str.lastIndexOf(substr);
      return str.substring(0, index);
    },

    search: function() {
      var searchInput,
        searchString,
        strLength,
        reducedCollection;

      searchInput = $('#graphManagementSearchInput');
      searchString = $("#graphManagementSearchInput").val();
      reducedCollection = this.collection.filter(
        function(u) {
          return u.get("_key").indexOf(searchString) !== -1;
        }
      );
      $(this.el).html(this.template.render({
        graphs        : reducedCollection,
        searchString  : searchString
      }));

      //after rendering, get the "new" element
      searchInput = $('#graphManagementSearchInput');
      //set focus on end of text in input field
      strLength= searchInput.val().length;
      searchInput.focus();
      searchInput[0].setSelectionRange(strLength, strLength);
    },

    updateGraphManagementView: function() {
      var self = this;
      this.collection.fetch({
        success: function() {
          self.render();
        }
      });
    },

    createNewGraph: function() {
      var _key = $("#createNewGraphName").val(),
        vertices = $("#newGraphVertices").val(),
        edges = $("#newGraphEdges").val(),
        self = this;
      if (!_key) {
        arangoHelper.arangoNotification(
          "A name for the graph has to be provided."
        );
        return;
      }
      if (!vertices) {
        arangoHelper.arangoNotification(
          "A vertex collection has to be provided."
        );
        return;
      }
      if (!edges) {
        arangoHelper.arangoNotification(
          "An edge collection has to be provided."
        );
        return;
      }
      this.collection.create({
        _key: _key,
        vertices: vertices,
        edges: edges
      }, {
        success: function() {
          self.updateGraphManagementView();
          window.modalView.hide();
        },
        error: function(obj, err) {
          var response = JSON.parse(err.responseText),
            msg = response.errorMessage;
          // Gritter does not display <>
          msg = msg.replace("<", "");
          msg = msg.replace(">", "");
          arangoHelper.arangoError(msg);
        }
      });
    },

    createNewGraph2: function() {
      var name = $("#createNewGraphName").val(),
        vertexCollections = _.pluck($('#newVertexCollections').select2("data"), "text"),
        edgeDefinitions = [],
        self = this,
        index = 0,
        collection,
        from,
        to,
        searchForNext = true;

      while(searchForNext) {
        collection = _.pluck($('#s2id_newEdgeDefinitions' + index).select2("data"), "text")[0];
        if (collection && collection !== "") {
          from = _.pluck($('#s2id_newFromCollections' + index).select2("data"), "text");
          to = _.pluck($('#s2id_newToCollections' + index).select2("data"), "text");
          if (from !== 1 && to !== 1) {
            edgeDefinitions.push(
              {
                collection: collection,
                from: from,
                to: to
              }
            );
          }
        } else {
          searchForNext = false;
        }
        index++;
      }

      if (!name) {
        arangoHelper.arangoNotification(
          "A name for the graph has to be provided."
        );
        return;
      }
      this.collection.create({
        name: name,
        edgeDefinitions: edgeDefinitions,
        orphanCollections: vertexCollections
      }, {
        success: function() {
          self.updateGraphManagementView();
          window.modalView.hide();
        },
        error: function(obj, err) {
          var response = JSON.parse(err.responseText),
            msg = response.errorMessage;
          // Gritter does not display <>
          msg = msg.replace("<", "");
          msg = msg.replace(">", "");
          arangoHelper.arangoError(msg);
        }
      });
    },

    createNewGraphModal: function() {
      var buttons = [],
        tableContent = [];

      tableContent.push(
        window.modalView.createTextEntry(
          "createNewGraphName",
          "Name",
          "",
          "The name to identify the graph. Has to be unique.",
          "graphName",
          true
        )
      );
      tableContent.push(
        window.modalView.createTextEntry(
          "newGraphVertices",
          "Vertices",
          "",
          "The path name of the document collection that should be used as vertices. "
            + "If this does not exist it will be created.",
          "Vertex Collection",
          true
        )
      );
      tableContent.push(
        window.modalView.createTextEntry(
          "newGraphEdges",
          "Edges",
          "",
          "The path name of the edge collection that should be used as edges. "
            + "If this does not exist it will be created.",
          "Edge Collection",
          true
        )
      );
      buttons.push(
        window.modalView.createSuccessButton("Create", this.createNewGraph2.bind(this))
      );
      window.modalView.show("modalTable.ejs", "Add new Graph", buttons, tableContent);
    },

    createEditGraphModal: function(name, vertices, edges) {
      var buttons = [],
        tableContent = [];

      tableContent.push(
        window.modalView.createReadOnlyEntry(
          "editGraphName",
          "Name",
          name,
          false
        )
      );
      tableContent.push(
        window.modalView.createReadOnlyEntry(
          "editVertices",
          "Vertices",
          vertices,
          false
        )
      );
      tableContent.push(
        window.modalView.createReadOnlyEntry(
          "editEdges",
          "Edges",
          edges,
          false
        )
      );

      buttons.push(
        window.modalView.createDeleteButton("Delete", this.deleteGraph.bind(this))
      );

      window.modalView.show("modalTable.ejs", "Edit Graph", buttons, tableContent);

    },

    createInfoGraphModal: function(name, vertices, edges) {
      var buttons = [],
        tableContent = [];

      tableContent.push(
        window.modalView.createReadOnlyEntry(
          "infoGraphName",
          "Name",
          name,
          false
        )
      );
      tableContent.push(
        window.modalView.createReadOnlyEntry(
          "infoVertices",
          "Vertices",
          vertices,
          false
        )
      );
      tableContent.push(
        window.modalView.createReadOnlyEntry(
          "infoEdges",
          "Edges",
          edges,
          false
        )
      );

      window.modalView.show("modalTable.ejs", "Graph Properties", buttons, tableContent);

    },

    showHideDefinition : function(e) {
      e.stopPropagation();
      var id = $(e.currentTarget).attr("id"), number;
      if (id.indexOf("row_newEdgeDefinitions") !== -1 ) {
        number = id.split("row_newEdgeDefinitions")[1];
        $('#row_fromCollections' + number).toggle();
        $('#row_toCollections' + number).toggle();
      }
    },

    addRemoveDefinition : function(e) {
      e.stopPropagation();
      var id = $(e.currentTarget).attr("id"), number;
      if (id.indexOf("addAfter_newEdgeDefinitions") !== -1 ) {
        this.counter++;
        $('#row_newVertexCollections').before(
          this.edgeDefintionTemplate.render({
            number: this.counter
          })
        );
        $('#newEdgeDefinitions'+this.counter).select2({
          tags: [],
          showSearchBox: false,
          minimumResultsForSearch: -1,
          width: "336px",
          maximumSelectionSize: 1
        });
        $('#newFromCollections'+this.counter).select2({
          tags: [],
          showSearchBox: false,
          minimumResultsForSearch: -1,
          width: "336px",
          maximumSelectionSize: 10
        });
        $('#newToCollections'+this.counter).select2({
          tags: [],
          showSearchBox: false,
          minimumResultsForSearch: -1,
          width: "336px",
          maximumSelectionSize: 10
        });
        window.modalView.undelegateEvents();
        window.modalView.delegateEvents(this.events);
        return;
      }
      if (id.indexOf("remove_newEdgeDefinitions") !== -1 ) {
        number = id.split("remove_newEdgeDefinitions")[1];
        $('#row_newEdgeDefinitions' + number).remove();
        $('#row_fromCollections' + number).remove();
        $('#row_toCollections' + number).remove();
      }
    },

    createNewGraphModal2: function() {
      var buttons = [],
        tableContent = [];

      this.counter = 0;
      window.modalView.disableSubmitOnEnter = true;

      tableContent.push(
        window.modalView.createTextEntry(
          "createNewGraphName",
          "Name",
          "",
          "The name to identify the graph. Has to be unique.",
          "graphName",
          true
        )
      );

      tableContent.push(
        window.modalView.createSelect2Entry(
          "newEdgeDefinitions0",
          "Edge definitions",
          "",
          "Some info for edge definitions",
          "Edge definitions",
          true,
          false,
          true,
          1
        )
      );
      tableContent.push(
        window.modalView.createSelect2Entry(
          "newFromCollections0",
          "fromCollections",
          "",
          "The collection that contain the start vertices of the relation.",
          "fromCollections",
          true,
          false,
          false,
          10
        )
      );
      tableContent.push(
        window.modalView.createSelect2Entry(
          "newToCollections0",
          "toCollections",
          "",
          "The collection that contain the end vertices of the relation.",
          "toCollections",
          true,
          false,
          false,
          10
        )
      );

      tableContent.push(
        window.modalView.createSelect2Entry(
          "newVertexCollections",
          "Vertex collections",
          "",
          "Some info for vertex collections",
          "Vertex Collections",
          false
        )
      );
      buttons.push(
        window.modalView.createSuccessButton("Create", this.createNewGraph2.bind(this))
      );

      window.modalView.show(
        "modalGraphTable.ejs", "Add new Graph", buttons, tableContent, null, this.events
      );
      $('#row_fromCollections1').hide();
      $('#row_toCollections1').hide();
    },

    createEditGraphModal2: function(name, vertices, edgeDefinitions) {
      var buttons = [],
        tableContent = [];

      this.counter = 0;

      tableContent.push(
        window.modalView.createReadOnlyEntry(
          "graphName",
          "Name",
          name,
          "The name to identify the graph. Has to be unique."
        )
      );
      edgeDefinitions.forEach(function(ed) {
        tableContent.push(
          window.modalView.createReadOnlyEntry(
            "edgeDefinitions" + this.counter,
            "Edge definitions",
            ed.collection,
            "Some info for edge definitions"
          )
        );

        tableContent.push(
          window.modalView.createSelect2Entry(
            "fromCollections" + this.counter,
            "fromCollections",
            ed.from,
            "The collection that contain the start vertices of the relation.",
            "",
            true
          )
        );
        tableContent.push(
          window.modalView.createSelect2Entry(
            "toCollections" + this.counter,
            "toCollections",
            ed.to,
            "The collection that contain the end vertices of the relation.",
            "",
            true
          )
        );
        this.counter++;
      });

      tableContent.push(
        window.modalView.createSelect2Entry(
          "vertexCollections",
          "Vertex collections",
          vertices,
          "Some info for vertex collections",
          "Vertex Collections",
          false
        )
      );

      buttons.push(
        window.modalView.createDeleteButton("Delete", this.deleteGraph.bind(this))
      );
      buttons.push(
        window.modalView.createNeutralButton("Save", this.deleteGraph.bind(this))
      );

      window.modalView.show("modalGraphTable.ejs", "Edit Graph", buttons, tableContent);

    }

  });
}());
<commit_msg>removed dead code<commit_after>/*jslint indent: 2, nomen: true, maxlen: 100, vars: true, white: true, plusplus: true*/
/*global Backbone, $, _, window, templateEngine, arangoHelper*/

(function() {
  "use strict";

  window.GraphManagementView = Backbone.View.extend({
    el: '#content',
    template: templateEngine.createTemplate("graphManagementView.ejs"),
    edgeDefintionTemplate: templateEngine.createTemplate("edgeDefinitionTable.ejs"),

    events: {
      "click #deleteGraph"                  : "deleteGraph",
      "click .icon_arangodb_settings2"      : "editGraph",
      "click .icon_arangodb_info"           : "info",
      "click #createGraph"                  : "addNewGraph",
      "keyup #graphManagementSearchInput"   : "search",
      "click #graphManagementSearchSubmit"  : "search"
    },

    addNewGraph: function(e) {
      e.preventDefault();
      this.createNewGraphModal();
    },

    deleteGraph: function(e) {
      var self = this;
      var name = $('#editGraphName').html();
      this.collection.get(name).destroy({
        success: function() {
          self.updateGraphManagementView();
          window.modalView.hide();
        },
        error: function(xhr, err) {
          var response = JSON.parse(err.responseText),
            msg = response.errorMessage;
          arangoHelper.arangoError(msg);
          window.modalView.hide();
        }
      });
    },

    render: function() {
      this.collection.fetch({
        async: false
      });

      $(this.el).html(this.template.render({
        graphs: this.collection,
        searchString : ''
      }));
      this.events["click .tableRow"] = this.showHideDefinition.bind(this);
      this.events["click .graphViewer-icon-button"] = this.addRemoveDefinition.bind(this);
      return this;
    },

    editGraph : function(e) {
      this.collection.fetch();
      this.graphToEdit = this.evaluateGraphName($(e.currentTarget).attr("id"), '_settings');
      var graph = this.collection.findWhere({_key: this.graphToEdit});
      this.createEditGraphModal(this.graphToEdit, graph.get("vertices"), graph.get("edges"));
    },

    info : function(e) {
      this.collection.fetch();
      var graph = this.collection.findWhere(
        {_key: this.evaluateGraphName($(e.currentTarget).attr("id"), '_info')}
      );
      this.createInfoGraphModal(
        graph.get('_key'),
        graph.get('vertices'),
        graph.get('edges')
      );
    },

    evaluateGraphName : function(str, substr) {
      var index = str.lastIndexOf(substr);
      return str.substring(0, index);
    },

    search: function() {
      var searchInput,
        searchString,
        strLength,
        reducedCollection;

      searchInput = $('#graphManagementSearchInput');
      searchString = $("#graphManagementSearchInput").val();
      reducedCollection = this.collection.filter(
        function(u) {
          return u.get("_key").indexOf(searchString) !== -1;
        }
      );
      $(this.el).html(this.template.render({
        graphs        : reducedCollection,
        searchString  : searchString
      }));

      //after rendering, get the "new" element
      searchInput = $('#graphManagementSearchInput');
      //set focus on end of text in input field
      strLength= searchInput.val().length;
      searchInput.focus();
      searchInput[0].setSelectionRange(strLength, strLength);
    },

    updateGraphManagementView: function() {
      var self = this;
      this.collection.fetch({
        success: function() {
          self.render();
        }
      });
    },

    createNewGraph: function() {
      var name = $("#createNewGraphName").val(),
        vertexCollections = _.pluck($('#newVertexCollections').select2("data"), "text"),
        edgeDefinitions = [],
        self = this,
        index = 0,
        collection,
        from,
        to,
        searchForNext = true;

      while(searchForNext) {
        collection = _.pluck($('#s2id_newEdgeDefinitions' + index).select2("data"), "text")[0];
        if (collection && collection !== "") {
          from = _.pluck($('#s2id_newFromCollections' + index).select2("data"), "text");
          to = _.pluck($('#s2id_newToCollections' + index).select2("data"), "text");
          if (from !== 1 && to !== 1) {
            edgeDefinitions.push(
              {
                collection: collection,
                from: from,
                to: to
              }
            );
          }
        } else {
          searchForNext = false;
        }
        index++;
      }

      if (!name) {
        arangoHelper.arangoNotification(
          "A name for the graph has to be provided."
        );
        return;
      }
      this.collection.create({
        name: name,
        edgeDefinitions: edgeDefinitions,
        orphanCollections: vertexCollections
      }, {
        success: function() {
          self.updateGraphManagementView();
          window.modalView.hide();
        },
        error: function(obj, err) {
          var response = JSON.parse(err.responseText),
            msg = response.errorMessage;
          // Gritter does not display <>
          msg = msg.replace("<", "");
          msg = msg.replace(">", "");
          arangoHelper.arangoError(msg);
        }
      });
    },

    createEditGraphModal: function(name, vertices, edges) {
      var buttons = [],
        tableContent = [];

      tableContent.push(
        window.modalView.createReadOnlyEntry(
          "editGraphName",
          "Name",
          name,
          false
        )
      );
      tableContent.push(
        window.modalView.createReadOnlyEntry(
          "editVertices",
          "Vertices",
          vertices,
          false
        )
      );
      tableContent.push(
        window.modalView.createReadOnlyEntry(
          "editEdges",
          "Edges",
          edges,
          false
        )
      );

      buttons.push(
        window.modalView.createDeleteButton("Delete", this.deleteGraph.bind(this))
      );

      window.modalView.show("modalTable.ejs", "Edit Graph", buttons, tableContent);

    },

    createInfoGraphModal: function(name, vertices, edges) {
      var buttons = [],
        tableContent = [];

      tableContent.push(
        window.modalView.createReadOnlyEntry(
          "infoGraphName",
          "Name",
          name,
          false
        )
      );
      tableContent.push(
        window.modalView.createReadOnlyEntry(
          "infoVertices",
          "Vertices",
          vertices,
          false
        )
      );
      tableContent.push(
        window.modalView.createReadOnlyEntry(
          "infoEdges",
          "Edges",
          edges,
          false
        )
      );

      window.modalView.show("modalTable.ejs", "Graph Properties", buttons, tableContent);

    },

    showHideDefinition : function(e) {
      e.stopPropagation();
      var id = $(e.currentTarget).attr("id"), number;
      if (id.indexOf("row_newEdgeDefinitions") !== -1 ) {
        number = id.split("row_newEdgeDefinitions")[1];
        $('#row_fromCollections' + number).toggle();
        $('#row_toCollections' + number).toggle();
      }
    },

    addRemoveDefinition : function(e) {
      e.stopPropagation();
      var id = $(e.currentTarget).attr("id"), number;
      if (id.indexOf("addAfter_newEdgeDefinitions") !== -1 ) {
        this.counter++;
        $('#row_newVertexCollections').before(
          this.edgeDefintionTemplate.render({
            number: this.counter
          })
        );
        $('#newEdgeDefinitions'+this.counter).select2({
          tags: [],
          showSearchBox: false,
          minimumResultsForSearch: -1,
          width: "336px",
          maximumSelectionSize: 1
        });
        $('#newFromCollections'+this.counter).select2({
          tags: [],
          showSearchBox: false,
          minimumResultsForSearch: -1,
          width: "336px",
          maximumSelectionSize: 10
        });
        $('#newToCollections'+this.counter).select2({
          tags: [],
          showSearchBox: false,
          minimumResultsForSearch: -1,
          width: "336px",
          maximumSelectionSize: 10
        });
        window.modalView.undelegateEvents();
        window.modalView.delegateEvents(this.events);
        return;
      }
      if (id.indexOf("remove_newEdgeDefinitions") !== -1 ) {
        number = id.split("remove_newEdgeDefinitions")[1];
        $('#row_newEdgeDefinitions' + number).remove();
        $('#row_fromCollections' + number).remove();
        $('#row_toCollections' + number).remove();
      }
    },

    createNewGraphModal: function() {
      var buttons = [],
        tableContent = [];

      this.counter = 0;
      window.modalView.disableSubmitOnEnter = true;

      tableContent.push(
        window.modalView.createTextEntry(
          "createNewGraphName",
          "Name",
          "",
          "The name to identify the graph. Has to be unique.",
          "graphName",
          true
        )
      );

      tableContent.push(
        window.modalView.createSelect2Entry(
          "newEdgeDefinitions0",
          "Edge definitions",
          "",
          "Some info for edge definitions",
          "Edge definitions",
          true,
          false,
          true,
          1
        )
      );
      tableContent.push(
        window.modalView.createSelect2Entry(
          "newFromCollections0",
          "fromCollections",
          "",
          "The collection that contain the start vertices of the relation.",
          "fromCollections",
          true,
          false,
          false,
          10
        )
      );
      tableContent.push(
        window.modalView.createSelect2Entry(
          "newToCollections0",
          "toCollections",
          "",
          "The collection that contain the end vertices of the relation.",
          "toCollections",
          true,
          false,
          false,
          10
        )
      );

      tableContent.push(
        window.modalView.createSelect2Entry(
          "newVertexCollections",
          "Vertex collections",
          "",
          "Some info for vertex collections",
          "Vertex Collections",
          false
        )
      );
      buttons.push(
        window.modalView.createSuccessButton("Create", this.createNewGraph.bind(this))
      );

      window.modalView.show(
        "modalGraphTable.ejs", "Add new Graph", buttons, tableContent, null, this.events
      );
      $('#row_fromCollections1').hide();
      $('#row_toCollections1').hide();
    },

    createEditGraphModal2: function(name, vertices, edgeDefinitions) {
      var buttons = [],
        tableContent = [];

      this.counter = 0;

      tableContent.push(
        window.modalView.createReadOnlyEntry(
          "graphName",
          "Name",
          name,
          "The name to identify the graph. Has to be unique."
        )
      );
      edgeDefinitions.forEach(function(ed) {
        tableContent.push(
          window.modalView.createReadOnlyEntry(
            "edgeDefinitions" + this.counter,
            "Edge definitions",
            ed.collection,
            "Some info for edge definitions"
          )
        );

        tableContent.push(
          window.modalView.createSelect2Entry(
            "fromCollections" + this.counter,
            "fromCollections",
            ed.from,
            "The collection that contain the start vertices of the relation.",
            "",
            true
          )
        );
        tableContent.push(
          window.modalView.createSelect2Entry(
            "toCollections" + this.counter,
            "toCollections",
            ed.to,
            "The collection that contain the end vertices of the relation.",
            "",
            true
          )
        );
        this.counter++;
      });

      tableContent.push(
        window.modalView.createSelect2Entry(
          "vertexCollections",
          "Vertex collections",
          vertices,
          "Some info for vertex collections",
          "Vertex Collections",
          false
        )
      );

      buttons.push(
        window.modalView.createDeleteButton("Delete", this.deleteGraph.bind(this))
      );
      buttons.push(
        window.modalView.createNeutralButton("Save", this.deleteGraph.bind(this))
      );

      window.modalView.show("modalGraphTable.ejs", "Edit Graph", buttons, tableContent);

    }

  });
}());
<|endoftext|>


<commit_before>import { routerReducer } from 'react-router-redux'

function categories (state = [], action) {
    switch (action.type) {
    case 'ADD_CATEGORIES':
        return Object.assign([], [
            ...state,
            ...action.categories
        ])
    default:
        return state
    }
}

function selectedCategory (state = 0, action) {
    switch (action.type) {
    case 'SET_ACTIVE_CATEGORY':
        return action.id
    default:
        return state
    }
}

function currentItem (state = {}, action, items) {
    switch (action.type) {
    case 'SET_ACTIVE_ITEM':
        var item = items.find(item => item.id === action.item)
        return {
            id: item.id,
            ingredients: Object.assign([], item.ingredients)
        }
    case 'TOGGLE_INGREDIENT':
        var index = state.ingredients.indexOf(action.id)
        if (index !== -1) {
            return Object.assign({}, state, {
                ingredients: [
                    ...state.ingredients.slice(0, index),
                    ...state.ingredients.slice(index + 1)
                ]
            })
        } else {
            return Object.assign({}, state, {
                ingredients: [
                    ...state.ingredients,
                    action.id
                ]
            })
        }
    case 'ADD_CURRENT_TO_CART':
        return {
            id: 0,
            ingredients: []
        }
    default:
        return state
    }
}

function cart (state = [], action, currentItem) {
    switch (action.type) {
    case 'ADD_TO_CART':
        return [
            ...state,
            {
                item: action.id,
                ingredients: action.ingredients
            }
        ]
    case 'ADD_CURRENT_TO_CART':
        return [
            ...state,
            {
                item: currentItem.id,
                ingredients: Object.assign([], currentItem.ingredients)
            }
        ]
    case 'REMOVE_ITEM':
        return [
            ...state.slice(0, action.id),
            ...state.slice(action.id + 1)
        ]
    case 'EMPTY_CART':
        return []
    default:
        return state
    }
}

function ingredients (state = [], action) {
    switch (action.type) {
    case 'SET_INGREDIENTS':
        return [...action.ingredients]
    default:
        return state
    }
}

function items (state = [], action) {
    switch (action.type) {
    case 'SET_ITEMS':
        return [...action.items]
    default:
        return state
    }
}

function rootReducer (state, action) {
    return {
        ingredients: ingredients(state.ingredients, action),
        items: items(state.items, action),
        selectedCategory: selectedCategory(state.selectedCategory, action),
        categories: categories(state.categories, action),
        currentItem: currentItem(state.currentItem, action, state.items),
        cart: cart(state.cart, action, state.currentItem),
        routing: routerReducer(state.routing, action)
    }
}
export default rootReducer
<commit_msg>Some cleanup of object assignments in reducer<commit_after>import { routerReducer } from 'react-router-redux'

function categories (state = [], action) {
    switch (action.type) {
    case 'ADD_CATEGORIES':
        return [
            ...state,
            ...action.categories
        ]
    default:
        return state
    }
}

function selectedCategory (state = 0, action) {
    switch (action.type) {
    case 'SET_ACTIVE_CATEGORY':
        return action.id
    default:
        return state
    }
}

function currentItem (state = {}, action, items) {
    switch (action.type) {
    case 'SET_ACTIVE_ITEM':
        var item = items.find(item => item.id === action.item)
        return {
            id: item.id,
            ingredients: [...item.ingredients]
        }
    case 'TOGGLE_INGREDIENT':
        var index = state.ingredients.indexOf(action.id)
        if (index !== -1) {
            return {
                ...state,
                ingredients: [
                    ...state.ingredients.slice(0, index),
                    ...state.ingredients.slice(index + 1)
                ]
            }
        } else {
            return {
                ...state,
                ingredients: [
                    ...state.ingredients,
                    action.id
                ]
            }
        }
    case 'ADD_CURRENT_TO_CART':
        return {
            id: 0,
            ingredients: []
        }
    default:
        return state
    }
}

function cart (state = [], action, currentItem) {
    switch (action.type) {
    case 'ADD_TO_CART':
        return [
            ...state,
            {
                item: action.id,
                ingredients: action.ingredients
            }
        ]
        case 'ADD_CURRENT_TO_CART':
        return [
            ...state,
            {
                item: currentItem.id,
                ingredients: [...currentItem.ingredients]
            }
        ]
    case 'REMOVE_ITEM':
        return [
            ...state.slice(0, action.id),
            ...state.slice(action.id + 1)
        ]
    case 'EMPTY_CART':
        return []
    default:
        return state
    }
}

function ingredients (state = [], action) {
    switch (action.type) {
    case 'SET_INGREDIENTS':
        return [...action.ingredients]
    default:
        return state
    }
}

function items (state = [], action) {
    switch (action.type) {
    case 'SET_ITEMS':
        return [...action.items]
    default:
        return state
    }
}

function rootReducer (state, action) {
    return {
        ingredients: ingredients(state.ingredients, action),
        items: items(state.items, action),
        selectedCategory: selectedCategory(state.selectedCategory, action),
        categories: categories(state.categories, action),
        currentItem: currentItem(state.currentItem, action, state.items),
        cart: cart(state.cart, action, state.currentItem),
        routing: routerReducer(state.routing, action)
    }
}
export default rootReducer

<|endoftext|>


<commit_before>/* Meta.js
KC3改 Meta Data

Provides access to data on built-in JSON files
*/
(function(){
	"use strict";

	window.KC3Meta = {
		_cache:{},
		_icons:{},
		_exp:{},
		_gauges:{},
		_ship:{},
		_defeq:{},
		_slotitem:{},
		_quests:{},
		_ranks:{},
		_stype:{},
		_servers:{},
		_battle:{},
		_terms:{
			troll:{},
			lang:{},
		},
		_edges:{},
		_defaultIcon:"",

		/* Initialization
		-------------------------------------------------------*/
		init :function( repo ){
			/* to remove deprecated warning
				http://stackoverflow.com/questions/22090764/alternative-to-async-false-ajax
			*/
			// Load Common Meta
			this._icons		= JSON.parse( $.ajax(repo+'icons.json', { async: false }).responseText );
			this._exp		= JSON.parse( $.ajax(repo+'experience.json', { async: false }).responseText );
			this._gauges	= JSON.parse( $.ajax(repo+'gauges.json', { async: false }).responseText );
			this._defeq		= JSON.parse( $.ajax(repo+'defeq.json', { async: false }).responseText );
			this._edges		= JSON.parse( $.ajax(repo+'edges.json', { async: false }).responseText );

			// Load Translations
			this._ship 		= KC3Translation.getJSON(repo, 'ships', true);
			this._slotitem	= KC3Translation.getJSON(repo, 'items', true);
			this._quests	= KC3Translation.getJSON(repo, 'quests', true);
			this._ranks		= KC3Translation.getJSON(repo, 'ranks', true);
			this._stype		= KC3Translation.getJSON(repo, 'stype', true);
			this._servers	= KC3Translation.getJSON(repo, 'servers', true);
			this._battle	= KC3Translation.getJSON(repo, 'battle', true);
			// troll language always loaded
			this._terms.troll		= JSON.parse( $.ajax(repo+'lang/data/troll/terms.json', { async: false }).responseText );
			// other language loaded here
			this._terms.lang		= KC3Translation.getJSON(repo, 'terms');
		},

		/* Data Access
		-------------------------------------------------------*/
		defaultIcon :function(iconSrc){
			this._defaultIcon = iconSrc;
		},

		shipIcon :function(id, empty){
			if(typeof this._icons[id] !== "undefined"){
				return "http://i708.photobucket.com/albums/ww87/dragonjet25/KC3%20Ship%20Icons/"+this._icons[id];
			}
			if(typeof empty == "undefined"){
				return this._defaultIcon;
			}
			return empty;
		},

		abyssIcon :function(id, empty){
			if(typeof this._icons[id] !== "undefined"){
				return "http://i708.photobucket.com/albums/ww87/dragonjet25/KC3%20Abyss%20Icons/"+this._icons[id];
			}
			if(typeof empty == "undefined"){
				return this._defaultIcon;
			}
			return empty;
		},

		formationIcon :function(formationId){
			return "../../../../assets/img/formation2/" + formationId + ".png";
		},

		formationText :function(formationId){
			return [
				"",
				"Line Ahead",
				"Double Line",
				"Diamond",
				"Echelon",
				"Line Abreast",
				"","","","","",
				"Cruising Formation 1 (anti-sub)",
				"Cruising Formation 2 (forward)",
				"Cruising Formation 1 (anti-sub)",
				"Cruising Formation 1 (anti-sub)",
				"","","","","","",
				"Cruising Formation 1 (anti-sub)",
				"Cruising Formation 2 (forward)",
				"Cruising Formation 1 (anti-sub)",
				"Cruising Formation 1 (anti-sub)"
			][formationId];
		},

		shipName :function( jp_name ){
			if(typeof jp_name == "undefined"){ return "Unknown ship"; }
			if(typeof this._cache[jp_name] !== "undefined"){ return this._cache[jp_name]; }
			if(typeof this._ship[jp_name] !== "undefined"){
				this._cache[jp_name] = this._ship[jp_name];
				return this._cache[jp_name];
			}
			var
				bare = jp_name,
				combin = [],
				repTab = {
					"甲"   : '_A',
					"改二" : '_KaiNi',
					"改"   : '_Kai',
				},
				repRes = null,
				replaced = false;
			// in here, the regular expression will read which one comes first (which mean, to be in the end of the name
			// and then, the bare string will be chopped by how long the pattern match...
			// the matched one, added to the combination stack (FILO)
			// removing from the replacement table in order to prevent infinite loop ^^;
			// if there's no match, it'll instantly stop and return the actual value
			while( !!(repRes = (new RegExp(".+("+(Object.keys(repTab).join("|"))+")$",'gi')).exec(bare)) ){
				bare = bare.substr(0, bare.length-repRes[1].length);
				combin.unshift(this._ship[repTab[repRes[1]]]);
				delete repTab[repRes[1]];
				replaced = true;
			}
			console.log("Remaining",bare,"with combination",combin.join(" "));
			if(replaced) {
				combin.unshift("");
				if(typeof this._ship[bare] !== "undefined"){
					this._cache[jp_name] = this._ship[bare] + (combin.length > 0 ? combin.join(" ") : "");
				}
				return this._cache[jp_name];
			}
			return jp_name;
		},

		gearName :function( jp_name ){
			if(typeof this._slotitem[ jp_name ] !== "undefined"){
				return this._slotitem[ jp_name ];
			}
			return jp_name;
		},

		exp :function(level){
			return this._exp[level] || [0,0];
		},

		quest :function(id){
			return this._quests[id] || false;
		},

		rank :function(id){
			return this._ranks[id] || "Unknown Rank";
		},

		stype :function(id){
			return this._stype[id] || "??";
		},

		server :function(ip){
			return this._servers[ip] || {name:"Unknown Server", num:0, ip:ip };
		},

		serverByNum :function(num){
			var ctr;
			for(ctr in this._servers){
				if(this._servers[ctr].num==num){
					return this._servers[ctr];
				}
			}
			return {name:"Unknown Server", num:num, ip:"0.0.0.0" };
		},

		gauge :function(map_id){
			return this._gauges["m"+map_id] || false;
		},

		defaultEquip :function(id){
			if (typeof this._defeq["s" + id] == "undefined") {
				console.log("No ship has master id " + id + " in defeq.json");
			}
			return this._defeq["s" + id] || 0;
		},

		detection :function(index){
			return this._battle.detection[index] || ["",""];
		},

		airbattle :function(index){
			return this._battle.airbattle[index] || ["",""];
		},

		engagement :function(index){
			return this._battle.engagement[index] || ["",""];
		},

		term: function(key) {
			return (ConfigManager.info_troll && this._terms.troll[key]) || this._terms.lang[key] || key;
		},

		nodeLetter : function(worldId, mapId, edgeId) {
			var map = this._edges["World " + worldId + "-" + mapId];
			if (typeof map !== "undefined") {
				var edge = map[edgeId];
				if (typeof edge !== "undefined") {
					return edge[1];	// return destination
				}
			}
			return edgeId;
		}
	};

})();
<commit_msg>[Fix #941] Ship names not showing up on JP lang<commit_after>/* Meta.js
KC3改 Meta Data

Provides access to data on built-in JSON files
*/
(function(){
	"use strict";

	window.KC3Meta = {
		_cache:{},
		_icons:{},
		_exp:{},
		_gauges:{},
		_ship:{},
		_defeq:{},
		_slotitem:{},
		_quests:{},
		_ranks:{},
		_stype:{},
		_servers:{},
		_battle:{},
		_terms:{
			troll:{},
			lang:{},
		},
		_edges:{},
		_defaultIcon:"",

		/* Initialization
		-------------------------------------------------------*/
		init :function( repo ){
			/* to remove deprecated warning
				http://stackoverflow.com/questions/22090764/alternative-to-async-false-ajax
			*/
			// Load Common Meta
			this._icons		= JSON.parse( $.ajax(repo+'icons.json', { async: false }).responseText );
			this._exp		= JSON.parse( $.ajax(repo+'experience.json', { async: false }).responseText );
			this._gauges	= JSON.parse( $.ajax(repo+'gauges.json', { async: false }).responseText );
			this._defeq		= JSON.parse( $.ajax(repo+'defeq.json', { async: false }).responseText );
			this._edges		= JSON.parse( $.ajax(repo+'edges.json', { async: false }).responseText );

			// Load Translations
			this._ship 		= KC3Translation.getJSON(repo, 'ships', true);
			this._slotitem	= KC3Translation.getJSON(repo, 'items', true);
			this._quests	= KC3Translation.getJSON(repo, 'quests', true);
			this._ranks		= KC3Translation.getJSON(repo, 'ranks', true);
			this._stype		= KC3Translation.getJSON(repo, 'stype', true);
			this._servers	= KC3Translation.getJSON(repo, 'servers', true);
			this._battle	= KC3Translation.getJSON(repo, 'battle', true);
			// troll language always loaded
			this._terms.troll		= JSON.parse( $.ajax(repo+'lang/data/troll/terms.json', { async: false }).responseText );
			// other language loaded here
			this._terms.lang		= KC3Translation.getJSON(repo, 'terms');
		},

		/* Data Access
		-------------------------------------------------------*/
		defaultIcon :function(iconSrc){
			this._defaultIcon = iconSrc;
		},

		shipIcon :function(id, empty){
			if(typeof this._icons[id] !== "undefined"){
				return "http://i708.photobucket.com/albums/ww87/dragonjet25/KC3%20Ship%20Icons/"+this._icons[id];
			}
			if(typeof empty == "undefined"){
				return this._defaultIcon;
			}
			return empty;
		},

		abyssIcon :function(id, empty){
			if(typeof this._icons[id] !== "undefined"){
				return "http://i708.photobucket.com/albums/ww87/dragonjet25/KC3%20Abyss%20Icons/"+this._icons[id];
			}
			if(typeof empty == "undefined"){
				return this._defaultIcon;
			}
			return empty;
		},

		formationIcon :function(formationId){
			return "../../../../assets/img/formation2/" + formationId + ".png";
		},

		formationText :function(formationId){
			return [
				"",
				"Line Ahead",
				"Double Line",
				"Diamond",
				"Echelon",
				"Line Abreast",
				"","","","","",
				"Cruising Formation 1 (anti-sub)",
				"Cruising Formation 2 (forward)",
				"Cruising Formation 1 (anti-sub)",
				"Cruising Formation 1 (anti-sub)",
				"","","","","","",
				"Cruising Formation 1 (anti-sub)",
				"Cruising Formation 2 (forward)",
				"Cruising Formation 1 (anti-sub)",
				"Cruising Formation 1 (anti-sub)"
			][formationId];
		},

		shipName :function( jp_name ){
			// console.log( "---------request to TL---------", jp_name );
			//if(typeof jp_name == "undefined"){ return "Unknown ship"; }
			if(typeof this._cache[jp_name] !== "undefined"){ return this._cache[jp_name]; }
			if(typeof this._ship[jp_name] !== "undefined"){
				this._cache[jp_name] = this._ship[jp_name];
				return this._cache[jp_name];
			}
			var
				bare = jp_name,
				combin = [],
				repTab = {
					"甲"   : '_A',
					"改二" : '_KaiNi',
					"改"   : '_Kai',
				},
				repRes = null,
				replaced = false;
			// in here, the regular expression will read which one comes first (which mean, to be in the end of the name
			// and then, the bare string will be chopped by how long the pattern match...
			// the matched one, added to the combination stack (FILO)
			// removing from the replacement table in order to prevent infinite loop ^^;
			// if there's no match, it'll instantly stop and return the actual value
			while( !!(repRes = (new RegExp(".+("+(Object.keys(repTab).join("|"))+")$",'gi')).exec(bare)) ){
				bare = bare.substr(0, bare.length-repRes[1].length);
				combin.unshift(this._ship[repTab[repRes[1]]]);
				delete repTab[repRes[1]];
				replaced = true;
			}
			// console.log("Remaining", bare, "with combination", combin.join(" "));
			if(replaced) {
				combin.unshift("");
				// console.log("this._ship", this._ship);
				// console.log("this._ship[bare]", this._ship[bare]);
				if(typeof this._ship[bare] !== "undefined"){
					this._cache[jp_name] = this._ship[bare] + (combin.length > 0 ? combin.join(" ") : "");
				}
				// console.log("this._cache[jp_name]", this._cache[jp_name]);
				// return this._cache[jp_name]; // being here means the jp_name is not cached. there's already a cache checker at the start of this function
			}
			// console.log("returning original:", jp_name);
			return jp_name;
		},

		gearName :function( jp_name ){
			if(typeof this._slotitem[ jp_name ] !== "undefined"){
				return this._slotitem[ jp_name ];
			}
			return jp_name;
		},

		exp :function(level){
			return this._exp[level] || [0,0];
		},

		quest :function(id){
			return this._quests[id] || false;
		},

		rank :function(id){
			return this._ranks[id] || "Unknown Rank";
		},

		stype :function(id){
			return this._stype[id] || "??";
		},

		server :function(ip){
			return this._servers[ip] || {name:"Unknown Server", num:0, ip:ip };
		},

		serverByNum :function(num){
			var ctr;
			for(ctr in this._servers){
				if(this._servers[ctr].num==num){
					return this._servers[ctr];
				}
			}
			return {name:"Unknown Server", num:num, ip:"0.0.0.0" };
		},

		gauge :function(map_id){
			return this._gauges["m"+map_id] || false;
		},

		defaultEquip :function(id){
			if (typeof this._defeq["s" + id] == "undefined") {
				console.log("No ship has master id " + id + " in defeq.json");
			}
			return this._defeq["s" + id] || 0;
		},

		detection :function(index){
			return this._battle.detection[index] || ["",""];
		},

		airbattle :function(index){
			return this._battle.airbattle[index] || ["",""];
		},

		engagement :function(index){
			return this._battle.engagement[index] || ["",""];
		},

		term: function(key) {
			return (ConfigManager.info_troll && this._terms.troll[key]) || this._terms.lang[key] || key;
		},

		nodeLetter : function(worldId, mapId, edgeId) {
			var map = this._edges["World " + worldId + "-" + mapId];
			if (typeof map !== "undefined") {
				var edge = map[edgeId];
				if (typeof edge !== "undefined") {
					return edge[1];	// return destination
				}
			}
			return edgeId;
		}
	};

})();
<|endoftext|>


<commit_before>'use strict';

module.exports = function(err, req, res, next){
	if(!err){
		return next();
	} else if(err.timeout){
		res.statusCode = 504;
		res.end('timeout of ' + err.timeout + 'ms exceeded');
	}
};<commit_msg>Added 500 error handler<commit_after>'use strict';

var constants = require('../config/constants')

module.exports = function(err, req, res, next){
	if(!err){
		return next();
	} else if(err.timeout){
		res.statusCode = 504;
		res.end('timeout of ' + err.timeout + 'ms exceeded');
	} else {
		var response = JSON.stringify({ code: 500, error: '500 Oh oh! something broke!' });
		res.setHeader('X-Powered-By', constants.APP_NAME + constants.APP_VERSION);
		res.setHeader('Content-Type', 'application/json');
		res.setHeader('Content-Length', Buffer.byteLength(response));
		res.send(500, response);
	}
};<|endoftext|>