<commit_before>
import { expect } from 'chai';

const RGTest = require('../../roguetest');
const RG = require('../../../client/src/battles');

const Goal = require('../../../client/src/goals');
const Evaluator = require('../../../client/src/evaluators');

describe('Actor Goal', () => {

    let movSys = null;
    let attSys = null;
    let dmgSys = null;
    let systems = null;

    beforeEach(() => {
        movSys = new RG.System.Movement(['Movement']);
        attSys = new RG.System.Attack(['Attack']);
        dmgSys = new RG.System.Damage(['Damage']);
        systems = [movSys, attSys, dmgSys];
    });

    it('it indicates to actor what to do', () => {

        const actor = new RG.Actor.Rogue('thinker');
        const enemy = new RG.Actor.Rogue('enemy');
        actor.setBrain(new RG.Brain.GoalOriented(actor));

        actor.addEnemy(enemy);
        enemy.addEnemy(actor);
        const startHP = enemy.get('Health').getHP();
        RGTest.wrapIntoLevel([actor, enemy]);
        RGTest.moveEntityTo(actor, 5, 5);
        RGTest.moveEntityTo(actor, 17, 17);

        let [x, y] = actor.getXY();
        let action = actor.nextAction();
        action.doAction();
        systems.forEach(sys => {sys.update();});

        const [nX, nY] = actor.getXY();

        const coordSame = x === nX && y === nY;
        expect(coordSame).not.to.equal(true);

        RGTest.moveEntityTo(actor, 2, 2);
        RGTest.moveEntityTo(enemy, 5, 5);

        RGTest.updateGame(actor, systems, 5);
        // RGTest.printScreen(actor);
        const endHP = enemy.get('Health').getHP();
        expect(endHP, 'Health must decrease').to.be.below(startHP);

        [x, y] = actor.getXY();
        expect([x, y]).to.deep.equal([4, 4]);
        actor.get('Health').setHP(5);
        for (let i = 0; i < 1; i++) {
            action = actor.nextAction();
            action.doAction();
            systems.forEach(sys => {sys.update();});
            [x, y] = actor.getXY();
            expect([x, y]).to.deep.equal([3, 3]);
        }

    });

    it('can be injected into actor via "commander"', () => {
        const commander = new RG.Actor.Rogue('commander');
        const soldier = new RG.Actor.Rogue('soldier');
        const actors = [commander, soldier];
        commander.setBrain(new RG.Brain.GoalOriented(commander));
        soldier.setBrain(new RG.Brain.GoalOriented(soldier));

        RGTest.wrapIntoLevel(actors);
        RGTest.moveEntityTo(commander, 2, 2);
        RGTest.moveEntityTo(soldier, 3, 3);

        const topGoal = soldier.getBrain().getGoal();
        topGoal.removeEvaluators();
        const ordersGoal = new Goal.Orders(soldier);
        ordersGoal.addSubGoal(new Goal.FollowPath(soldier, [10, 10]));

        const orderBias = 1.0;
        const commandEval = new Evaluator.Orders(orderBias);
        commandEval.setArgs({srcActor: commander, goal: ordersGoal});
        topGoal.giveOrders(commandEval);

        RGTest.updateGame(actors, systems, 11);

        const sXY = soldier.getXY();
        expect(sXY).to.deep.equal([10, 10]);
    });

    it('can be Commander Battle goal', () => {
        const commander = new RG.Actor.Rogue('commander');
        const inBattleComp = new RG.Component.InBattle();
        commander.add(new RG.Component.Commander());
        commander.add(inBattleComp);
        commander.setBrain(new RG.Brain.Commander(commander));
        const soldiers = [];
        for (let i = 0; i < 10; i++) {
            const soldier = new RG.Actor.Rogue('soldier' + i);
            soldier.setBrain(new RG.Brain.GoalOriented(soldier));
            soldiers.push(soldier);

            soldier.addFriend(commander);
            commander.addFriend(soldier);
        }

        const actors = [commander].concat(soldiers);
        RGTest.wrapIntoLevel(actors);
        soldiers.forEach((soldier, i) => {
            RGTest.moveEntityTo(soldier, 3, 5 + i);
        });
        RGTest.moveEntityTo(commander, 2, 10);

        RGTest.updateGame(actors, systems, 11);

        soldiers.forEach(soldier => {
            expect(soldier.getX()).to.be.above(5);
        });

    });

});
<commit_msg>Increased the commander FOV.<commit_after>
import { expect } from 'chai';

const RGTest = require('../../roguetest');
const RG = require('../../../client/src/battles');

const Goal = require('../../../client/src/goals');
const Evaluator = require('../../../client/src/evaluators');

describe('Actor Goal', () => {

    let movSys = null;
    let attSys = null;
    let dmgSys = null;
    let systems = null;

    beforeEach(() => {
        movSys = new RG.System.Movement(['Movement']);
        attSys = new RG.System.Attack(['Attack']);
        dmgSys = new RG.System.Damage(['Damage']);
        systems = [movSys, attSys, dmgSys];
    });

    it('it indicates to actor what to do', () => {

        const actor = new RG.Actor.Rogue('thinker');
        const enemy = new RG.Actor.Rogue('enemy');
        actor.setBrain(new RG.Brain.GoalOriented(actor));

        actor.addEnemy(enemy);
        enemy.addEnemy(actor);
        const startHP = enemy.get('Health').getHP();
        RGTest.wrapIntoLevel([actor, enemy]);
        RGTest.moveEntityTo(actor, 5, 5);
        RGTest.moveEntityTo(actor, 17, 17);

        let [x, y] = actor.getXY();
        let action = actor.nextAction();
        action.doAction();
        systems.forEach(sys => {sys.update();});

        const [nX, nY] = actor.getXY();

        const coordSame = x === nX && y === nY;
        expect(coordSame).not.to.equal(true);

        RGTest.moveEntityTo(actor, 2, 2);
        RGTest.moveEntityTo(enemy, 5, 5);

        RGTest.updateGame(actor, systems, 5);
        // RGTest.printScreen(actor);
        const endHP = enemy.get('Health').getHP();
        expect(endHP, 'Health must decrease').to.be.below(startHP);

        [x, y] = actor.getXY();
        expect([x, y]).to.deep.equal([4, 4]);
        actor.get('Health').setHP(5);
        for (let i = 0; i < 1; i++) {
            action = actor.nextAction();
            action.doAction();
            systems.forEach(sys => {sys.update();});
            [x, y] = actor.getXY();
            expect([x, y]).to.deep.equal([3, 3]);
        }

    });

    it('can be injected into actor via "commander"', () => {
        const commander = new RG.Actor.Rogue('commander');
        const soldier = new RG.Actor.Rogue('soldier');
        const actors = [commander, soldier];
        commander.setBrain(new RG.Brain.GoalOriented(commander));
        soldier.setBrain(new RG.Brain.GoalOriented(soldier));

        RGTest.wrapIntoLevel(actors);
        RGTest.moveEntityTo(commander, 2, 2);
        RGTest.moveEntityTo(soldier, 3, 3);

        const topGoal = soldier.getBrain().getGoal();
        topGoal.removeEvaluators();
        const ordersGoal = new Goal.Orders(soldier);
        ordersGoal.addSubGoal(new Goal.FollowPath(soldier, [10, 10]));

        const orderBias = 1.0;
        const commandEval = new Evaluator.Orders(orderBias);
        commandEval.setArgs({srcActor: commander, goal: ordersGoal});
        topGoal.giveOrders(commandEval);

        RGTest.updateGame(actors, systems, 11);

        const sXY = soldier.getXY();
        expect(sXY).to.deep.equal([10, 10]);
    });

    it('can be Commander Battle goal', () => {
        const commander = new RG.Actor.Rogue('commander');
        const inBattleComp = new RG.Component.InBattle();
        commander.add(new RG.Component.Commander());
        commander.add(inBattleComp);
        commander.setBrain(new RG.Brain.Commander(commander));
        commander.setFOVRange(10);
        const soldiers = [];
        for (let i = 0; i < 10; i++) {
            const soldier = new RG.Actor.Rogue('soldier' + i);
            soldier.setBrain(new RG.Brain.GoalOriented(soldier));
            soldiers.push(soldier);

            soldier.addFriend(commander);
            commander.addFriend(soldier);
        }

        const actors = [commander].concat(soldiers);
        const level = RGTest.wrapIntoLevel(actors);
        soldiers.forEach((soldier, i) => {
            RGTest.moveEntityTo(soldier, 3, 5 + i);
        });
        RGTest.moveEntityTo(commander, 2, 10);

        // RGTest.printLevel(level);
        RGTest.updateGame(actors, systems, 11);

        soldiers.forEach(soldier => {
            expect(soldier.getX()).to.be.above(5);
        });
        expect(level.getActors().length).to.equal(11);
        // RGTest.printLevel(level);

    });

});
<|endoftext|>


<commit_before>/**
 * Module dependencies
 */

var util = require('util');
var _ = require('@sailshq/lodash');
var LifecycleCallbackBuilder = require('./utils/system/lifecycle-callback-builder');
var TransformerBuilder = require('./utils/system/transformer-builder');
var hasSchemaCheck = require('./utils/system/has-schema-check');

/**
 * MetaModel
 *
 * Construct a new MetaModel instance (e.g. `User` or `WLModel`) with methods for
 * interacting with a set of structured database records.
 *
 * > This file contains the entry point for all ORM methods (e.g. User.find())
 * > In other words, `User` is a MetaModel INSTANCE  (sorry! I know it's weird with
 * > the capital "U"!)
 *
 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 * Usage:
 * ```
 * var WLModel = new MetaModel(orm, { adapter: require('sails-disk') });
 * // (sorry about the capital "W" in the instance!)
 * ```
 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 *
 * @param {Dictionary} orm
 *
 * @param {Dictionary} adapterWrapper
 *        @property {Dictionary} adapter
 *                  The adapter definition.
 *                  ************************************************************
 *                  FUTURE: probably just remove this second argument.  Instead of
 *                  passing it in, it seems like we should just look up the
 *                  appropriate adapter at the top of this constructor function
 *                  (or even just attach `._adapter` in userland- after instantiating
 *                  the new MetaModel instance-- e.g. "WLModel").  The only code that
 *                  directly runs `new MetaModel()` or `new SomeCustomizedMetaModel()`
 *                  is inside of Waterline core anyway.)
 *                  ************************************************************
 *
 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 * @constructs {MetaModel}
 *             The base MetaModel from whence other MetaModels are customized.
 *             Remember: running `new MetaModel()` yields an instance like `User`,
 *             which is itself generically called a WLModel.
 *
 *             > This is kind of confusing, mainly because capitalization.  And
 *             > it feels silly to nitpick about something so confusing.  But at
 *             > least this way we know what everything's called, and it's consistent.
 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 */

var MetaModel = module.exports = function MetaModel (orm, adapterWrapper) {

  // Attach a private reference to the adapter definition indicated by
  // this model's configured `datastore`.
  this._adapter = adapterWrapper.adapter;

  // Attach a private reference to the ORM.
  this._orm = orm;
  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  // > Note that we also alias it as `this.waterline`.
  this.waterline = orm;
  // ^^^
  // FUTURE: remove this alias in Waterline v1.0
  // (b/c it implies that `this.waterline` might be the stateless export from
  // the Waterline package itself, rather than what it actually is: a configured
  // ORM instance)
  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  // Initialize the `attributes` of our new MetaModel instance (e.g. `User.attributes`)
  // to an empty dictionary, unless they're already set.
  if (_.isUndefined(this.attributes)) {
    this.attributes = {};
  }
  else {
    if (!_.isObject(this.attributes)) {
      throw new Error('Consistency violation: When instantiating this new instance of MetaModel, it became clear (within the constructor) that `this.attributes` was already set, and not a dictionary: '+util.inspect(this.attributes, {depth: 5})+'');
    }
    else {
      // FUTURE: Consider not allowing this, because it's weird.
    }
  }

  // Build a dictionary of all lifecycle callbacks applicable to this model, and
  // attach it as a private property (`_callbacks`).
  this._callbacks = LifecycleCallbackBuilder(this);
  //^^FUTURE: bust this utility apart to make it stateless like the others
  //
  //^^FUTURE: Also, document what's going on here as far as timing-- i.e. answering questions
  //like "when are model settings from the original model definition applied?" and
  //"How are they set?".

  // Set the `hasSchema` flag for this model.
  // > This is based on a handful of factors, including the original model definition,
  // > ORM-wide default model settings, and (if defined) an implicit default from the
  // > adapter itself.
  this.hasSchema = hasSchemaCheck(this);
  // ^^FUTURE: change utility's name to either the imperative mood (e.g. `getSchemafulness()`)
  // or interrogative mood (`isSchemaful()`) for consistency w/ the other utilities
  // (and to avoid confusion, because the name of the flag makes it kind of crazy in this case.)

  // Build a TransformerBuilder instance and attach it as a private property (`_transformer`).
  this._transformer = new TransformerBuilder(this.schema);
  // ^^FUTURE: bust this utility apart to make it stateless like the others

  return this;
  // ^^FUTURE: remove this `return` (it shouldn't be necessary)
};

//  ██╗███╗   ██╗███████╗████████╗ █████╗ ███╗   ██╗ ██████╗███████╗
//  ██║████╗  ██║██╔════╝╚══██╔══╝██╔══██╗████╗  ██║██╔════╝██╔════╝
//  ██║██╔██╗ ██║███████╗   ██║   ███████║██╔██╗ ██║██║     █████╗
//  ██║██║╚██╗██║╚════██║   ██║   ██╔══██║██║╚██╗██║██║     ██╔══╝
//  ██║██║ ╚████║███████║   ██║   ██║  ██║██║ ╚████║╚██████╗███████╗
//  ╚═╝╚═╝  ╚═══╝╚══════╝   ╚═╝   ╚═╝  ╚═╝╚═╝  ╚═══╝ ╚═════╝╚══════╝
//
//  ███╗   ███╗███████╗████████╗██╗  ██╗ ██████╗ ██████╗ ███████╗
//  ████╗ ████║██╔════╝╚══██╔══╝██║  ██║██╔═══██╗██╔══██╗██╔════╝
//  ██╔████╔██║█████╗     ██║   ███████║██║   ██║██║  ██║███████╗
//  ██║╚██╔╝██║██╔══╝     ██║   ██╔══██║██║   ██║██║  ██║╚════██║
//  ██║ ╚═╝ ██║███████╗   ██║   ██║  ██║╚██████╔╝██████╔╝███████║
//  ╚═╝     ╚═╝╚══════╝   ╚═╝   ╚═╝  ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝
//
// INSTANCE METHODS
//
// Now extend the MetaModel constructor's `prototype` with each built-in model method.
// > This allows for the use of `Foo.find()`, etc., and it's equivalent to attaching
// > each method individually (e.g. `MetaModel.prototype.find = ()->{}`), just with
// > slightly better performance characteristics.
_.extend(
  MetaModel.prototype,
  {
    // DQL
    find: require('./methods/find'),
    findOne: require('./methods/find-one'),
    findOrCreate: require('./methods/find-or-create'),
    stream: require('./methods/stream'),
    count: require('./methods/count'),
    sum: require('./methods/sum'),
    avg: require('./methods/avg'),

    // DML
    create: require('./methods/create'),
    createEach: require('./methods/create-each'),
    update: require('./methods/update'),
    destroy: require('./methods/destroy'),
    addToCollection: require('./methods/add-to-collection'),
    removeFromCollection: require('./methods/remove-from-collection'),
    replaceCollection: require('./methods/replace-collection'),

    // Misc.
    validate: require('./methods/validate'),
  }
);

//  ███████╗████████╗ █████╗ ████████╗██╗ ██████╗
//  ██╔════╝╚══██╔══╝██╔══██╗╚══██╔══╝██║██╔════╝
//  ███████╗   ██║   ███████║   ██║   ██║██║
//  ╚════██║   ██║   ██╔══██║   ██║   ██║██║
//  ███████║   ██║   ██║  ██║   ██║   ██║╚██████╗
//  ╚══════╝   ╚═╝   ╚═╝  ╚═╝   ╚═╝   ╚═╝ ╚═════╝
//
//  ███╗   ███╗███████╗████████╗██╗  ██╗ ██████╗ ██████╗ ███████╗
//  ████╗ ████║██╔════╝╚══██╔══╝██║  ██║██╔═══██╗██╔══██╗██╔════╝
//  ██╔████╔██║█████╗     ██║   ███████║██║   ██║██║  ██║███████╗
//  ██║╚██╔╝██║██╔══╝     ██║   ██╔══██║██║   ██║██║  ██║╚════██║
//  ██║ ╚═╝ ██║███████╗   ██║   ██║  ██║╚██████╔╝██████╔╝███████║
//  ╚═╝     ╚═╝╚══════╝   ╚═╝   ╚═╝  ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝
//
// STATIC METHODS
//
// Now add properties to the MetaModel constructor itself.
// (i.e. static properties)

/**
 * MetaModel.extend()
 *
 * Build & return a new constructor based on the existing constructor in the
 * current runtime context (`this`) -- which happens to be our base model
 * constructor (MetaModel).  This also attaches the specified properties to
 * the new constructor's prototype.
 *
 *
 * > Originally taken from `.extend()` in Backbone source:
 * > http://backbonejs.org/docs/backbone.html#section-189
 * >
 * > Although this is called `extend()`, note that it does not actually modify
 * > the original MetaModel constructor.  Instead, it first builds a shallow
 * > clone of the original constructor and then extends THAT.
 *
 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 *
 * @param {Dictionary?}  protoProps
 *        Optional extra set of properties to attach to the new ctor's prototype.
 *        (& possibly a brand of breakfast cereal)
 *
 * @param {Dictionary?}  staticProps
 *        NO LONGER SUPPORTED: An optional, extra set of properties to attach
 *        directly to the new ctor.
 *
 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 * @returns {Function}  [The new constructor -- e.g. `SomeCustomizedMetaModel`]
 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 * @this {Function}  [The original constructor -- BaseMetaModel]
 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 */
MetaModel.extend = function (protoProps, staticProps) {
  var thisConstructor = this;

  // Sanity checks:

  // If a prototypal properties were provided, and one of them is under the `constructor` key,
  // then freak out.  This is no longer supported, and shouldn't still be in use anywhere.
  if (protoProps && _.has(protoProps, 'constructor')) {
    throw new Error('Consistency violation: The first argument (`protoProps`) provided to Waterline.Model.extend() should never have a `constructor` property. (This kind of usage is no longer supported.)');
  }

  // If any additional custom static properties were specified, then freak out.
  // This is no longer supported, and shouldn't still be in use anywhere.
  if (!_.isUndefined(staticProps)) {
    throw new Error('Consistency violation: Unrecognized extra argument provided to Waterline.Model.extend() (`staticProps` is no longer supported.)');
  }

  //--•
  // Now proceed with the classical, Backbone-flavor extending.

  var newConstructor;
  if (protoProps && _.has(protoProps, 'constructor')) {
    newConstructor = protoProps.constructor;
  } else {
    newConstructor = function() { return thisConstructor.apply(this, arguments); };
  }

  // Shallow-copy all of the static properties (top-level props of original constructor)
  // over to the new constructor.
  _.extend(newConstructor, thisConstructor, staticProps);

  // Create an ad hoc "Surrogate" -- a short-lived, bionic kind of a constructor
  // that serves as an intermediary... or maybe more of an organ donor?  Surrogate
  // is probably still best.  Anyway it's some dark stuff, that's for sure.  Because
  // what happens next is that we give it a reference to our original ctor's prototype
  // and constructor, then "new up" an instance for us-- but only so that we can cut out
  // that newborn instance's `prototype` and put it where the prototype for our new ctor
  // is supposed to go.
  //
  // > Why?  Well for one thing, this is important so that our new constructor appears
  // > to "inherit" from our original constructor.  But likely a more prescient motive
  // > is so that our new ctor is a proper clone.  That is, it's no longer entangled with
  // > the original constructor.
  // > (More or less anyway.  If there are any deeply nested things, like an `attributes`
  // > dictionary -- those could still contain deep, entangled references to stuff from the
  // > original ctor's prototype.
  var Surrogate = function() { this.constructor = newConstructor; };
  Surrogate.prototype = thisConstructor.prototype;
  newConstructor.prototype = new Surrogate();

  // If extra `protoProps` were provided, merge them onto our new ctor's prototype.
  // (now that it's a legitimately separate thing that we can safely modify)
  if (protoProps) {
    _.extend(newConstructor.prototype, protoProps);
  }

  // Set a proprietary `__super__` key to keep track of the original ctor's prototype.
  // (see http://stackoverflow.com/questions/8596861/super-in-backbone#comment17856929_8614228)
  newConstructor.__super__ = thisConstructor.prototype;

  // Return our new ctor.
  return newConstructor;

};

<commit_msg>Explain what's up with the terminology.<commit_after>/**
 * Module dependencies
 */

var util = require('util');
var _ = require('@sailshq/lodash');
var LifecycleCallbackBuilder = require('./utils/system/lifecycle-callback-builder');
var TransformerBuilder = require('./utils/system/transformer-builder');
var hasSchemaCheck = require('./utils/system/has-schema-check');

/**
 * MetaModel
 *
 * Construct a new MetaModel instance (e.g. `User` or `WLModel`) with methods for
 * interacting with a set of structured database records.
 *
 * > This is really just the same idea as constructing a "Model instance"-- we just
 * > use the term "MetaModel" for utmost clarity -- since at various points in the
 * > past, individual records were referred to as "model instances" rather than "records".
 * >
 * > In other words, this file contains the entry point for all ORM methods
 * > (e.g. User.find()).  So like, `User` is a MetaModel instance.  You might
 * > call it a "model" or a "model model" -- the important thing is just to
 * > understand that we're talking about the same thing in either case.
 *
 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 * Usage:
 * ```
 * var WLModel = new MetaModel(orm, { adapter: require('sails-disk') });
 * // (sorry about the capital "W" in the instance!)
 * ```
 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 *
 * @param {Dictionary} orm
 *
 * @param {Dictionary} adapterWrapper
 *        @property {Dictionary} adapter
 *                  The adapter definition.
 *                  ************************************************************
 *                  FUTURE: probably just remove this second argument.  Instead of
 *                  passing it in, it seems like we should just look up the
 *                  appropriate adapter at the top of this constructor function
 *                  (or even just attach `._adapter` in userland- after instantiating
 *                  the new MetaModel instance-- e.g. "WLModel").  The only code that
 *                  directly runs `new MetaModel()` or `new SomeCustomizedMetaModel()`
 *                  is inside of Waterline core anyway.)
 *                  ************************************************************
 *
 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 * @constructs {MetaModel}
 *             The base MetaModel from whence other MetaModels are customized.
 *             Remember: running `new MetaModel()` yields an instance like `User`,
 *             which is itself generically called a WLModel.
 *
 *             > This is kind of confusing, mainly because capitalization.  And
 *             > it feels silly to nitpick about something so confusing.  But at
 *             > least this way we know what everything's called, and it's consistent.
 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 */

var MetaModel = module.exports = function MetaModel (orm, adapterWrapper) {

  // Attach a private reference to the adapter definition indicated by
  // this model's configured `datastore`.
  this._adapter = adapterWrapper.adapter;

  // Attach a private reference to the ORM.
  this._orm = orm;
  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  // > Note that we also alias it as `this.waterline`.
  this.waterline = orm;
  // ^^^
  // FUTURE: remove this alias in Waterline v1.0
  // (b/c it implies that `this.waterline` might be the stateless export from
  // the Waterline package itself, rather than what it actually is: a configured
  // ORM instance)
  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  // Initialize the `attributes` of our new MetaModel instance (e.g. `User.attributes`)
  // to an empty dictionary, unless they're already set.
  if (_.isUndefined(this.attributes)) {
    this.attributes = {};
  }
  else {
    if (!_.isObject(this.attributes)) {
      throw new Error('Consistency violation: When instantiating this new instance of MetaModel, it became clear (within the constructor) that `this.attributes` was already set, and not a dictionary: '+util.inspect(this.attributes, {depth: 5})+'');
    }
    else {
      // FUTURE: Consider not allowing this, because it's weird.
    }
  }

  // Build a dictionary of all lifecycle callbacks applicable to this model, and
  // attach it as a private property (`_callbacks`).
  this._callbacks = LifecycleCallbackBuilder(this);
  //^^FUTURE: bust this utility apart to make it stateless like the others
  //
  //^^FUTURE: Also, document what's going on here as far as timing-- i.e. answering questions
  //like "when are model settings from the original model definition applied?" and
  //"How are they set?".

  // Set the `hasSchema` flag for this model.
  // > This is based on a handful of factors, including the original model definition,
  // > ORM-wide default model settings, and (if defined) an implicit default from the
  // > adapter itself.
  this.hasSchema = hasSchemaCheck(this);
  // ^^FUTURE: change utility's name to either the imperative mood (e.g. `getSchemafulness()`)
  // or interrogative mood (`isSchemaful()`) for consistency w/ the other utilities
  // (and to avoid confusion, because the name of the flag makes it kind of crazy in this case.)

  // Build a TransformerBuilder instance and attach it as a private property (`_transformer`).
  this._transformer = new TransformerBuilder(this.schema);
  // ^^FUTURE: bust this utility apart to make it stateless like the others

  return this;
  // ^^FUTURE: remove this `return` (it shouldn't be necessary)
};

//  ██╗███╗   ██╗███████╗████████╗ █████╗ ███╗   ██╗ ██████╗███████╗
//  ██║████╗  ██║██╔════╝╚══██╔══╝██╔══██╗████╗  ██║██╔════╝██╔════╝
//  ██║██╔██╗ ██║███████╗   ██║   ███████║██╔██╗ ██║██║     █████╗
//  ██║██║╚██╗██║╚════██║   ██║   ██╔══██║██║╚██╗██║██║     ██╔══╝
//  ██║██║ ╚████║███████║   ██║   ██║  ██║██║ ╚████║╚██████╗███████╗
//  ╚═╝╚═╝  ╚═══╝╚══════╝   ╚═╝   ╚═╝  ╚═╝╚═╝  ╚═══╝ ╚═════╝╚══════╝
//
//  ███╗   ███╗███████╗████████╗██╗  ██╗ ██████╗ ██████╗ ███████╗
//  ████╗ ████║██╔════╝╚══██╔══╝██║  ██║██╔═══██╗██╔══██╗██╔════╝
//  ██╔████╔██║█████╗     ██║   ███████║██║   ██║██║  ██║███████╗
//  ██║╚██╔╝██║██╔══╝     ██║   ██╔══██║██║   ██║██║  ██║╚════██║
//  ██║ ╚═╝ ██║███████╗   ██║   ██║  ██║╚██████╔╝██████╔╝███████║
//  ╚═╝     ╚═╝╚══════╝   ╚═╝   ╚═╝  ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝
//
// INSTANCE METHODS
//
// Now extend the MetaModel constructor's `prototype` with each built-in model method.
// > This allows for the use of `Foo.find()`, etc., and it's equivalent to attaching
// > each method individually (e.g. `MetaModel.prototype.find = ()->{}`), just with
// > slightly better performance characteristics.
_.extend(
  MetaModel.prototype,
  {
    // DQL
    find: require('./methods/find'),
    findOne: require('./methods/find-one'),
    findOrCreate: require('./methods/find-or-create'),
    stream: require('./methods/stream'),
    count: require('./methods/count'),
    sum: require('./methods/sum'),
    avg: require('./methods/avg'),

    // DML
    create: require('./methods/create'),
    createEach: require('./methods/create-each'),
    update: require('./methods/update'),
    destroy: require('./methods/destroy'),
    addToCollection: require('./methods/add-to-collection'),
    removeFromCollection: require('./methods/remove-from-collection'),
    replaceCollection: require('./methods/replace-collection'),

    // Misc.
    validate: require('./methods/validate'),
  }
);

//  ███████╗████████╗ █████╗ ████████╗██╗ ██████╗
//  ██╔════╝╚══██╔══╝██╔══██╗╚══██╔══╝██║██╔════╝
//  ███████╗   ██║   ███████║   ██║   ██║██║
//  ╚════██║   ██║   ██╔══██║   ██║   ██║██║
//  ███████║   ██║   ██║  ██║   ██║   ██║╚██████╗
//  ╚══════╝   ╚═╝   ╚═╝  ╚═╝   ╚═╝   ╚═╝ ╚═════╝
//
//  ███╗   ███╗███████╗████████╗██╗  ██╗ ██████╗ ██████╗ ███████╗
//  ████╗ ████║██╔════╝╚══██╔══╝██║  ██║██╔═══██╗██╔══██╗██╔════╝
//  ██╔████╔██║█████╗     ██║   ███████║██║   ██║██║  ██║███████╗
//  ██║╚██╔╝██║██╔══╝     ██║   ██╔══██║██║   ██║██║  ██║╚════██║
//  ██║ ╚═╝ ██║███████╗   ██║   ██║  ██║╚██████╔╝██████╔╝███████║
//  ╚═╝     ╚═╝╚══════╝   ╚═╝   ╚═╝  ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝
//
// STATIC METHODS
//
// Now add properties to the MetaModel constructor itself.
// (i.e. static properties)

/**
 * MetaModel.extend()
 *
 * Build & return a new constructor based on the existing constructor in the
 * current runtime context (`this`) -- which happens to be our base model
 * constructor (MetaModel).  This also attaches the specified properties to
 * the new constructor's prototype.
 *
 *
 * > Originally taken from `.extend()` in Backbone source:
 * > http://backbonejs.org/docs/backbone.html#section-189
 * >
 * > Although this is called `extend()`, note that it does not actually modify
 * > the original MetaModel constructor.  Instead, it first builds a shallow
 * > clone of the original constructor and then extends THAT.
 *
 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 *
 * @param {Dictionary?}  protoProps
 *        Optional extra set of properties to attach to the new ctor's prototype.
 *        (& possibly a brand of breakfast cereal)
 *
 * @param {Dictionary?}  staticProps
 *        NO LONGER SUPPORTED: An optional, extra set of properties to attach
 *        directly to the new ctor.
 *
 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 * @returns {Function}  [The new constructor -- e.g. `SomeCustomizedMetaModel`]
 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 * @this {Function}  [The original constructor -- BaseMetaModel]
 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 */
MetaModel.extend = function (protoProps, staticProps) {
  var thisConstructor = this;

  // Sanity checks:

  // If a prototypal properties were provided, and one of them is under the `constructor` key,
  // then freak out.  This is no longer supported, and shouldn't still be in use anywhere.
  if (protoProps && _.has(protoProps, 'constructor')) {
    throw new Error('Consistency violation: The first argument (`protoProps`) provided to Waterline.Model.extend() should never have a `constructor` property. (This kind of usage is no longer supported.)');
  }

  // If any additional custom static properties were specified, then freak out.
  // This is no longer supported, and shouldn't still be in use anywhere.
  if (!_.isUndefined(staticProps)) {
    throw new Error('Consistency violation: Unrecognized extra argument provided to Waterline.Model.extend() (`staticProps` is no longer supported.)');
  }

  //--•
  // Now proceed with the classical, Backbone-flavor extending.

  var newConstructor;
  if (protoProps && _.has(protoProps, 'constructor')) {
    newConstructor = protoProps.constructor;
  } else {
    newConstructor = function() { return thisConstructor.apply(this, arguments); };
  }

  // Shallow-copy all of the static properties (top-level props of original constructor)
  // over to the new constructor.
  _.extend(newConstructor, thisConstructor, staticProps);

  // Create an ad hoc "Surrogate" -- a short-lived, bionic kind of a constructor
  // that serves as an intermediary... or maybe more of an organ donor?  Surrogate
  // is probably still best.  Anyway it's some dark stuff, that's for sure.  Because
  // what happens next is that we give it a reference to our original ctor's prototype
  // and constructor, then "new up" an instance for us-- but only so that we can cut out
  // that newborn instance's `prototype` and put it where the prototype for our new ctor
  // is supposed to go.
  //
  // > Why?  Well for one thing, this is important so that our new constructor appears
  // > to "inherit" from our original constructor.  But likely a more prescient motive
  // > is so that our new ctor is a proper clone.  That is, it's no longer entangled with
  // > the original constructor.
  // > (More or less anyway.  If there are any deeply nested things, like an `attributes`
  // > dictionary -- those could still contain deep, entangled references to stuff from the
  // > original ctor's prototype.
  var Surrogate = function() { this.constructor = newConstructor; };
  Surrogate.prototype = thisConstructor.prototype;
  newConstructor.prototype = new Surrogate();

  // If extra `protoProps` were provided, merge them onto our new ctor's prototype.
  // (now that it's a legitimately separate thing that we can safely modify)
  if (protoProps) {
    _.extend(newConstructor.prototype, protoProps);
  }

  // Set a proprietary `__super__` key to keep track of the original ctor's prototype.
  // (see http://stackoverflow.com/questions/8596861/super-in-backbone#comment17856929_8614228)
  newConstructor.__super__ = thisConstructor.prototype;

  // Return our new ctor.
  return newConstructor;

};

<|endoftext|>


<commit_before>var Crypto = require('crypto');

// Map configuration object

/// API: Create MapConfig from configuration object
//
/// @param obj js MapConfiguration object
///
function MapConfig(cfg) {
  // TODO: check configuration ?
  this._cfg = cfg;
}

var o = MapConfig.prototype;

o._md5 = function(s) {
  return Crypto.createHash('md5').update(s).digest('hex');
};

/// API: Get serialized version of this MapConfig
o.serialize = function() {
  return JSON.stringify(this._cfg);
};

/// API: Get identifier for this MapConfig
o.id = function() {
  return this._md5(this.serialize());
}

/// API: Get configuration object of this MapConfig
o.obj = function() {
  return this._cfg;
}

/// API: Get type string of given layer
//
/// @param num layer index (0-based)
/// @returns a type string, as read from the layer
///
o.layerType = function(num) {
  var lyr = this.getLayer(num);
  if ( ! lyr ) return undefined;
  var typ = lyr.type;
  if ( ! typ || typ == 'cartodb' ) typ = 'mapnik';
  // TODO: check validity of other types ?
  return typ;
}

/// API: Get layer by index
//
/// @returns undefined on invalid index
///
o.getLayer = function(num) {
  return this._cfg.layers[num];
}

module.exports = MapConfig;
<commit_msg>Add link to MapConfig spec<commit_after>var Crypto = require('crypto');

// Map configuration object

/// API: Create MapConfig from configuration object
//
/// @param obj js MapConfiguration object, see
///        http://github.com/CartoDB/Windshaft/wiki/MapConfig-specification
///
function MapConfig(cfg) {
  // TODO: check configuration ?
  // TODO: inject defaults ?
  this._cfg = cfg;
}

var o = MapConfig.prototype;

o._md5 = function(s) {
  return Crypto.createHash('md5').update(s).digest('hex');
};

/// API: Get serialized version of this MapConfig
o.serialize = function() {
  return JSON.stringify(this._cfg);
};

/// API: Get identifier for this MapConfig
o.id = function() {
  return this._md5(this.serialize());
}

/// API: Get configuration object of this MapConfig
o.obj = function() {
  return this._cfg;
}

/// API: Get type string of given layer
//
/// @param num layer index (0-based)
/// @returns a type string, as read from the layer
///
o.layerType = function(num) {
  var lyr = this.getLayer(num);
  if ( ! lyr ) return undefined;
  var typ = lyr.type;
  if ( ! typ || typ == 'cartodb' ) typ = 'mapnik';
  // TODO: check validity of other types ?
  return typ;
}

/// API: Get layer by index
//
/// @returns undefined on invalid index
///
o.getLayer = function(num) {
  return this._cfg.layers[num];
}

module.exports = MapConfig;
<|endoftext|>


<commit_before>/**
  Copyright 2010-2011 Ondrej Certik <ondrej@certik.cz>
  Copyright 2010-2011 Mateusz Paprocki <mattpap@gmail.com>
  Copyright 2011 Christian Iversen <ci@sikkerhed.org>

  Permission is hereby granted, free of charge, to any person
  obtaining a copy of this software and associated documentation
  files (the "Software"), to deal in the Software without
  restriction, including without limitation the rights to use,
  copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the
  Software is furnished to do so, subject to the following
  conditions:

  The above copyright notice and this permission notice shall be
  included in all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  OTHER DEALINGS IN THE SOFTWARE.
**/

var basestring = __inherit(object, "basestring");

$PY.basestring = basestring;

basestring.PY$__init__ = function(s) {
    if (s === undefined) {
        this.obj = '';
    } else if (typeof s === "string") {
        this.obj = s;
    } else if (s.toString !== undefined) {
        this.obj = s.toString();
    } else {
        this.obj = js(s);
    }
};

var __basestring_real__ = basestring.PY$__create__;

basestring.PY$__create__ = function(cls, obj) {
    if ($PY.isinstance(obj, basestring) == true) {
        return obj;
    } else if (obj.PY$__class__ === undefined && obj.PY$__super__ !== undefined) {
        return object.PY$__repr__.apply(obj);
    } else if (obj.PY$__str__ !== undefined) {
        return obj.PY$__str__();
    } else {
        return __basestring_real__(cls, obj);
    }
};

basestring.PY$__str__ = function () {
    return this;
};

basestring.PY$__repr__ = function () {
    return this.PY$__class__("'" + this.obj + "'");
};

basestring._js_ = function () {
    return this.obj;
};

basestring.PY$__hash__ = function () {
    var value = this.obj.charCodeAt(0) << 7;
    var len = this.obj.length;

    for (var i = 1; i < len; i++) {
        value = ((1000003 * value) & 0xFFFFFFFF) ^ this.obj[i];
        value = value ^ len;
    }

    if (value == -1) {
        value = -2;
    }

    return value;
};

basestring.PY$__len__ = function() {
    return int(this.obj.length);
};

basestring.PY$__iter__ = function() {
    return iter(this.obj);
};

basestring.PY$__mod__ = function(args) {
    return basestring(sprintf(this, args));
};

basestring.PY$__eq__ = function(s) {
    if (typeof(s) === "string")
        return this.obj == s ? True : False;
    else if ($PY.isinstance(s, $PY.basestring) == true) {
        return this.obj == s.obj ? True : False;
    }
    else
        return False;
};

basestring.PY$__gt__ = function(s) {
    if (typeof(s) === "string")
        return this.obj > s ? True : False;
    else if ($PY.isinstance(s, $PY.basestring) == true)
        return this.obj > s.obj ? True : False;
    else if ($PY.isinstance(s, $PY.tuple) == true)
        return False;
    else
        return True;
};

basestring.PY$__lt__ = function(s) {
    if (typeof(s) === "string")
        return this.obj < s ? True : False;
    else if ($PY.isinstance(s, $PY.basestring) == true)
        return this.obj < s.obj ? True : False;
    else if ($PY.isinstance(s, $PY.tuple) == true)
        return True;
    else
        return False;
};

basestring.PY$__contains__ = function(item) {
    for (var index in this.obj) {
        if (item == this.obj[index]) {
            return True;
        }
    }

    return False;
};

basestring.PY$__getitem__ = function(index) {
    var seq;
    index = js(index);
    if ($PY.isinstance(index, slice) == true) {
        var s = index;
        var inds = js(s.PY$indices(py_builtins.len(this)));
        var start = inds[0];
        var stop = inds[1];
        var step = inds[2];
        if (step != 1) {
            seq = "";
            for (var i = start; i < stop; i += step) {
                seq = seq + js(this.obj.charAt(i));
            }
            return this.PY$__class__(seq);
        } else {
            return this.PY$__class__(this.obj.slice(start, stop));
        }
    } else if ((index >= 0) && (index < js(py_builtins.len(this))))
        return this.obj.charAt(index);
    else if ((index < 0) && (index >= -js(py_builtins.len(this))))
        return this.obj.charAt(index + js(py_builtins.len(this)));
    else
        throw py_builtins.IndexError("string index out of range");
};

basestring.PY$__setitem__ = function() {
    throw py_builtins.TypeError("'str' object doesn't support item assignment");
};

basestring.PY$__delitem__ = function() {
    throw py_builtins.TypeError("'str' object doesn't support item deletion");
};

basestring.PY$__mul__ = function(c) {
    if ($PY.isinstance(c, int) == true) {
        var max = js(c);
        var res = "";
        for (var i = 0; i < max; i++) {
            res += this.obj;
        }
        return basestring(res);
    } else {
        throw py_builtins.TypeError(sprintf("Cannot multiply string and <%s>", c.PY$__class__.PY$__name__));
    }
};

basestring.PY$__add__ = function(c) {
    if ($PY.isinstance(c, basestring) == true) {
        return this.PY$__class__(this.obj + c.PY$__str__()._js_());
    } else {
        throw py_builtins.TypeError(sprintf("Cannot add string and <%s>", c.PY$__class__.PY$__name__));
    }
};

basestring.PY$__iadd__ = basestring.PY$__add__;

basestring.PY$count = function(needle, start, end) {
    if (start === undefined) {
        start = 0;
    } else {
      start = js(start);
    }
    if (end === undefined)
        end = null;
    else
        end = js(end);
    var count = 0;
    var s = this.PY$__getitem__(slice(start, end));
    var idx = js(s.PY$find(needle));
    while (idx != -1) {
        count += 1;
        s = s.PY$__getitem__(slice(idx+1, null));
        idx = js(s.PY$find(needle));
    }
    return count;
};

basestring.PY$index = function(value, start, end) {
    if (start === undefined) {
        start = 0;
    }

    for (var i = js(start); (end === undefined) || (start < end); i++) {
        var _value = this.obj[i];

        if (_value === undefined) {
            break;
        }

        if (_value == value) {
            return int(i);
        }
    }

    throw py_builtins.ValueError("substring not found");
};

basestring.PY$find = function(s) {
    return int(this.obj.indexOf(js(s)));
};

basestring.PY$rfind = function(s) {
    return int(this.obj.lastIndexOf(js(s)));
};

basestring.PY$join = function(s) {
    // return this.PY$__class__(js(s).join(js(this)));
    var res = "";
    var that = this;
    iterate(s, function(elm) {
                if (res != "")
                    res += that.obj;
                res += str(elm)._js_();
            });
    return str(res);
};

basestring.PY$replace = function(old, _new, count) {
    old = js(old);
    _new = js(_new);
    var old_s;
    var new_s;

    if (count !== undefined)
        count = js(count);
    else
        count = -1;
    old_s = "";
    new_s = this.obj;
    while ((count != 0) && (new_s != old_s)) {
        old_s = new_s;
        new_s = new_s.replace(old, _new);
        count -= 1;
    }
    return this.PY$__class__(new_s);
};

basestring.PY$lstrip = function(chars) {
    if (js(py_builtins.len(this)) === 0)
        return this;
    if (chars !== undefined)
        chars = tuple(chars);
    else
        chars = tuple(["\n", "\t", " "]);
    var i = 0;
    while ((i < js(py_builtins.len(this))) && (js(chars.PY$__contains__(this.PY$__getitem__(i))))) {
        i += 1;
    }
    return this.PY$__getitem__(slice(i, null));
};

basestring.PY$rstrip = function(chars) {
    if (js(py_builtins.len(this)) === 0)
        return this;
    if (chars !== undefined)
        chars = tuple(chars);
    else
        chars = tuple(["\n", "\t", " "]);
    var i = js(py_builtins.len(this))-1;
    while ((i >= 0) && (js(chars.PY$__contains__(this.PY$__getitem__(i))))) {
        i -= 1;
    }
    return this.PY$__getitem__(slice(i+1));
};

basestring.PY$strip = function(chars) {
    return this.PY$lstrip(chars).PY$rstrip(chars);
};

basestring.PY$split = function(sep, max) {
    var r_new;
    if (sep === undefined) {
        var strings = this.obj.split(/\s+/);
        for (var x = 0; x < strings.length; x++) {
            strings[x] = str(strings[x]);
        };
        return list(strings);
    } else {
        sep = js(sep);
    }
    if (max === undefined) {
        max = 0xFFFFFFFF;
    } else {
        max = js(max);
        if (max === 0) {
            return list([this]);
        }
    }
    r_new = list();
    var i = -sep.length;
    var c = 0;
    var q = 0;
    while (c < max) {
        i = this.obj.indexOf(sep, i + sep.length);
        if (i === -1) {
            break;
        }
        r_new.PY$append(this.PY$__class__(this.obj.substring(q, i)));
        q = i + sep.length;
        c++;
    }
    r_new.PY$append(this.PY$__class__(this.obj.substring(q)));
    return r_new;
};

basestring.PY$splitlines = function() {
    return this.PY$split("\n");
};

basestring.PY$lower = function() {
    return this.PY$__class__(this.obj.toLowerCase());
};

basestring.PY$upper = function() {
    return this.PY$__class__(this.obj.toUpperCase());
};

basestring.PY$encode = function() {
    return this;
};

basestring.PY$decode = function() {
    return this;
};

basestring.PY$startswith = function(other) {
    return bool(this.obj.indexOf(js(other)) === 0);
};

basestring.PY$endswith = function(other) {
    var x = js(other);
    var i = this.obj.lastIndexOf(x);
    return (i !== -1 && i == (this.obj.length - x.length)) ? True : False;
};

var str = __inherit(basestring, "str");
var unicode = __inherit(basestring, "unicode");

$PY.str = str;
$PY.unicode = unicode;

unicode.PY$__create__ = function(cls, obj) {
    if (obj.PY$__unicode__ !== undefined) {
        return obj.PY$__unicode__();
    } else {
        return basestring.PY$__create__(cls, obj);
    }
};
<commit_msg> - Removed "== true" from comparison with $PY.isinstance  * Changed unnecessary calls to py_builtins.len() into references to obj.length<commit_after>/**
  Copyright 2010-2011 Ondrej Certik <ondrej@certik.cz>
  Copyright 2010-2011 Mateusz Paprocki <mattpap@gmail.com>
  Copyright 2011 Christian Iversen <ci@sikkerhed.org>

  Permission is hereby granted, free of charge, to any person
  obtaining a copy of this software and associated documentation
  files (the "Software"), to deal in the Software without
  restriction, including without limitation the rights to use,
  copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the
  Software is furnished to do so, subject to the following
  conditions:

  The above copyright notice and this permission notice shall be
  included in all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  OTHER DEALINGS IN THE SOFTWARE.
**/

var basestring = __inherit(object, "basestring");

$PY.basestring = basestring;

basestring.PY$__init__ = function(s) {
    if (s === undefined) {
        this.obj = '';
    } else if (typeof s === "string") {
        this.obj = s;
    } else if (s.toString !== undefined) {
        this.obj = s.toString();
    } else {
        this.obj = js(s);
    }
};

var __basestring_real__ = basestring.PY$__create__;

basestring.PY$__create__ = function(cls, obj) {
    if ($PY.isinstance(obj, basestring) == true) {
        return obj;
    } else if (obj.PY$__class__ === undefined && obj.PY$__super__ !== undefined) {
        return object.PY$__repr__.apply(obj);
    } else if (obj.PY$__str__ !== undefined) {
        return obj.PY$__str__();
    } else {
        return __basestring_real__(cls, obj);
    }
};

basestring.PY$__str__ = function () {
    return this;
};

basestring.PY$__repr__ = function () {
    return this.PY$__class__("'" + this.obj + "'");
};

basestring._js_ = function () {
    return this.obj;
};

basestring.PY$__hash__ = function () {
    var value = this.obj.charCodeAt(0) << 7;
    var len = this.obj.length;

    for (var i = 1; i < len; i++) {
        value = ((1000003 * value) & 0xFFFFFFFF) ^ this.obj[i];
        value = value ^ len;
    }

    if (value == -1) {
        value = -2;
    }

    return value;
};

basestring.PY$__len__ = function() {
    return int(this.obj.length);
};

basestring.PY$__iter__ = function() {
    return iter(this.obj);
};

basestring.PY$__mod__ = function(args) {
    return basestring(sprintf(this, args));
};

basestring.PY$__eq__ = function(s) {
    if (typeof(s) === "string")
        return this.obj == s ? True : False;
    else if ($PY.isinstance(s, $PY.basestring)) {
        return this.obj == s.obj ? True : False;
    }
    else
        return False;
};

basestring.PY$__gt__ = function(s) {
    if (typeof(s) === "string")
        return this.obj > s ? True : False;
    else if ($PY.isinstance(s, $PY.basestring))
        return this.obj > s.obj ? True : False;
    else if ($PY.isinstance(s, $PY.tuple))
        return False;
    else
        return True;
};

basestring.PY$__lt__ = function(s) {
    if (typeof(s) === "string")
        return this.obj < s ? True : False;
    else if ($PY.isinstance(s, $PY.basestring))
        return this.obj < s.obj ? True : False;
    else if ($PY.isinstance(s, $PY.tuple))
        return True;
    else
        return False;
};

basestring.PY$__contains__ = function(item) {
    for (var index in this.obj) {
        if (item == this.obj[index]) {
            return True;
        }
    }

    return False;
};

basestring.PY$__getitem__ = function(index) {
    var seq;
    index = js(index);
    if ($PY.isinstance(index, slice) == true) {
        var s = index;
        var inds = js(s.PY$indices(this.obj.length));
        var start = inds[0];
        var stop = inds[1];
        var step = inds[2];
        if (step != 1) {
            seq = "";
            for (var i = start; i < stop; i += step) {
                seq = seq + js(this.obj.charAt(i));
            }
            return this.PY$__class__(seq);
        } else {
            return this.PY$__class__(this.obj.slice(start, stop));
        }
    } else if ((index >= 0) && (index < this.obj.length))
        return this.obj.charAt(index);
    else if ((index < 0) && (index >= -this.obj.length))
        return this.obj.charAt(index + this.obj.length);
    else
        throw py_builtins.IndexError("string index out of range");
};

basestring.PY$__setitem__ = function() {
    throw py_builtins.TypeError("'str' object doesn't support item assignment");
};

basestring.PY$__delitem__ = function() {
    throw py_builtins.TypeError("'str' object doesn't support item deletion");
};

basestring.PY$__mul__ = function(c) {
    if ($PY.isinstance(c, int) == true) {
        var max = js(c);
        var res = "";
        for (var i = 0; i < max; i++) {
            res += this.obj;
        }
        return basestring(res);
    } else {
        throw py_builtins.TypeError(sprintf("Cannot multiply string and <%s>", c.PY$__class__.PY$__name__));
    }
};

basestring.PY$__add__ = function(c) {
    if ($PY.isinstance(c, basestring) == true) {
        return this.PY$__class__(this.obj + c.PY$__str__()._js_());
    } else {
        throw py_builtins.TypeError(sprintf("Cannot add string and <%s>", c.PY$__class__.PY$__name__));
    }
};

basestring.PY$__iadd__ = basestring.PY$__add__;

basestring.PY$count = function(needle, start, end) {
    if (start === undefined) {
        start = 0;
    } else {
      start = js(start);
    }
    if (end === undefined)
        end = null;
    else
        end = js(end);
    var count = 0;
    var s = this.PY$__getitem__(slice(start, end));
    var idx = js(s.PY$find(needle));
    while (idx != -1) {
        count += 1;
        s = s.PY$__getitem__(slice(idx+1, null));
        idx = js(s.PY$find(needle));
    }
    return count;
};

basestring.PY$index = function(value, start, end) {
    if (start === undefined) {
        start = 0;
    }

    for (var i = js(start); (end === undefined) || (start < end); i++) {
        var _value = this.obj[i];

        if (_value === undefined) {
            break;
        }

        if (_value == value) {
            return int(i);
        }
    }

    throw py_builtins.ValueError("substring not found");
};

basestring.PY$find = function(s) {
    return int(this.obj.indexOf(js(s)));
};

basestring.PY$rfind = function(s) {
    return int(this.obj.lastIndexOf(js(s)));
};

basestring.PY$join = function(s) {
    // return this.PY$__class__(js(s).join(js(this)));
    var res = "";
    var that = this;
    iterate(s, function(elm) {
                if (res != "")
                    res += that.obj;
                res += str(elm)._js_();
            });
    return str(res);
};

basestring.PY$replace = function(old, _new, count) {
    old = js(old);
    _new = js(_new);
    var old_s;
    var new_s;

    if (count !== undefined)
        count = js(count);
    else
        count = -1;
    old_s = "";
    new_s = this.obj;
    while ((count != 0) && (new_s != old_s)) {
        old_s = new_s;
        new_s = new_s.replace(old, _new);
        count -= 1;
    }
    return this.PY$__class__(new_s);
};

basestring.PY$lstrip = function(chars) {
    if (this.obj.length === 0)
        return this;
    if (chars !== undefined)
        chars = tuple(chars);
    else
        chars = tuple(["\n", "\t", " "]);
    var i = 0;
    while ((i < this.obj.length) && (js(chars.PY$__contains__(this.PY$__getitem__(i))))) {
        i += 1;
    }
    return this.PY$__getitem__(slice(i, null));
};

basestring.PY$rstrip = function(chars) {
    if (this.obj.length === 0)
        return this;
    if (chars !== undefined)
        chars = tuple(chars);
    else
        chars = tuple(["\n", "\t", " "]);
    var i = this.obj.length - 1;
    while ((i >= 0) && (js(chars.PY$__contains__(this.PY$__getitem__(i))))) {
        i -= 1;
    }
    return this.PY$__getitem__(slice(i+1));
};

basestring.PY$strip = function(chars) {
    return this.PY$lstrip(chars).PY$rstrip(chars);
};

basestring.PY$split = function(sep, max) {
    var r_new;
    if (sep === undefined) {
        var strings = this.obj.split(/\s+/);
        for (var x = 0; x < strings.length; x++) {
            strings[x] = str(strings[x]);
        };
        return list(strings);
    } else {
        sep = js(sep);
    }
    if (max === undefined) {
        max = 0xFFFFFFFF;
    } else {
        max = js(max);
        if (max === 0) {
            return list([this]);
        }
    }
    r_new = list();
    var i = -sep.length;
    var c = 0;
    var q = 0;
    while (c < max) {
        i = this.obj.indexOf(sep, i + sep.length);
        if (i === -1) {
            break;
        }
        r_new.PY$append(this.PY$__class__(this.obj.substring(q, i)));
        q = i + sep.length;
        c++;
    }
    r_new.PY$append(this.PY$__class__(this.obj.substring(q)));
    return r_new;
};

basestring.PY$splitlines = function() {
    return this.PY$split("\n");
};

basestring.PY$lower = function() {
    return this.PY$__class__(this.obj.toLowerCase());
};

basestring.PY$upper = function() {
    return this.PY$__class__(this.obj.toUpperCase());
};

basestring.PY$encode = function() {
    return this;
};

basestring.PY$decode = function() {
    return this;
};

basestring.PY$startswith = function(other) {
    return bool(this.obj.indexOf(js(other)) === 0);
};

basestring.PY$endswith = function(other) {
    var x = js(other);
    var i = this.obj.lastIndexOf(x);
    return (i !== -1 && i == (this.obj.length - x.length)) ? True : False;
};

var str = __inherit(basestring, "str");
var unicode = __inherit(basestring, "unicode");

$PY.str = str;
$PY.unicode = unicode;

unicode.PY$__create__ = function(cls, obj) {
    if (obj.PY$__unicode__ !== undefined) {
        return obj.PY$__unicode__();
    } else {
        return basestring.PY$__create__(cls, obj);
    }
};
<|endoftext|>


<commit_before>import React, { Component } from 'react'

import { fieldFilter, FILTER_OP_HAS_PREFIX, FILTER_OP_CONTAINS } from 'sajari'

import { default as BaseBody } from '../api-components/Body'
import Page from '../api-components/Page'
import { FilterFieldBoost } from '../api-components'
import { ALL } from '../constants/RunModes'

class InputBody extends Component {
  constructor() {
    this.state = {
      text: this.props.text
    }
    this.onChange = this.onChange.bind(this)
  }

  onChange(evt) {
    const v = evt.target.value
    if (v.length === 0 || !this.state.text.startswith(v.slice(0, 3))) {
      SearchActions.resetTracking()
    }
    this.setState({
      text: v
    })
  }

  render() {
    // Take out text to prevent it going into others
    const { text as _, minLength, prefixBoosts, containsBoosts, namespace, ...others } = this.props
    return (

        <input type="text" onChange={this.onChange} {...others} />

    )

  }
}

class Body extends Component {
  constructor(props) {
    super(props)

    this.onPageChange = this.onPageChange.bind(this)
  }

  shouldComponentUpdate(newProps) {
    // Don't update the component if the text doesn't satisfy the minimum length
    return newProps.text.length >= newProps.minLength
  }

  componentDidMount() {
    PageStore.AddChangeListener(this.onPageChange)
  }

  componentWillUnmount() {
    PageStore.RemoveChangeListener(this.onPageChange)
  }

  onPageChange() {
    this.setState({
      page: PageStore.get()
    })
  }

  render() {
    const { text, minLength, prefixBoosts, containsBoosts, namespace } = this.props

    // Stop rendering happening on initial render if the text doesn't satisfy the minimum length
    if (text < minLength) {
      return null
    }

    const prefixBoostComponents = []
    for (let field in prefixBoosts) {
      prefixBoostComponents.push(
        <FilterFieldBoost
          key={field}
          filter={fieldFilter(field, text, FILTER_OP_HAS_PREFIX)}
          value={prefixBoosts[field]}
          namespace={namespace}
        />
      )
    }

    const containsBoostComponents = []
    for (let field in containsBoosts) {
      containsBoostComponents.push(
        <FilterFieldBoost
          key={field}
          filter={fieldFilter(field, text, FILTER_OP_CONTAINS)}
          value={containsBoosts[field]}
          namespace={namespace}
        />
      )
    }

    return (

        {prefixBoostComponents}
        {containsBoostComponents}
        <Page page={this.state.page} namespace={namespace} />
        <BaseBody body={text} run={ALL} weight={1} namespace={namespace} trackingResetTrigger={trackingResetFns} />

    )
  }
}

Body.propTypes = {
  text: React.PropTypes.string.isRequired,
  minLength: React.PropTypes.number,
  prefixBoosts: React.PropTypes.object,
  containsBoosts: React.PropTypes.object,
  namespace: React.PropTypes.string,
}

Body.defaultProps = {
  text: '',
  minLength: 3,
  prefixBoosts: {},
  containsBoosts: {},
  namespace: 'default',
}

export default Body
<commit_msg>Remove unnecessary Page interactions from Body<commit_after>import React, { Component } from 'react'

import { fieldFilter, FILTER_OP_HAS_PREFIX, FILTER_OP_CONTAINS } from 'sajari'

import { default as BaseBody } from '../api-components/Body'
import { FilterFieldBoost } from '../api-components'
import { ALL } from '../constants/RunModes'

class Body extends Component {
  constructor(props) {
    super(props)
    this.state = {}
    this.onPageChange = this.onPageChange.bind(this)
  }

  shouldComponentUpdate(newProps) {
    // Don't update the component if the text doesn't satisfy the minimum length
    return newProps.text.length >= newProps.minLength
  }

  render() {
    const { text, minLength, prefixBoosts, containsBoosts, namespace } = this.props

    // Stop rendering happening on initial render if the text doesn't satisfy the minimum length
    if (text < minLength) {
      return null
    }

    const prefixBoostComponents = []
    for (let field in prefixBoosts) {
      prefixBoostComponents.push(
        <FilterFieldBoost
          key={field}
          filter={fieldFilter(field, text, FILTER_OP_HAS_PREFIX)}
          value={prefixBoosts[field]}
          namespace={namespace}
        />
      )
    }

    const containsBoostComponents = []
    for (let field in containsBoosts) {
      containsBoostComponents.push(
        <FilterFieldBoost
          key={field}
          filter={fieldFilter(field, text, FILTER_OP_CONTAINS)}
          value={containsBoosts[field]}
          namespace={namespace}
        />
      )
    }

    return (

        {prefixBoostComponents}
        {containsBoostComponents}
        <BaseBody body={text} run={ALL} weight={1} namespace={namespace} />

    )
  }
}

Body.propTypes = {
  text: React.PropTypes.string.isRequired,
  minLength: React.PropTypes.number,
  prefixBoosts: React.PropTypes.object,
  containsBoosts: React.PropTypes.object,
  namespace: React.PropTypes.string,
}

Body.defaultProps = {
  text: '',
  minLength: 3,
  prefixBoosts: {},
  containsBoosts: {},
  namespace: 'default',
}

export default Body
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import CheckList from './CheckList';
import marked from 'marked';
import { CSSTransitionGroup } from 'react-transition-group';
import { DragSource } from 'react-dnd';
import constants from './constants';

let titlePropType = (props, propName, componentName) => {
  if (props[propName]) {
    let value = props[propName];
    if (typeof value !== 'string' || value.length > 80) {
      return new Error(
        `$(propName) in $(componentName) is longer than 80 characters`
      );
    }
  }
};

const cardDragSpec = {
  beginDrag(props) {
    return {
      id: props.id,
    };
  },
};

let collectDrag = (connect, monitor) => {
  return {
    connectDragSource: connect.dragSource(),
  };
}

class Card extends Component {
  constructor() {
    super(...arguments);
    this.state = {
      showDetails: false,
    };
  }

  toggleDetails() {
    this.setState({ showDetails: !this.state.showDetails });
  }

  render() {
    const { connectDragSource } = this.props;

    let cardDetails;
    if (this.state.showDetails) {
      cardDetails = (

          <CheckList cardId={this.props.id} taskCallbacks={this.props.taskCallbacks} tasks={this.props.tasks} />

      );
    };

    let sideColor = {
      position: 'absolute',
      zIndex: -1,
      top: 0,
      bottom: 0,
      left: 0,
      width: 7,
      backgroundColor: this.props.color,
    };

    return connectDragSource(

          {this.props.title}

        <CSSTransitionGroup transitionName='toggle'
                            transitonEnterTimeout={250}
                            transitionLeaveTimeout={250} >
        {cardDetails}
        </CSSTransitionGroup>

    );
  }
}

Card.propTypes = {
  id: PropTypes.number,
  title: titlePropType,
  description: PropTypes.string,
  color: PropTypes.string,
  tasks: PropTypes.arrayOf(PropTypes.object),
  taskCallbacks: PropTypes.object,
  cardCallbacks: PropTypes.object,
  connectDragSource: PropTypes.func.isRequired,

};

export default DragSource(constants.CARD, cardDragSpec, collectDrag)(Card);
<commit_msg>sorting cards<commit_after>import React, { Component, PropTypes } from 'react';
import CheckList from './CheckList';
import marked from 'marked';
import { CSSTransitionGroup } from 'react-transition-group';
import { DragSource, DropTarget } from 'react-dnd';
import constants from './constants';

let titlePropType = (props, propName, componentName) => {
  if (props[propName]) {
    let value = props[propName];
    if (typeof value !== 'string' || value.length > 80) {
      return new Error(
        `$(propName) in $(componentName) is longer than 80 characters`
      );
    }
  }
};

const cardDropSpec = {
  hover(props, monitor) {
    const draggedId = monitor.getItem().id;
    props.cardCallbacks.updatePosition(draggedId, props.id);
  },
};

const cardDragSpec = {
  beginDrag(props) {
    return {
      id: props.id,
    };
  },
};

let collectDrop = (connect, monitor) => {
  return {
    connectDropTarget: connect.dropTarget(),
  };
};

let collectDrag = (connect, monitor) => {
  return {
    connectDragSource: connect.dragSource(),
  };
};

class Card extends Component {
  constructor() {
    super(...arguments);
    this.state = {
      showDetails: false,
    };
  }

  toggleDetails() {
    this.setState({ showDetails: !this.state.showDetails });
  }

  render() {
    const { connectDragSource, connectDropTarget } = this.props;

    let cardDetails;
    if (this.state.showDetails) {
      cardDetails = (

          <CheckList cardId={this.props.id} taskCallbacks={this.props.taskCallbacks} tasks={this.props.tasks} />

      );
    };

    let sideColor = {
      position: 'absolute',
      zIndex: -1,
      top: 0,
      bottom: 0,
      left: 0,
      width: 7,
      backgroundColor: this.props.color,
    };

    return connectDropTarget(connectDragSource(

          {this.props.title}

        <CSSTransitionGroup transitionName='toggle'
                            transitonEnterTimeout={250}
                            transitionLeaveTimeout={250} >
        {cardDetails}
        </CSSTransitionGroup>

    ));
  }
}

Card.propTypes = {
  id: PropTypes.number,
  title: titlePropType,
  description: PropTypes.string,
  color: PropTypes.string,
  tasks: PropTypes.arrayOf(PropTypes.object),
  taskCallbacks: PropTypes.object,
  cardCallbacks: PropTypes.object,
  connectDragSource: PropTypes.func.isRequired,

};

const dragHighOrderCard = DragSource(constants.CARD, cardDragSpec, collectDrag)(Card);
const dragDropHighOrderCard = DropTarget(constants.CARD, cardDropSpec, collectDrop)(dragHighOrderCard);
export default dragDropHighOrderCard;
<|endoftext|>


<commit_before>import React from 'react';
import Interactive from 'react-interactive';
import { Link } from 'react-router-dom';
import { Code } from '../styles/style';
import s from '../styles/home.style';

export default function Home() {
  const repoReadmeLink = text => (
    <Interactive
      as="a"
      {...s.link}
      href="https://github.com/rafrex/spa-github-pages#readme"
    >{text}</Interactive>
  );

  return (

        This is an example single page app built
        with React and React Router using {' '}
        browserHistory. Navigate with the links below and
        refresh the page or copy/paste the url to test out the redirect
        functionality deployed to overcome GitHub Pages incompatibility
        with single page apps (like this one).

        Please see the {repoReadmeLink('repo readme')} for instructions on how to
        use this boilerplate to deploy your own single page app using GitHub Pages.

        <Interactive
          as={Link}
          {...s.link}
          to="/example"
        >Example page</Interactive>

        <Interactive
          as={Link}
          {...s.link}
          to="/example/two-deep?field1=foo&field2=bar#boom!"
        >Example two deep with query and hash</Interactive>

  );
}
<commit_msg>Update example site text<commit_after>import React from 'react';
import Interactive from 'react-interactive';
import { Link } from 'react-router-dom';
import { Code } from '../styles/style';
import s from '../styles/home.style';

export default function Home() {
  const repoReadmeLink = text => (
    <Interactive
      as="a"
      {...s.link}
      href="https://github.com/rafrex/spa-github-pages#readme"
    >{text}</Interactive>
  );

  return (

        This is an example single page app built
        with React and React Router using {' '}
        BrowserRouter. Navigate with the links below and
        refresh the page or copy/paste the url to test out the redirect
        functionality deployed to overcome GitHub Pages incompatibility
        with single page apps (like this one).

        Please see the {repoReadmeLink('repo readme')} for instructions on how to
        use this boilerplate to deploy your own single page app using GitHub Pages.

        <Interactive
          as={Link}
          {...s.link}
          to="/example"
        >Example page</Interactive>

        <Interactive
          as={Link}
          {...s.link}
          to="/example/two-deep?field1=foo&field2=bar#boom!"
        >Example two deep with query and hash</Interactive>

  );
}
<|endoftext|>


<commit_before>var transformData = undefined;
var svg = undefined;
var pt = undefined;

var category = "Total";
var year = "1950";
var transitionTime = "1s";
var colors = {
  "Thermoelectric": "#FCBA04",
  "Public_Supply": "#BA3228",
  "Industrial": "#8A716A",
  "Irrigation": "#9BC53D",
  "Total": "#2E86AB"
};

$(document).ready(function(){
  get_data();
  svg = document.querySelector("svg");
  pt = svg.createSVGPoint();
  for (var cat in colors) {
    var catButton = $("#" + cat + '-button');
    catButton.css({'fill': colors[cat]});
  }

  var set_slider_click = function(x) {
    $("#bar-" + x).on("click", function(){
      $("#slider")[0].noUiSlider.set(x);
    });
  };

  var yr = 1950;
  while (yr <= 2015) {
    set_slider_click(yr);
    yr += 5;
  }
});

/* depends on jquery */
var animate_resize_map = function(data) {
  var color = colors[category];
  $("#category-area-legend").css(
    {
    "fill": color,
    "stroke":"none",
    "transition": "all " + transitionTime + " ease-in-out"
  });
  $.each(data, function(index, val) {
    var scale = Math.sqrt(val.scaleFactor);
    var style = {
      "fill": color,
      "transform": "scale3d(" + scale + "," + scale + ",1)",
      "stroke":"none",
      "transition": "all " + transitionTime + " ease-in-out"
    };
    var state = $("#" + val.state_name);
    if (state !== undefined) {
      if (isNaN(scale)){ // doesn't seem to work?
        style = {
          "fill":"url(#nodata)",
          "transform": "scale3d(1,1,1)",
          "stroke":"#f1f1f1",
          "transition": "all 0s"
        };
      }
      state.css(style);
    }
  });
  document.getElementById('category-area-text').firstChild.data = transformData['catVals'][category].toLocaleString() + ' mgd water withdrawal';
};

var animate_bars = function(data) {

  $.each(data, function(prop, val) {
    var myYear = prop;
    var color = colors[category];
    var scale = val[category][0]["barScale"];
    var value = val[category][0]["value"];
    var style = {
      "background": color,
      "transform": "scale3d(1," + scale + ",1)",
      "transform-origin": "100% 100%",
      "transition": "all " + transitionTime + " ease-in-out"
    };
    var bar = $("#bar-" + myYear);
    if (bar !== undefined) {
      bar.css(style);
      if (myYear !== year) {
        bar.css('opacity','0.25');
      } else {
        bar.css('opacity','1.0');
      }
      value = value.toLocaleString() + ' mgd';
      bar.attr("title", value);
    }
  });
  update_bar_tips();
};

var stateHoverDelay = 1500; // ms
var stateHoverTimer = null;
var get_state_value = (function() {
  var prevState = "";
  var prevCat = "";
  var prevYear = "";
  var prevVal = "";
  var sameHover = function(state) {
    return (prevState === state &&
            prevCat === category &&
            prevYear === year);
  }
  return function(state) {
    if (transformData !== undefined && !sameHover(state)) {
        prevState = state;
        prevCat = category;
        prevYear = year;
        if(stateHoverTimer){
          clearTimeout(stateHoverTimer);
        }
        stateHoverTimer = setTimeout(function(){
          //could send cateogory and year here too?
          ga('send', 'event', 'figure', 'Hovered on ' + state);
        }, stateHoverDelay);

        var stateData = transformData["totState"][year][category];
        prevVal = function(allData) {
          for (var i = 0; i < allData.length; i++) {
            if (allData[i]['state_name'] === state){
              return allData[i]['value'];
            }
          }
        }(stateData);
    }

    return prevVal;
  }
})();

var get_data = function() {
  $.get( "js/scaleFactors.json", function( data ) {
    transformData = data;

    var slider = document.getElementById('slider');
    slider.noUiSlider.on('update', function( values, handle ) {
  	  var year = "" + Math.round(values[handle]);
    	setYear(year);
    });

    setCategory(category);
  });
};

var animate = function() {
  var statesTransform = transformData["totState"][year][category];
  var barsTransform = transformData["totNat"];
  animate_resize_map(statesTransform);
  animate_bars(barsTransform);
};

var setCategory = function(cat) {
  category = cat;
  $('.cat-button').css("fill-opacity", '0.7');
  $('.cat-button').css("stroke-opacity","0.0");
  $('#' + cat).css("fill-opacity", "0.0");
  $('#' + cat).css("stroke-opacity","1.0");
  animate();
  ga('send', 'event', 'figure', 'Category changed to ' + category);
};

var setYrTimer = null;
var sendYrDelay = 1000; //ms
var setYear = function(yr) {
  year = yr;
  animate();
  if(setYrTimer){
    clearTimeout(setYrTimer);
  }
  setYrTimer = setTimeout(function(){
     ga('send', 'event', 'figure', 'Year changed to ' + year + ' ' + category);
  }, sendYrDelay);
 };

var update_bar_tips = function() {
  $.each($(".dataBar"), function(prop, val){
    $(val).off("mouseenter mouseleave");

    if ($(val).data("tooltipsy") !== undefined) {
      $(val).data("tooltipsy").destroy()
    }
  });
  $('.hastip').tooltipsy({
    delay: 50,
    offset: [0, -10]
  });
}

function hovertext(text, evt){
  var tooltip = document.getElementById("tooltip-text");
  var tooltip_bg = document.getElementById("tooltip-box");
  var tool_pt = document.getElementById("tooltip-point");
  if (evt === undefined){
    tooltip.firstChild.data = ' ';
    tooltip_bg.setAttribute("class","hidden");
    tooltip_bg.setAttribute("x",0);
    tool_pt.setAttribute("class","hidden");
    stateVal = " ";
  } else {
    var ref = evt.target.getAttribute('xlink:href').split('-')[0];
    var stateName = ref.replace(/#/g, '');
    var displayNum = Math.round(get_state_value(stateName));
    if (isNaN(displayNum)){
      displayNum = 'no data';
    } else {
      displayNum = displayNum.toLocaleString() + ' mgd';
    }
    text = text + ': ' + displayNum;
    pt = cursorPoint(evt);
    pt.x = Math.round(pt.x);
    pt.y = Math.round(pt.y);
    svgWidth = Number(svg.getAttribute("viewBox").split(" ")[2]);
    tooltip.setAttribute("x",pt.x);
    tooltip.setAttribute("y",pt.y);
    tooltip.firstChild.data = text;
    var length = Math.round(tooltip.getComputedTextLength());
    if (pt.x - length/2 - 6 < 0){
      tooltip.setAttribute("x",length/2+6);
    } else if (pt.x + length/2 + 6 > svgWidth) {
      tooltip.setAttribute("x", svgWidth-length/2-6);
    }
    tool_pt.setAttribute("transform","translate("+pt.x+","+pt.y+")");
    tooltip_bg.setAttribute("x",tooltip.getAttribute("x")-length/2-6);
    tooltip_bg.setAttribute("y",pt.y-35);
    tooltip.setAttribute("class","shown");
    tooltip_bg.setAttribute("class","tooltip-box");
    tool_pt.setAttribute("class","tooltip-box");
    tooltip_bg.setAttribute("width", length+12);
  }
}

function cursorPoint(evt){
  pt.x = evt.clientX; pt.y = evt.clientY;
  return pt.matrixTransform(svg.getScreenCTM().inverse());
}
function changeOpacity(id, val){
  document.getElementById(id).setAttribute("opacity", val);
}
<commit_msg>fixed hover edge state problem<commit_after>var transformData = undefined;
var svg = undefined;
var pt = undefined;

var category = "Total";
var year = "1950";
var transitionTime = "1s";
var colors = {
  "Thermoelectric": "#FCBA04",
  "Public_Supply": "#BA3228",
  "Industrial": "#8A716A",
  "Irrigation": "#9BC53D",
  "Total": "#2E86AB"
};

$(document).ready(function(){
  get_data();
  svg = document.querySelector("svg");
  pt = svg.createSVGPoint();
  for (var cat in colors) {
    var catButton = $("#" + cat + '-button');
    catButton.css({'fill': colors[cat]});
  }

  var set_slider_click = function(x) {
    $("#bar-" + x).on("click", function(){
      $("#slider")[0].noUiSlider.set(x);
    });
  };

  var yr = 1950;
  while (yr <= 2015) {
    set_slider_click(yr);
    yr += 5;
  }
});

/* depends on jquery */
var animate_resize_map = function(data) {
  var color = colors[category];
  $("#category-area-legend").css(
    {
    "fill": color,
    "stroke":"none",
    "transition": "all " + transitionTime + " ease-in-out"
  });
  $.each(data, function(index, val) {
    var scale = Math.sqrt(val.scaleFactor);
    var style = {
      "fill": color,
      "transform": "scale3d(" + scale + "," + scale + ",1)",
      "stroke":"none",
      "transition": "all " + transitionTime + " ease-in-out"
    };
    var state = $("#" + val.state_name);
    if (state !== undefined) {
      if (isNaN(scale)){ // doesn't seem to work?
        style = {
          "fill":"url(#nodata)",
          "transform": "scale3d(1,1,1)",
          "stroke":"#f1f1f1",
          "transition": "all 0s"
        };
      }
      state.css(style);
    }
  });
  document.getElementById('category-area-text').firstChild.data = transformData['catVals'][category].toLocaleString() + ' mgd water withdrawal';
};

var animate_bars = function(data) {

  $.each(data, function(prop, val) {
    var myYear = prop;
    var color = colors[category];
    var scale = val[category][0]["barScale"];
    var value = val[category][0]["value"];
    var style = {
      "background": color,
      "transform": "scale3d(1," + scale + ",1)",
      "transform-origin": "100% 100%",
      "transition": "all " + transitionTime + " ease-in-out"
    };
    var bar = $("#bar-" + myYear);
    if (bar !== undefined) {
      bar.css(style);
      if (myYear !== year) {
        bar.css('opacity','0.25');
      } else {
        bar.css('opacity','1.0');
      }
      value = value.toLocaleString() + ' mgd';
      bar.attr("title", value);
    }
  });
  update_bar_tips();
};

var stateHoverDelay = 1500; // ms
var stateHoverTimer = null;
var get_state_value = (function() {
  var prevState = "";
  var prevCat = "";
  var prevYear = "";
  var prevVal = "";
  var sameHover = function(state) {
    return (prevState === state &&
            prevCat === category &&
            prevYear === year);
  }
  return function(state) {
    if (transformData !== undefined && !sameHover(state)) {
        prevState = state;
        prevCat = category;
        prevYear = year;
        if(stateHoverTimer){
          clearTimeout(stateHoverTimer);
        }
        stateHoverTimer = setTimeout(function(){
          //could send cateogory and year here too?
          ga('send', 'event', 'figure', 'Hovered on ' + state);
        }, stateHoverDelay);

        var stateData = transformData["totState"][year][category];
        prevVal = function(allData) {
          for (var i = 0; i < allData.length; i++) {
            if (allData[i]['state_name'] === state){
              return allData[i]['value'];
            }
          }
        }(stateData);
    }

    return prevVal;
  }
})();

var get_data = function() {
  $.get( "js/scaleFactors.json", function( data ) {
    transformData = data;

    var slider = document.getElementById('slider');
    slider.noUiSlider.on('update', function( values, handle ) {
  	  var year = "" + Math.round(values[handle]);
    	setYear(year);
    });

    setCategory(category);
  });
};

var animate = function() {
  var statesTransform = transformData["totState"][year][category];
  var barsTransform = transformData["totNat"];
  animate_resize_map(statesTransform);
  animate_bars(barsTransform);
};

var setCategory = function(cat) {
  category = cat;
  $('.cat-button').css("fill-opacity", '0.7');
  $('.cat-button').css("stroke-opacity","0.0");
  $('#' + cat).css("fill-opacity", "0.0");
  $('#' + cat).css("stroke-opacity","1.0");
  animate();
  ga('send', 'event', 'figure', 'Category changed to ' + category);
};

var setYrTimer = null;
var sendYrDelay = 1000; //ms
var setYear = function(yr) {
  year = yr;
  animate();
  if(setYrTimer){
    clearTimeout(setYrTimer);
  }
  setYrTimer = setTimeout(function(){
     ga('send', 'event', 'figure', 'Year changed to ' + year + ' ' + category);
  }, sendYrDelay);
 };

var update_bar_tips = function() {
  $.each($(".dataBar"), function(prop, val){
    $(val).off("mouseenter mouseleave");

    if ($(val).data("tooltipsy") !== undefined) {
      $(val).data("tooltipsy").destroy()
    }
  });
  $('.hastip').tooltipsy({
    delay: 50,
    offset: [0, -10]
  });
}

function hovertext(text, evt){
  var tooltip = document.getElementById("tooltip-text");
  var tooltip_bg = document.getElementById("tooltip-box");
  var tool_pt = document.getElementById("tooltip-point");
  if (evt === undefined){
    tooltip.firstChild.data = ' ';
    tooltip_bg.setAttribute("class","hidden");
    tooltip_bg.setAttribute("x",0);
    tool_pt.setAttribute("class","hidden");
    stateVal = " ";
    clearTimeout(stateHoverTimer); // stop ga for edge states
  } else {
    var ref = evt.target.getAttribute('xlink:href').split('-')[0];
    var stateName = ref.replace(/#/g, '');
    var displayNum = Math.round(get_state_value(stateName));
    if (isNaN(displayNum)){
      displayNum = 'no data';
    } else {
      displayNum = displayNum.toLocaleString() + ' mgd';
    }
    text = text + ': ' + displayNum;
    pt = cursorPoint(evt);
    pt.x = Math.round(pt.x);
    pt.y = Math.round(pt.y);
    svgWidth = Number(svg.getAttribute("viewBox").split(" ")[2]);
    tooltip.setAttribute("x",pt.x);
    tooltip.setAttribute("y",pt.y);
    tooltip.firstChild.data = text;
    var length = Math.round(tooltip.getComputedTextLength());
    if (pt.x - length/2 - 6 < 0){
      tooltip.setAttribute("x",length/2+6);
    } else if (pt.x + length/2 + 6 > svgWidth) {
      tooltip.setAttribute("x", svgWidth-length/2-6);
    }
    tool_pt.setAttribute("transform","translate("+pt.x+","+pt.y+")");
    tooltip_bg.setAttribute("x",tooltip.getAttribute("x")-length/2-6);
    tooltip_bg.setAttribute("y",pt.y-35);
    tooltip.setAttribute("class","shown");
    tooltip_bg.setAttribute("class","tooltip-box");
    tool_pt.setAttribute("class","tooltip-box");
    tooltip_bg.setAttribute("width", length+12);
  }
}

function cursorPoint(evt){
  pt.x = evt.clientX; pt.y = evt.clientY;
  return pt.matrixTransform(svg.getScreenCTM().inverse());
}
function changeOpacity(id, val){
  document.getElementById(id).setAttribute("opacity", val);
}
<|endoftext|>


<commit_before>import React from 'React'

export default ({href, text}) => {text.toLowerCase()}
<commit_msg>More readable link component<commit_after>import React from 'React'

export default ({href, text}) =>
  {text.toLowerCase()}
<|endoftext|>


<commit_before>import React from 'react'
import PropTypes from 'prop-types'

import pic01 from '../images/pic01.jpg'
import pic02 from '../images/pic02.jpg'
import pic03 from '../images/pic03.jpg'

class Main extends React.Component {
  render() {

    let close =
 {this.props.onCloseArticle()}}>

    return (

        <article id="intro" className={`${this.props.article === 'intro' ? 'active' : ''} ${this.props.articleTimeout ? 'timeout' : ''}`} style={{display:'none'}}>

Intro

A passionate Software Engineer specialising in building Full-Stack Applications to meet the needs of businesses using standard industry practices. Uses great communications skills to develop strong professional relationships with clients and team members. Strong problem-solving skills are used to meet the needs of the parties involved by making sure all risks and issues with the project are outlined in order to minimise problems.

          {close}

        <article id="work" className={`${this.props.article === 'work' ? 'active' : ''} ${this.props.articleTimeout ? 'timeout' : ''}`} style={{display:'none'}}>

Work

Hello

Project desc

Front-End:

Back-End:

Database:

Hosting:

Hello

Project desc

Front-End:

Back-End:

Database:

Hosting:

Hello

Project desc

Front-End:

Back-End:

Database:

Hosting:

          {close}

        <article id="skills" className={`${this.props.article === 'skills' ? 'active' : ''} ${this.props.articleTimeout ? 'timeout' : ''}`} style={{display:'none'}}>

Skills

HTML, CSS and JavaScript

MVC/REST Frameworks

Backend development (PHP, NodeJS)

Object orientated languages (C#, Python)

Teamworking Skills

Good Communication

Personal Development and Self Evaluation

Great Time Management and Time Keeping

Database Design (UML, DFD, ERD)

Database Systems (Oracle, MySQL, PostgreSQL)

Realtime Communication (Firebase, Socket.io)

Documentation Skills

Full Stack Development

Object Orientated Programming Concepts

Full UK Driving License

          {close}

        <article id="contact" className={`${this.props.article === 'contact' ? 'active' : ''} ${this.props.articleTimeout ? 'timeout' : ''}`} style={{display:'none'}}>

Contact

          <form method="post" name="contact" data-netlify="true" data-netlify-honeypot="bot-field">

              Name
              <input type="text" name="name" id="name" />

              Email
              <input type="text" name="email" id="email" />

              Message
              <textarea name="message" id="message" rows="4"></textarea>

              {/*
<button type="submit" value="Send Message" className="special" />
 */}

<button className="special">Send</button>

<input type="reset" value="Reset" />

          </form>
          {close}

    )
  }
}

Main.propTypes = {
  route: PropTypes.object,
  article: PropTypes.string,
  articleTimeout: PropTypes.bool,
  onCloseArticle: PropTypes.func,
  timeout: PropTypes.bool,
  setWrapperRef: PropTypes.func.isRequired,
}

export default Main<commit_msg>update form<commit_after>import React from 'react'
import PropTypes from 'prop-types'

import pic01 from '../images/pic01.jpg'
import pic02 from '../images/pic02.jpg'
import pic03 from '../images/pic03.jpg'

class Main extends React.Component {
  render() {

    let close =
 {this.props.onCloseArticle()}}>

    return (

        <article id="intro" className={`${this.props.article === 'intro' ? 'active' : ''} ${this.props.articleTimeout ? 'timeout' : ''}`} style={{display:'none'}}>

Intro

A passionate Software Engineer specialising in building Full-Stack Applications to meet the needs of businesses using standard industry practices. Uses great communications skills to develop strong professional relationships with clients and team members. Strong problem-solving skills are used to meet the needs of the parties involved by making sure all risks and issues with the project are outlined in order to minimise problems.

          {close}

        <article id="work" className={`${this.props.article === 'work' ? 'active' : ''} ${this.props.articleTimeout ? 'timeout' : ''}`} style={{display:'none'}}>

Work

Hello

Project desc

Front-End:

Back-End:

Database:

Hosting:

Hello

Project desc

Front-End:

Back-End:

Database:

Hosting:

Hello

Project desc

Front-End:

Back-End:

Database:

Hosting:

          {close}

        <article id="skills" className={`${this.props.article === 'skills' ? 'active' : ''} ${this.props.articleTimeout ? 'timeout' : ''}`} style={{display:'none'}}>

Skills

HTML, CSS and JavaScript

MVC/REST Frameworks

Backend development (PHP, NodeJS)

Object orientated languages (C#, Python)

Teamworking Skills

Good Communication

Personal Development and Self Evaluation

Great Time Management and Time Keeping

Database Design (UML, DFD, ERD)

Database Systems (Oracle, MySQL, PostgreSQL)

Realtime Communication (Firebase, Socket.io)

Documentation Skills

Full Stack Development

Object Orientated Programming Concepts

Full UK Driving License

          {close}

        <article id="contact" className={`${this.props.article === 'contact' ? 'active' : ''} ${this.props.articleTimeout ? 'timeout' : ''}`} style={{display:'none'}}>

Contact

          <form method="post" name="contact" data-netlify="true" data-netlify-honeypot="bot-field">
            <input type="hidden" name="form-name" value="contact" />

              Name
              <input type="text" name="name" id="name" />

              Email
              <input type="text" name="email" id="email" />

              Message
              <textarea name="message" id="message" rows="4"></textarea>

              {/*
<button type="submit" value="Send Message" className="special" />
 */}

<button className="special">Send</button>

<input type="reset" value="Reset" />

          </form>
          {close}

    )
  }
}

Main.propTypes = {
  route: PropTypes.object,
  article: PropTypes.string,
  articleTimeout: PropTypes.bool,
  onCloseArticle: PropTypes.func,
  timeout: PropTypes.bool,
  setWrapperRef: PropTypes.func.isRequired,
}

export default Main<|endoftext|>


<commit_before>/*
 * A template for all pages, and thus a global container for the
 * application. Includes a header (with navigation bar) and footer.
 */

import React, {Component} from 'react';
import {StyleSheet, css} from 'aphrodite';

import Colors from '../data/Colors';
import {Link, MailLink} from '../Components';
import {routeData} from '../data/Routes';

export default class Page extends Component {

    render() {
        return

                    <Link to="/" className={css(styles.navTitle)}>
                        William Chargin
                    </Link>

                        {routeData
                            .filter(x => x.navbarTitle)
                            .map(({path, navbarTitle, isIndex}) =>
                                this._renderNavItem(
                                    path, navbarTitle, isIndex))}

                {this.props.children}

                    William Chargin

                    <MailLink>Get my email address</MailLink>

;
    }

    _renderNavItem(linkPath, linkText, isIndex) {
        // Test whether the current location (from our props) either
        // matches the route for the navbar entry we're rendering, or
        // is a subroute thereof.
        const currentPath = this.props.location.pathname;
        const start = currentPath.substring(0, linkPath.length);
        const end = currentPath.substring(linkPath.length);
        const here = (start === linkPath &&
            (end.length === 0 || end.charAt(0) === '/'));

        return

            <Link to={linkPath}>{isIndex ? <HomeIcon /> : linkText}</Link>

;
    }

}

/*
 * A simple home icon component. This icon is by Timothy Miller and is
 * released under CC-BY-SA [1] [2].
 *
 * [1]: https://commons.wikimedia.org/wiki/File:Home-icon.svg
 * [2]: https://www.iconfinder.com/icons/126572/home_house_icon#size=128
 */
class HomeIcon extends Component {

    static svgPath = 'M15.45,7L14,5.551V2c0-0.55-0.45-1-1-1h-1c-0.55,0-1,0.45-1,1v0.553L9,0.555C8.727,0.297,8.477,0,8,0S7.273,0.297,7,0.555  L0.55,7C0.238,7.325,0,7.562,0,8c0,0.563,0.432,1,1,1h1v6c0,0.55,0.45,1,1,1h3v-5c0-0.55,0.45-1,1-1h2c0.55,0,1,0.45,1,1v5h3  c0.55,0,1-0.45,1-1V9h1c0.568,0,1-0.437,1-1C16,7.562,15.762,7.325,15.45,7z';

    render() {
        const size = 14;
        return <svg
            width={size}
            height={size}
            viewBox="0 0 16 16"
            alt="Home"
            aria-label="Home"
        >
            <path fill="currentColor" d={HomeIcon.svgPath} />
        </svg>;
    }

}

const styles = StyleSheet.create({
    base: {
        fontFamily: "Helvetica, Arial, sans-serif",
        fontSize: 16,
        color: Colors.primary,
        lineHeight: 1.5,
    },
    header: {
        borderTop: `${Colors.accentBlue.dark} 5px solid`,
        borderBottom: `0.5px ${Colors.gray.medium} solid`,
        marginBottom: 24,
        paddingTop: 10,
        paddingBottom: 10,
    },
    centered: {
        maxWidth: 800,
        margin: 'auto',
        paddingLeft: 20,
        paddingRight: 20,
    },
    nav: {
        display: 'flex',
        justifyContent: 'space-between',
        alignItems: 'center',
        marginTop: 10,
        marginBottom: 10,
    },
    navList: {
        listStyle: 'none',
        paddingLeft: 0,
        margin: 0,
    },
    navTitle: {
        fontSize: 24,
        letterSpacing: -0.5,
        color: '#222',
    },
    navLink: {
        display: 'inline',
        marginLeft: 20,
    },
    activeNavLink: {
        fontWeight: 'bold',
    },
    footer: {
        color: Colors.gray.dark,
        borderTop: `0.5px ${Colors.gray.medium} solid`,
        marginTop: 24,
        paddingTop: 24,
        paddingBottom: 24,
    },
});
<commit_msg>Extract the navbar to its own component<commit_after>/*
 * A template for all pages, and thus a global container for the
 * application. Includes a header (with navigation bar) and footer.
 */

import React, {Component, PropTypes} from 'react';
import {StyleSheet, css} from 'aphrodite';

import Colors from '../data/Colors';
import {Link, MailLink} from '../Components';
import {routeData} from '../data/Routes';

export default class Page extends Component {

    render() {
        return

                    <Link to="/" className={css(styles.navTitle)}>
                        William Chargin
                    </Link>
                    <HorizontalNav
                        currentPath={this.props.location.pathname}
                    />

                {this.props.children}

                    William Chargin

                    <MailLink>Get my email address</MailLink>

;
    }

}

/*
 * Test whether `maybeChild` is equal to or a subroute of `parent`.
 *
 * @param {string} maybeChild
 * @param {string} parent
 * @return {boolean}
 */
function isSubroute(maybeChild, parent) {
    const start = maybeChild.substring(0, parent.length);
    const end = maybeChild.substring(parent.length);
    const startOkay = start === parent;
    const endOkay = end.length === 0 || end.charAt(0) === '/';
    return startOkay && endOkay;
}

/*
 * A navbar that shows its entries in a horizontal row.
 */
class HorizontalNav extends Component {

    static propTypes = {
        currentPath: PropTypes.string.isRequired,
    }

    render() {
        return

            {routeData
                .filter(x => x.navbarTitle)
                .map(({path, navbarTitle, isIndex}) =>
                    this._renderNavItem(
                        path, navbarTitle, isIndex))}

;
    }

    _renderNavItem(linkPath, linkText, isIndex) {
        const here = isSubroute(this.props.currentPath, linkPath);
        return

            <Link to={linkPath}>{isIndex ? <HomeIcon /> : linkText}</Link>

;
    }

}

/*
 * A simple home icon component. This icon is by Timothy Miller and is
 * released under CC-BY-SA [1] [2].
 *
 * [1]: https://commons.wikimedia.org/wiki/File:Home-icon.svg
 * [2]: https://www.iconfinder.com/icons/126572/home_house_icon#size=128
 */
class HomeIcon extends Component {

    static svgPath = 'M15.45,7L14,5.551V2c0-0.55-0.45-1-1-1h-1c-0.55,0-1,0.45-1,1v0.553L9,0.555C8.727,0.297,8.477,0,8,0S7.273,0.297,7,0.555  L0.55,7C0.238,7.325,0,7.562,0,8c0,0.563,0.432,1,1,1h1v6c0,0.55,0.45,1,1,1h3v-5c0-0.55,0.45-1,1-1h2c0.55,0,1,0.45,1,1v5h3  c0.55,0,1-0.45,1-1V9h1c0.568,0,1-0.437,1-1C16,7.562,15.762,7.325,15.45,7z';

    render() {
        const size = 14;
        return <svg
            width={size}
            height={size}
            viewBox="0 0 16 16"
            alt="Home"
            aria-label="Home"
        >
            <path fill="currentColor" d={HomeIcon.svgPath} />
        </svg>;
    }

}

const styles = StyleSheet.create({
    base: {
        fontFamily: "Helvetica, Arial, sans-serif",
        fontSize: 16,
        color: Colors.primary,
        lineHeight: 1.5,
    },
    header: {
        borderTop: `${Colors.accentBlue.dark} 5px solid`,
        borderBottom: `0.5px ${Colors.gray.medium} solid`,
        marginBottom: 24,
        paddingTop: 10,
        paddingBottom: 10,
    },
    centered: {
        maxWidth: 800,
        margin: 'auto',
        paddingLeft: 20,
        paddingRight: 20,
    },
    nav: {
        display: 'flex',
        justifyContent: 'space-between',
        alignItems: 'center',
        marginTop: 10,
        marginBottom: 10,
    },
    navList: {
        listStyle: 'none',
        paddingLeft: 0,
        margin: 0,
    },
    navTitle: {
        fontSize: 24,
        letterSpacing: -0.5,
        color: '#222',
    },
    navLink: {
        display: 'inline',
        marginLeft: 20,
    },
    activeNavLink: {
        fontWeight: 'bold',
    },
    footer: {
        color: Colors.gray.dark,
        borderTop: `0.5px ${Colors.gray.medium} solid`,
        marginTop: 24,
        paddingTop: 24,
        paddingBottom: 24,
    },
});
<|endoftext|>