<commit_before>// Load mist textures

let numTexturesLoaded = 0;
let texturesLoaded = false;

// Paths to all the mist particle textures
const texturePaths = [
  require('./textures/mist-particle-1.png'),
  require('./textures/mist-particle-2.png'),
  require('./textures/mist-particle-3.png'),
  require('./textures/mist-particle-4.png'),
  require('./textures/mist-particle-5.png'),
];

// Array of Image objects, one for each mist particle texture
const textures = texturePaths.map(() => new Image());

// Called when a mist particle texture finishes loading to be able to tell when all mist particles
// have loaded.
function textureLoadCallback() {
  numTexturesLoaded += 1;
  if (numTexturesLoaded === texturePaths.length) {
    texturesLoaded = true;
  }
}

// Assign a mist particle texture to each Image object
for (let i = 0; i < textures.length; i += 1) {
  textures[i].addEventListener('load', textureLoadCallback);
  textures[i].src = texturePaths[i];
}

// Helper functions

// My [].fill polyfill
if (!Array.prototype.fill) {
  /* eslint-disable no-extend-native */
  Array.prototype.fill = (value) => {
    for (let i = 0; i < this.length; i += 1) {
      this[i] = value;
    }
    return this;
  };
  /* eslint-enable no-extend-native */
}

/** Return a random number between `low` and `high` */
function random(low, high) {
  return (Math.random() * (high - low)) + low;
}

/** Return a random integer between `low` and `high-1` */
function randint(low, high) {
  return Math.floor(random(low, high));
}

/** Return a random item from an array */
function randchoice(array) {
  return array[randint(0, array.length)];
}

/** Implements basic particle physics (moving and bouncing) */
class Particle {
  /**
   * Create a new particle in a simulation.
   * Particles have positions and velocities, and remember which renderer they're bound to.
   * @param {ParticleRenderer} renderer - the ParticleRender that the particle belongs to.
   * @param {number} x - the initial X position of the particle
   * @param {number} y - the initial Y position of the particle
   * @param {number} vx - the initial X velocity of the particle
   * @param {number} vy - the initial Y velocity of the particle
   * @param {number} vrot - the initial rotational velocity of the particle (degrees)
   */
  constructor(renderer, x, y, vx, vy, vrot, image) {
    this.renderer = renderer;
    // Image object for mist particle texture. Not used by Particle, used by ParticleRenderer
    this.image = image;

    this.rot = 0;      // Rotation (in degrees)
    this.x = x;        // X position on canvas
    this.y = y;        // Y position on canvas
    this.vx = vx;      // X velocity
    this.vy = vy;      // Y velocity
    this.vrot = vrot;  // Rotational velocity
  }

  /** Advance the simulation by one step */
  step() {
    // Bounce particles when they hit the edges of the canvas
    const marginX = this.image.width / 2;
    const marginY = this.image.height / 2;
    if (this.x < -marginX || this.x >= this.renderer.width() + marginX) {
      this.bounceX();
    }
    if (this.y < -1 * marginY || this.y >= this.renderer.height() + marginX) {
      this.bounceY();
    }

    this.x += this.vx;
    this.y += this.vy;

    this.rot += this.vrot;
    this.rot %= 360;
  }

  /** Cause the current particle to bounce in the X direction */
  bounceX() {
    this.vx = -1 * this.vx;
  }

  /** Cause the current particle to bounce in the Y direction */
  bounceY() {
    this.vy = -1 * this.vy;
  }
}

/** Orchestrates and renders particles */
class ParticleRenderer {
  /**
   * Create a new particle renderer.
   * @param {CanvasRenderingContext2D} ctx - the rendering context of the canvas to draw on
   * @param {number} particleCount - the number of particles to maintain in the simulation
   * @param {number} fps - the number of frames per second at which the simulation should run
   */
  constructor(ctx, particleCount, fps) {
    this.ctx = ctx;
    this.particleCount = particleCount;
    this.fps = fps;

    this.particles = new Array(this.particleCount).fill(0).map(() => new Particle(
      this,
      randint(0, this.width()),   // X position
      randint(0, this.height()),  // Y position
      randint(1, 4),              // X velocity
      randint(1, 4),              // Y velocity
      random(-0.5, 0.5),          // Rotational velocity
      randchoice(textures),       // Random choice of the mist particle textures
    ));
  }

  /**
   * Draw the particles on the canvas
   */
  draw() {
    this.ctx.globalCompositeOperation = 'source-over';

    if (texturesLoaded) {
      this.ctx.clearRect(0, 0, this.width(), this.height());
      this.particles.forEach((p) => {
        const rotation = p.rot * (Math.PI / 180);

        this.ctx.translate(p.x, p.y);
        this.ctx.rotate(rotation);

        this.ctx.drawImage(p.image, -(p.image.width / 2), -(p.image.height / 2));

        this.ctx.rotate(-rotation);
        this.ctx.translate(-p.x, -p.y);
      });
    }

    // Create fade by drawing a black to transparent gradient on top

    this.ctx.globalCompositeOperation = 'destination-out';
    const gradient = this.ctx.createLinearGradient(0, 0, 0, this.height());
    gradient.addColorStop(0.0, 'rgba(255, 255, 255, 1)');
    gradient.addColorStop(0.5, 'rgba(255, 255, 255, 0.75)');
    gradient.addColorStop(1.0, 'rgba(255, 255, 255, 0)');
    this.ctx.fillStyle = gradient;
    this.ctx.fillRect(0, 0, this.width(), this.height());
  }

  /**
   * Advance the simulation by one step
   */
  step() {
    this.particles.forEach(particle => particle.step());
  }

  /**
   * Begin a render loop
   */
  start() {
    // TODO
    this.interval = setInterval(() => {
      this.step();
      requestAnimationFrame(() => { this.draw(); });
    }, 1000 / this.fps);
  }

  /**
   * Get the width of the canvas coordinate system.
   * @return {number} the width of the canvas
   */
  width() {
    return this.ctx.canvas.width;
  }

  /**
   * Get the height of the canvas coordinate system
   * @return {number} the height of the canvas
   */
  height() {
    return this.ctx.canvas.height;
  }
}

window.addEventListener('resize', () => {
  const canvas = document.getElementById('mist');

  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight * 0.8;
});

window.addEventListener('load', () => window.dispatchEvent(new Event('resize')));

window.addEventListener('load', () => {
  const canvas = document.getElementById('mist');
  const ctx = canvas.getContext('2d');
  window.mistSim = new ParticleRenderer(ctx, 85, 25);
  window.mistSim.start();
});
<commit_msg>More precise image sizes based on window width<commit_after>// Load mist textures

let numTexturesLoaded = 0;
let texturesLoaded = false;

// Paths to all the mist particle textures
const texturePaths = [
  require('./textures/mist-particle-1.png'),
  require('./textures/mist-particle-2.png'),
  require('./textures/mist-particle-3.png'),
  require('./textures/mist-particle-4.png'),
  require('./textures/mist-particle-5.png'),
];

// Array of Image objects, one for each mist particle texture
const textures = texturePaths.map(() => new Image());

// Called when a mist particle texture finishes loading to be able to tell when all mist particles
// have loaded.
function textureLoadCallback() {
  numTexturesLoaded += 1;
  if (numTexturesLoaded === texturePaths.length) {
    texturesLoaded = true;
  }
}

// Assign a mist particle texture to each Image object
for (let i = 0; i < textures.length; i += 1) {
  textures[i].addEventListener('load', textureLoadCallback);
  textures[i].src = texturePaths[i];
}

// Helper functions

// My [].fill polyfill
if (!Array.prototype.fill) {
  /* eslint-disable no-extend-native */
  Array.prototype.fill = (value) => {
    for (let i = 0; i < this.length; i += 1) {
      this[i] = value;
    }
    return this;
  };
  /* eslint-enable no-extend-native */
}

/** Return a random number between `low` and `high` */
function random(low, high) {
  return (Math.random() * (high - low)) + low;
}

/** Return a random integer between `low` and `high-1` */
function randint(low, high) {
  return Math.floor(random(low, high));
}

/** Return a random item from an array */
function randchoice(array) {
  return array[randint(0, array.length)];
}

/** Implements basic particle physics (moving and bouncing) */
class Particle {
  /**
   * Create a new particle in a simulation.
   * Particles have positions and velocities, and remember which renderer they're bound to.
   * @param {ParticleRenderer} renderer - the ParticleRender that the particle belongs to.
   * @param {number} x - the initial X position of the particle
   * @param {number} y - the initial Y position of the particle
   * @param {number} vx - the initial X velocity of the particle
   * @param {number} vy - the initial Y velocity of the particle
   * @param {number} vrot - the initial rotational velocity of the particle (degrees)
   */
  constructor(renderer, x, y, vx, vy, vrot, image) {
    this.renderer = renderer;
    // Image object for mist particle texture. Not used by Particle, used by ParticleRenderer
    this.image = image;

    this.rot = 0;      // Rotation (in degrees)
    this.x = x;        // X position on canvas
    this.y = y;        // Y position on canvas
    this.vx = vx;      // X velocity
    this.vy = vy;      // Y velocity
    this.vrot = vrot;  // Rotational velocity
  }

  /** Advance the simulation by one step */
  step() {
    // Bounce particles when they hit the edges of the canvas
    const marginX = this.image.width / 2;
    const marginY = this.image.height / 2;
    if (this.x < -marginX || this.x >= this.renderer.width() + marginX) {
      this.bounceX();
    }
    if (this.y < -1 * marginY || this.y >= this.renderer.height() + marginX) {
      this.bounceY();
    }

    this.x += this.vx;
    this.y += this.vy;

    this.rot += this.vrot;
    this.rot %= 360;
  }

  /** Cause the current particle to bounce in the X direction */
  bounceX() {
    this.vx = -1 * this.vx;
  }

  /** Cause the current particle to bounce in the Y direction */
  bounceY() {
    this.vy = -1 * this.vy;
  }
}

/** Orchestrates and renders particles */
class ParticleRenderer {
  /**
   * Create a new particle renderer.
   * @param {CanvasRenderingContext2D} ctx - the rendering context of the canvas to draw on
   * @param {number} particleCount - the number of particles to maintain in the simulation
   * @param {number} fps - the number of frames per second at which the simulation should run
   */
  constructor(ctx, particleCount, fps) {
    this.ctx = ctx;
    this.particleCount = particleCount;
    this.fps = fps;

    this.particles = new Array(this.particleCount).fill(0).map(() => new Particle(
      this,
      randint(0, this.width()),   // X position
      randint(0, this.height()),  // Y position
      randint(1, 4),              // X velocity
      randint(1, 4),              // Y velocity
      random(-0.5, 0.5),          // Rotational velocity
      randchoice(textures),       // Random choice of the mist particle textures
    ));
  }

  /**
   * Draw the particles on the canvas
   */
  draw() {
    this.ctx.globalCompositeOperation = 'source-over';

    if (texturesLoaded) {
      this.ctx.clearRect(0, 0, this.width(), this.height());
      this.particles.forEach((p) => {
        const rotation = p.rot * (Math.PI / 180);

        this.ctx.translate(p.x, p.y);
        this.ctx.rotate(rotation);

        this.ctx.drawImage(
          p.image,
          -(p.image.width / 2),
          -(p.image.height / 2),
          window.innerWidth / 3,
          window.innerWidth / 3,
        );

        this.ctx.rotate(-rotation);
        this.ctx.translate(-p.x, -p.y);
      });
    }

    // Create fade by drawing a black to transparent gradient on top

    this.ctx.globalCompositeOperation = 'destination-out';
    const gradient = this.ctx.createLinearGradient(0, 0, 0, this.height());
    gradient.addColorStop(0.0, 'rgba(255, 255, 255, 1)');
    gradient.addColorStop(0.5, 'rgba(255, 255, 255, 0.75)');
    gradient.addColorStop(1.0, 'rgba(255, 255, 255, 0)');
    this.ctx.fillStyle = gradient;
    this.ctx.fillRect(0, 0, this.width(), this.height());
  }

  /**
   * Advance the simulation by one step
   */
  step() {
    this.particles.forEach(particle => particle.step());
  }

  /**
   * Begin a render loop
   */
  start() {
    // TODO
    this.interval = setInterval(() => {
      this.step();
      requestAnimationFrame(() => { this.draw(); });
    }, 1000 / this.fps);
  }

  /**
   * Get the width of the canvas coordinate system.
   * @return {number} the width of the canvas
   */
  width() {
    return this.ctx.canvas.width;
  }

  /**
   * Get the height of the canvas coordinate system
   * @return {number} the height of the canvas
   */
  height() {
    return this.ctx.canvas.height;
  }
}

window.addEventListener('resize', () => {
  const canvas = document.getElementById('mist');

  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight * 0.8;
});

window.addEventListener('load', () => window.dispatchEvent(new Event('resize')));

window.addEventListener('load', () => {
  const canvas = document.getElementById('mist');
  const ctx = canvas.getContext('2d');
  window.mistSim = new ParticleRenderer(ctx, 85, 25);
  window.mistSim.start();
});
<|endoftext|>


<commit_before>import * as store from '../core-data/store';
import * as components from '../core-data/components';
import * as api from '../core-data/api';
import * as model from './model';
import * as references from '../utils/references';
import lib from './create';

describe('component creator', () => {
  let sandbox;

  beforeEach(() => {
    sandbox = sinon.sandbox.create();
    sandbox.stub(store);
    sandbox.stub(components);
    sandbox.stub(api);
    sandbox.stub(model);
    sandbox.stub(references, 'isDefaultComponent').returns(true);
  });

  afterEach(() => {
    sandbox.restore();
  });

  it('resolves to empty array if passed no components', () => {
    return lib([]).then((res) => expect(res).to.eql([]));
  });

  it('creates a single component with no children', () => {
    components.getSchema.returns({});
    components.getDefaultData.returns({ a: 'b' });
    components.getModel.returns(null);
    // note: the _ref will be a uid that we can't test against
    return lib([{ name: 'foo' }]).then((res) => expect(res[0].a).to.equal('b'));
  });

  it('creates a single component with data, but no children', () => {
    components.getSchema.returns({});
    // make sure we don't accidentally expand non-child-component arrays and objects in the data
    components.getDefaultData.returns({ a: 'b', nonComponentArray: [{ text: 'ok' }], nonComponentProp: { text: 'ok' } });
    components.getModel.returns(null);
    return lib([{ name: 'foo', data: { c: 'd' } }]).then((res) => {
      expect(res[0].a).to.equal('b');
      expect(res[0].c).to.equal('d');
    });
  });

  it('creates a single component with a child list', () => {
    components.getSchema.returns({});
    // no store.state.site.prefix, hence undefined
    components.getDefaultData.withArgs('foo').returns({ a: 'b', children: [{ _ref: 'undefined/components/bar' }] });
    components.getDefaultData.withArgs('bar').returns({ c: 'd' });
    components.getModel.returns(null);
    // note: the _ref will be a uid that we can't test against
    return lib([{ name: 'foo' }]).then((res) => expect(res[0].children[0].c).to.equal('d'));
  });

  it('creates a single component with a child prop', () => {
    components.getSchema.returns({});
    // no store.state.site.prefix, hence undefined
    components.getDefaultData.withArgs('foo').returns({ a: 'b', child: { _ref: 'undefined/components/bar' } });
    components.getDefaultData.withArgs('bar').returns({ c: 'd' });
    components.getModel.returns(null);
    // note: the _ref will be a uid that we can't test against
    return lib([{ name: 'foo' }]).then((res) => expect(res[0].child.c).to.equal('d'));
  });

  it('resolves default data from the server', () => {
    components.getSchema.returns({});
    api.getObject.returns(Promise.resolve({ a: 'b' }));
    components.getDefaultData.returns(null);
    components.getModel.returns(null);
    return lib([{ name: 'foo' }]).then(() => expect(api.getObject).to.have.been.called);
  });

  it('resolves default data from the server', () => {
    components.getSchema.returns(null);
    api.getSchema.returns(Promise.resolve({}));
    components.getDefaultData.returns({ a: 'b' });
    components.getModel.returns(null);
    return lib([{ name: 'foo' }]).then(() => expect(api.getSchema).to.have.been.called);
  });

  it('updates store with data passed through model.js', () => {
    components.getSchema.returns({});
    components.getDefaultData.returns({ a: 'b' });
    components.getModel.returns(true);
    model.save.returns(Promise.resolve({ c: 'd' }));
    model.render.returns(Promise.resolve({ c: 'd' }));
    return lib([{ name: 'foo' }]).then(() => {
      expect(model.save).to.have.been.called;
      expect(model.render).to.have.been.called;
    });
  });
});
<commit_msg>fixed stub in tests<commit_after>import * as store from '../core-data/store';
import * as components from '../core-data/components';
import * as api from '../core-data/api';
import * as model from './model';
import * as references from '../utils/references';
import lib from './create';

describe('component creator', () => {
  let sandbox;

  beforeEach(() => {
    sandbox = sinon.sandbox.create();
    sandbox.stub(store);
    sandbox.stub(components);
    sandbox.stub(api);
    sandbox.stub(model);
    sandbox.stub(references, 'isDefaultComponent').returns(true);
    api.getText.returns(Promise.reject());
  });

  afterEach(() => {
    sandbox.restore();
  });

  it('resolves to empty array if passed no components', () => {
    return lib([]).then((res) => expect(res).to.eql([]));
  });

  it('creates a single component with no children', () => {
    components.getSchema.returns({});
    components.getDefaultData.returns({ a: 'b' });
    components.getModel.returns(null);
    // note: the _ref will be a uid that we can't test against
    return lib([{ name: 'foo' }]).then((res) => expect(res[0].a).to.equal('b'));
  });

  it('creates a single component with data, but no children', () => {
    components.getSchema.returns({});
    // make sure we don't accidentally expand non-child-component arrays and objects in the data
    components.getDefaultData.returns({ a: 'b', nonComponentArray: [{ text: 'ok' }], nonComponentProp: { text: 'ok' } });
    components.getModel.returns(null);
    return lib([{ name: 'foo', data: { c: 'd' } }]).then((res) => {
      expect(res[0].a).to.equal('b');
      expect(res[0].c).to.equal('d');
    });
  });

  it('creates a single component with a child list', () => {
    components.getSchema.returns({});
    // no store.state.site.prefix, hence undefined
    components.getDefaultData.withArgs('foo').returns({ a: 'b', children: [{ _ref: 'undefined/components/bar' }] });
    components.getDefaultData.withArgs('bar').returns({ c: 'd' });
    components.getModel.returns(null);
    // note: the _ref will be a uid that we can't test against
    return lib([{ name: 'foo' }]).then((res) => expect(res[0].children[0].c).to.equal('d'));
  });

  it('creates a single component with a child prop', () => {
    components.getSchema.returns({});
    // no store.state.site.prefix, hence undefined
    components.getDefaultData.withArgs('foo').returns({ a: 'b', child: { _ref: 'undefined/components/bar' } });
    components.getDefaultData.withArgs('bar').returns({ c: 'd' });
    components.getModel.returns(null);
    // note: the _ref will be a uid that we can't test against
    return lib([{ name: 'foo' }]).then((res) => expect(res[0].child.c).to.equal('d'));
  });

  it('resolves default data from the server', () => {
    components.getSchema.returns({});
    api.getObject.returns(Promise.resolve({ a: 'b' }));
    components.getDefaultData.returns(null);
    components.getModel.returns(null);
    return lib([{ name: 'foo' }]).then(() => expect(api.getObject).to.have.been.called);
  });

  it('resolves default data from the server', () => {
    components.getSchema.returns(null);
    api.getSchema.returns(Promise.resolve({}));
    components.getDefaultData.returns({ a: 'b' });
    components.getModel.returns(null);
    return lib([{ name: 'foo' }]).then(() => expect(api.getSchema).to.have.been.called);
  });

  it('updates store with data passed through model.js', () => {
    components.getSchema.returns({});
    components.getDefaultData.returns({ a: 'b' });
    components.getModel.returns(true);
    model.save.returns(Promise.resolve({ c: 'd' }));
    model.render.returns(Promise.resolve({ c: 'd' }));
    return lib([{ name: 'foo' }]).then(() => {
      expect(model.save).to.have.been.called;
      expect(model.render).to.have.been.called;
    });
  });
});
<|endoftext|>


<commit_before>({define: typeof define != "undefined" ? define : function (deps, factory) {
    module.exports = factory(exports, require("../..").Query);
}}).define(["exports", "Query"], function (exports, Query) {

        var comparatorMap = {
            "eql": "=",
            "gt": ">",
            "lt": "<",
            "lte": "<=",
            "gte": ">="
        }, undefined;

        var QueryComposer = {

            compose: function (query) {

                var hash = query.toObject(),
                    ret = {};

                if (hash.sort) {
                    ret.sort = this.translateSort(hash.sort);
                }

                if (hash.where) {
                    ret.where = this.translateOperator(hash.where)
                }

                return ret;
            },

            translateSort: function (sort) {
                return sort.join(",");
            },

            translateOperator: function (operator, depth) {
                depth = depth === undefined ? 0 : depth;
                var name = operator.operator;
                if (name === "and" || name === "or") {
                    var expressions = this.translateExpressions(operator.expressions, depth + 1).join(" " + name + " ");
                    if (expressions.length > 1 && depth !== 0) {
                        return "(" + expressions + ")";
                    }
                    return expressions;
                } else if(operator.field){
                    var value = operator.getValue();
                    var type = typeof(value);
                    if (type === "string") {
                        if (/^(\d+|false|true|null)$/.test(value)
                            || this.value === "false" || this.value === "true") {
                            value = type + ":" + value;
                        }
                    }
                    if (comparatorMap.hasOwnProperty(name)) {
                        return operator.field + comparatorMap[name] + value;
                    } else if (operator.field && value !== undefined) {
                        if (value instanceof Array) {
                            value = "(" + operator.value.join(",") + ")";
                        }
                        return name + "(" + operator.field + "," + value + ")";
                    }
                } else {
                    return name;
                }
            },

            translateExpressions: function (expressions, depth) {
                var ret = [];
                for (var i = 0; i < expressions.length; i++) {
                    ret.push(this.translateOperator(expressions[i], depth));
                }
                return ret;
            }

        };

        exports.RestQueryComposer = QueryComposer;

        return exports;
    });
<commit_msg>added type check for compose<commit_after>({define: typeof define != "undefined" ? define : function (deps, factory) {
    module.exports = factory(exports, require("../..").Query);
}}).define(["exports", "Query"], function (exports, Query) {

        var comparatorMap = {
            "eql": "=",
            "gt": ">",
            "lt": "<",
            "lte": "<=",
            "gte": ">="
        }, undefined;

        var QueryComposer = {

            compose: function (query) {

                var hash = query.query,
                    ret = {};

                if (hash.sort) {
                    ret.sort = this.translateSort(hash.sort);
                }

                if (hash.where) {
                    ret.where = this.translateOperator(hash.where)
                }

                return ret;
            },

            translateSort: function (sort) {
                return sort.join(",");
            },

            translateOperator: function (operator, depth) {
                depth = depth === undefined ? 0 : depth;
                var name = operator.operator;
                if (operator instanceof Query.Where) {
                    var expressions = this.translateExpressions(operator.expressions, depth + 1).join(" " + name + " ");
                    if (expressions.length > 1 && depth !== 0) {
                        return "(" + expressions + ")";
                    }
                    return expressions;
                } else if(operator instanceof  Query.Comparator){
                    var value = operator.getValue();
                    var type = typeof(value);
                    if (type === "string") {
                        if (/^(\d+|false|true|null)$/.test(value)
                            || this.value === "false" || this.value === "true") {
                            value = type + ":" + value;
                        }
                    }
                    if (comparatorMap.hasOwnProperty(name)) {
                        return operator.field + comparatorMap[name] + value;
                    } else if (operator.field && value !== undefined) {
                        if (value instanceof Array) {
                            value = "(" + operator.value.join(",") + ")";
                        }
                        return name + "(" + operator.field + "," + value + ")";
                    }
                } else {
                    return name;
                }
            },

            translateExpressions: function (expressions, depth) {
                var ret = [];
                for (var i = 0; i < expressions.length; i++) {
                    ret.push(this.translateOperator(expressions[i], depth));
                }
                return ret;
            }

        };

        exports.RestQueryComposer = QueryComposer;

        return exports;
    });
<|endoftext|>


<commit_before>function BattleRenderer(battle_data) {

    var zis = this;

    /* API */

    zis.click_callback = undefined;
    zis.hover_callback = undefined;

    zis.step_back = function () {
        if (zis.showing_turn > 0) zis.showing_turn--;
        zis.animated_update();
    };

    zis.step_fwd = function () {
        if (zis.showing_turn < zis.turn_count - 1) zis.showing_turn++;
        zis.animated_update();
    };

    zis.turn_back = function () {
        zis.showing_turn = Math.max(
            zis.showing_turn - zis.battle_ticks_per_turn,
            0
        );
        zis.animated_update();
    };

    zis.turn_fwd = function () {
        zis.showing_turn = Math.min(
            zis.showing_turn + zis.battle_ticks_per_turn,
            zis.turn_count - 1
        );
        zis.animated_update();
    };

    /* INTERNALS */

    zis.render_ground = function () {
        var ground = new THREE.Mesh( zis.ground_geometry, zis.ground_material );
        ground.position.x = 0;
        ground.position.z = 0;
        ground.position.y = -1;
        zis.renderer.scene.add(ground);
    };

    zis.get_contubernium_actual_material = function (contubernium) {
        if (contubernium === zis.clicked_contubernium) {
            return zis.contubernium_material_highlighted;
        } else if (contubernium === zis.picked_contubernium) {
            return zis.contubernium_material_highlighted;
        } else {
            return zis.get_contubernium_default_material(contubernium);
        }
    };

    zis.get_contubernium_default_material = function (contubernium) {
        var unit = zis.units[contubernium.unit_id];
        var character = zis.characters[unit.character_id];
        var organization = zis.organizations[unit.organization_id];
        return organization.material;
    };

    zis.add_contubernium = function (contubernium, contubernium_in_turn) {
        var material = zis.get_contubernium_default_material(contubernium);
        var mesh = new THREE.Mesh( zis.contubernium_geometry, material );

        if (contubernium_in_turn == undefined) {
            mesh.position.x = 1000;
            mesh.position.z = 1000;
        } else {
            mesh.position.x = contubernium_in_turn.x_pos;
            mesh.position.z = contubernium_in_turn.z_pos;
        }
        mesh.position.y = 0.5;

        mesh.contubernium = contubernium;
        mesh.pick_type = "contubernium";
        contubernium.mesh = mesh;

        zis.renderer.scene.add(mesh);
    };

    zis.update_turn_counter = function () {
        $('#current_turn_display').text(zis.showing_turn);
        $('#total_turn_display').text(zis.turn_count - 1);
    };

    zis.render_turn = function (turn_num) {
        for (var contubernium_id in zis.contubernia)  {
            if (Object.prototype.hasOwnProperty.call(zis.contubernia, contubernium_id)) {
                var contubernium = zis.contubernia[contubernium_id];
                var contubernium_in_turn = contubernium.in_turn[turn_num];

                if (contubernium.mesh === undefined) {
                    zis.add_contubernium(contubernium, contubernium_in_turn)
                }
            }
        }
        zis.update_turn_counter();
    };

    zis.animated_update = function () {
        for (var contubernium_id in zis.contubernia) {
            if (Object.prototype.hasOwnProperty.call(zis.contubernia, contubernium_id)) {
                var contubernium = zis.contubernia[contubernium_id];
                var contubernium_in_turn = contubernium.in_turn[zis.showing_turn];

                if (contubernium.mesh === undefined) {
                    zis.add_contubernium(contubernium, contubernium_in_turn);
                } else {
                    contubernium.mesh.position.x = contubernium_in_turn === undefined ? 1000 : contubernium_in_turn.x_pos;
                    contubernium.mesh.position.z = contubernium_in_turn === undefined ? 1000 : contubernium_in_turn.z_pos;
                }

            }
        }
        zis.renderer.render();
        zis.update_turn_counter();
    };

    zis.generate_organization_materials = function () {
        for (var organization_id in zis.organizations) {
            if (Object.prototype.hasOwnProperty.call(zis.organizations, organization_id)) {
                var organization = zis.organizations[organization_id];
                organization.material = new THREE.MeshLambertMaterial({
                    color: parseInt(organization.color, 16)
                });
            }
        }
    };

    zis.mouse_click_listener_notifier = function (event) {
        var previously_clicked = zis.clicked_contubernium;

        if (zis.picked_contubernium === undefined) {
            zis.clicked_contubernium = undefined;
        } else {
            zis.clicked_contubernium = zis.picked_contubernium;
            zis.clicked_contubernium.mesh.material = zis.get_contubernium_actual_material(zis.clicked_contubernium);
        }
        if (previously_clicked !== undefined) {
            previously_clicked.mesh.material = zis.get_contubernium_actual_material(previously_clicked);
        }

        zis.renderer.render();

        if (zis.click_callback) {
            if (zis.clicked_contubernium === undefined) {
                zis.click_callback(undefined, undefined, undefined, undefined);
            } else {
                var unit = zis.units[zis.clicked_contubernium.unit_id];
                var character = zis.characters[unit.character_id];
                var organization = zis.organizations[character.organization_id];
                zis.click_callback(zis.clicked_contubernium, unit, character, organization);
            }
        }
    };

    zis.notify_contubernium_pick = function (contubernium_three_object) {
        var previously_picked = zis.picked_contubernium;

        if (contubernium_three_object === undefined) {
            zis.picked_contubernium = undefined;
        } else {
            zis.picked_contubernium = contubernium_three_object.contubernium;
            zis.picked_contubernium.mesh.material = zis.get_contubernium_actual_material(zis.picked_contubernium);
        }
        if (previously_picked !== undefined) {
            previously_picked.mesh.material = zis.get_contubernium_actual_material(previously_picked);
        }

        zis.renderer.render();

        if (zis.hover_callback) {
            if (zis.picked_contubernium === undefined) {
                zis.hover_callback(undefined, undefined, undefined, undefined);
            } else {
                var unit = zis.units[zis.picked_contubernium.unit_id];
                var character = zis.characters[unit.character_id];
                var organization = zis.organizations[unit.organization_id];
                zis.hover_callback(
                    zis.picked_contubernium,
                    zis.picked_contubernium.in_turn[zis.showing_turn],
                    unit,
                    character,
                    organization
                );
            }
        }

    };

    /* DATA */

    zis.organizations = battle_data.organizations;
    zis.characters = battle_data.characters;
    zis.units = battle_data.units;
    zis.contubernia = battle_data.contubernia;
    zis.battle_ticks_per_turn = battle_data.battle_ticks_per_turn;
    zis.turn_count = battle_data.turn_count;

    /* VARS */
    zis.showing_turn = Math.max(zis.turn_count - 1 - zis.battle_ticks_per_turn, 0);
    zis.picked_contubernium = undefined;
    zis.clicked_contubernium = undefined;

    /* MATERIALS AND GEOMETRIES */

    zis.contubernium_material_highlighted = new THREE.MeshBasicMaterial( {color: 0xFFFFFF} );
    zis.ground_material = new THREE.MeshLambertMaterial({color: 0x1A5B07});
    zis.ground_geometry = new THREE.CubeGeometry(300, 2, 300);
    zis.contubernium_geometry = new THREE.CubeGeometry(0.9, 0.9, 0.9);
    zis.generate_organization_materials();

    /* CONSTRUCTION */

    zis.renderer = new BaseRenderer(40, 60, 0);
    zis.renderer.picking_types['contubernium'] = zis.notify_contubernium_pick;
    zis.render_ground();
    zis.render_turn(zis.showing_turn);

    zis.renderer.render();
    $(zis.renderer.canvas_container).on('click', zis.mouse_click_listener_notifier);

}
<commit_msg>Contubernium mesh size proportional to contubernium soldier count<commit_after>function BattleRenderer(battle_data) {

    var zis = this;

    /* API */

    zis.click_callback = undefined;
    zis.hover_callback = undefined;

    zis.step_back = function () {
        if (zis.showing_turn > 0) zis.showing_turn--;
        zis.animated_update();
    };

    zis.step_fwd = function () {
        if (zis.showing_turn < zis.turn_count - 1) zis.showing_turn++;
        zis.animated_update();
    };

    zis.turn_back = function () {
        zis.showing_turn = Math.max(
            zis.showing_turn - zis.battle_ticks_per_turn,
            0
        );
        zis.animated_update();
    };

    zis.turn_fwd = function () {
        zis.showing_turn = Math.min(
            zis.showing_turn + zis.battle_ticks_per_turn,
            zis.turn_count - 1
        );
        zis.animated_update();
    };

    /* INTERNALS */

    zis.render_ground = function () {
        var ground = new THREE.Mesh( zis.ground_geometry, zis.ground_material );
        ground.position.x = 0;
        ground.position.z = 0;
        ground.position.y = -1;
        zis.renderer.scene.add(ground);
    };

    zis.get_contubernium_actual_material = function (contubernium) {
        if (contubernium === zis.clicked_contubernium) {
            return zis.contubernium_material_highlighted;
        } else if (contubernium === zis.picked_contubernium) {
            return zis.contubernium_material_highlighted;
        } else {
            return zis.get_contubernium_default_material(contubernium);
        }
    };

    zis.get_contubernium_default_material = function (contubernium) {
        var unit = zis.units[contubernium.unit_id];
        var character = zis.characters[unit.character_id];
        var organization = zis.organizations[unit.organization_id];
        return organization.material;
    };

    zis.add_contubernium = function (contubernium, contubernium_in_turn) {
        var material = zis.get_contubernium_default_material(contubernium);
        var mesh = new THREE.Mesh( zis.contubernium_geometry, material );

        if (contubernium_in_turn == undefined) {
            mesh.position.x = 1000;
            mesh.position.z = 1000;
        } else {
            mesh.position.x = contubernium_in_turn.x_pos;
            mesh.position.z = contubernium_in_turn.z_pos;
        }
        mesh.position.y = 0.5;

        mesh.scale.x = Math.sqrt(contubernium_in_turn.soldiers.length) / Math.sqrt(8);
        mesh.scale.z = Math.sqrt(contubernium_in_turn.soldiers.length) / Math.sqrt(8);

        mesh.contubernium = contubernium;
        mesh.pick_type = "contubernium";
        contubernium.mesh = mesh;

        zis.renderer.scene.add(mesh);
    };

    zis.update_turn_counter = function () {
        $('#current_turn_display').text(zis.showing_turn);
        $('#total_turn_display').text(zis.turn_count - 1);
    };

    zis.render_turn = function (turn_num) {
        for (var contubernium_id in zis.contubernia)  {
            if (Object.prototype.hasOwnProperty.call(zis.contubernia, contubernium_id)) {
                var contubernium = zis.contubernia[contubernium_id];
                var contubernium_in_turn = contubernium.in_turn[turn_num];

                if (contubernium.mesh === undefined) {
                    zis.add_contubernium(contubernium, contubernium_in_turn)
                }
            }
        }
        zis.update_turn_counter();
    };

    zis.animated_update = function () {
        for (var contubernium_id in zis.contubernia) {
            if (Object.prototype.hasOwnProperty.call(zis.contubernia, contubernium_id)) {
                var contubernium = zis.contubernia[contubernium_id];
                var contubernium_in_turn = contubernium.in_turn[zis.showing_turn];

                if (contubernium.mesh === undefined) {
                    zis.add_contubernium(contubernium, contubernium_in_turn);
                } else {
                    contubernium.mesh.position.x = contubernium_in_turn === undefined ? 1000 : contubernium_in_turn.x_pos;
                    contubernium.mesh.position.z = contubernium_in_turn === undefined ? 1000 : contubernium_in_turn.z_pos;
                    contubernium.mesh.scale.x = contubernium_in_turn === undefined ? 0 : Math.sqrt(contubernium_in_turn.soldiers.length) / Math.sqrt(8);
                    contubernium.mesh.scale.z = contubernium_in_turn === undefined ? 0 : Math.sqrt(contubernium_in_turn.soldiers.length) / Math.sqrt(8);
                }

            }
        }
        zis.renderer.render();
        zis.update_turn_counter();
    };

    zis.generate_organization_materials = function () {
        for (var organization_id in zis.organizations) {
            if (Object.prototype.hasOwnProperty.call(zis.organizations, organization_id)) {
                var organization = zis.organizations[organization_id];
                organization.material = new THREE.MeshLambertMaterial({
                    color: parseInt(organization.color, 16)
                });
            }
        }
    };

    zis.mouse_click_listener_notifier = function (event) {
        var previously_clicked = zis.clicked_contubernium;

        if (zis.picked_contubernium === undefined) {
            zis.clicked_contubernium = undefined;
        } else {
            zis.clicked_contubernium = zis.picked_contubernium;
            zis.clicked_contubernium.mesh.material = zis.get_contubernium_actual_material(zis.clicked_contubernium);
        }
        if (previously_clicked !== undefined) {
            previously_clicked.mesh.material = zis.get_contubernium_actual_material(previously_clicked);
        }

        zis.renderer.render();

        if (zis.click_callback) {
            if (zis.clicked_contubernium === undefined) {
                zis.click_callback(undefined, undefined, undefined, undefined);
            } else {
                var unit = zis.units[zis.clicked_contubernium.unit_id];
                var character = zis.characters[unit.character_id];
                var organization = zis.organizations[character.organization_id];
                zis.click_callback(zis.clicked_contubernium, unit, character, organization);
            }
        }
    };

    zis.notify_contubernium_pick = function (contubernium_three_object) {
        var previously_picked = zis.picked_contubernium;

        if (contubernium_three_object === undefined) {
            zis.picked_contubernium = undefined;
        } else {
            zis.picked_contubernium = contubernium_three_object.contubernium;
            zis.picked_contubernium.mesh.material = zis.get_contubernium_actual_material(zis.picked_contubernium);
        }
        if (previously_picked !== undefined) {
            previously_picked.mesh.material = zis.get_contubernium_actual_material(previously_picked);
        }

        zis.renderer.render();

        if (zis.hover_callback) {
            if (zis.picked_contubernium === undefined) {
                zis.hover_callback(undefined, undefined, undefined, undefined);
            } else {
                var unit = zis.units[zis.picked_contubernium.unit_id];
                var character = zis.characters[unit.character_id];
                var organization = zis.organizations[unit.organization_id];
                zis.hover_callback(
                    zis.picked_contubernium,
                    zis.picked_contubernium.in_turn[zis.showing_turn],
                    unit,
                    character,
                    organization
                );
            }
        }

    };

    /* DATA */

    zis.organizations = battle_data.organizations;
    zis.characters = battle_data.characters;
    zis.units = battle_data.units;
    zis.contubernia = battle_data.contubernia;
    zis.battle_ticks_per_turn = battle_data.battle_ticks_per_turn;
    zis.turn_count = battle_data.turn_count;

    /* VARS */
    zis.showing_turn = Math.max(zis.turn_count - 1 - zis.battle_ticks_per_turn, 0);
    zis.picked_contubernium = undefined;
    zis.clicked_contubernium = undefined;

    /* MATERIALS AND GEOMETRIES */

    zis.contubernium_material_highlighted = new THREE.MeshBasicMaterial( {color: 0xFFFFFF} );
    zis.ground_material = new THREE.MeshLambertMaterial({color: 0x1A5B07});
    zis.ground_geometry = new THREE.CubeGeometry(300, 2, 300);
    zis.contubernium_geometry = new THREE.CubeGeometry(0.9, 0.9, 0.9);
    zis.generate_organization_materials();

    /* CONSTRUCTION */

    zis.renderer = new BaseRenderer(40, 60, 0);
    zis.renderer.picking_types['contubernium'] = zis.notify_contubernium_pick;
    zis.render_ground();
    zis.render_turn(zis.showing_turn);

    zis.renderer.render();
    $(zis.renderer.canvas_container).on('click', zis.mouse_click_listener_notifier);

}
<|endoftext|>


<commit_before>var RemoteHook = require('./hook').RemoteHook,
	sys = require('sys')

exports.plugin = function(mediator, host)
{
	var oldAddChannel = mediator.addChannel,
	readyBeans = {},
	groupId;

	// mediator.middleware.add(require('./middleware/hook'));

	mediator.addChannel = function(path, expr)
	{
		oldAddChannel.apply(mediator, arguments);

		//change here
		// mediator.push('channels', )
	}

	function init()
	{
		mediator.pull('hook/transport', function(transport)
		{
			new RemoteHook(transport, mediator);
		});
	}

	function onBeanReady(name)
	{
		readyBeans[name] = 1;

		mediator.push(name + '/ready');

		mediator.on('pull '+name+'/ready', { meta: { 'public': 1, 'rotate': 1 } }, function(pull)
		{
			pull.end(true);
		});
	}

	function getHook()
	{
		var channels = [],
			ch = mediator.channels();

		for(var channel in ch)
		{
			var expr = ch[channel];

			//make sure not to use any networked call
			if(expr.meta.hooked || !expr.meta['public']) continue;

			channels.push({ meta: expr.meta, path: channel });
		}

		var info = {
			cluster: groupId,
			channels: channels
		}

		return info;
	}

	function pullHook(writer)
	{
		writer.end(getHook());
	}

	function pushHook()
	{
		mediator.push('hook', getHook());
	}

	function onAppId(data)
	{
		console.log(data)
	}

	function setAppGroup(data)
	{
		groupId = data;

		pushHook();
	}

	function onConnection(data, req)
	{
		// console.log(req.from.channels);

		for(var bean in readyBeans)
		{
			req.from.push(bean + '/ready', true, { ignoreWarning: true });
		}
	}

	mediator.on({
		'push init': init,
		'push ready': onBeanReady,
		'pull hook': pullHook,

		//used for grouping apps so they communcate with one another only
		'push set/app/group': setAppGroup,

		'push hook/connection': onConnection,
	});
}<commit_msg>cleaned up<commit_after>var Hook = require('./hook'),
	sys = require('sys')

exports.plugin = function(mediator, host)
{
	var oldAddChannel = mediator.addChannel,
	readyBeans = {},
	groupId;

	// mediator.middleware.add(require('./middleware/hook'));

	mediator.addChannel = function(path, expr)
	{
		oldAddChannel.apply(mediator, arguments);

		//change here
		// mediator.push('channels', )
	}

	function init()
	{
		mediator.pull('hook/transport', function(transport)
		{
			new Hook(transport, mediator);
		});
	}

	function onBeanReady(name)
	{
		readyBeans[name] = 1;

		mediator.on('pull '+name+'/ready', { meta: { 'public': 1, 'rotate': 1 } }, function()
		{
			return true;
		});
	}

	function getHook()
	{
		var channels = [],
			ch = mediator.channels();

		for(var channel in ch)
		{
			var expr = ch[channel];

			//make sure not to use any networked call
			if(expr.meta.hooked || !expr.meta['public']) continue;

			channels.push({ meta: expr.meta, path: channel });
		}

		var info = {
			cluster: groupId,
			channels: channels
		}

		return info;
	}

	function pullHook()
	{
		return getHook();
	}

	function pushHook()
	{
		mediator.push('hook', getHook());
	}

	function onAppId(data)
	{
		console.log(data)
	}

	function setAppGroup(data)
	{
		groupId = data;

		pushHook();
	}

	function onConnection(data)
	{
		// console.log(req.from.channels);

		for(var bean in readyBeans)
		{
			this.from.push(bean + '/ready', true, { ignoreWarning: true });
		}
	}

	mediator.on({
		'push init': init,
		'push ready': onBeanReady,
		'pull hook': pullHook,

		//used for grouping apps so they communcate with one another only
		'push set/app/group': setAppGroup,

		'push hook/connection': onConnection,
	});
}<|endoftext|>


<commit_before>import path from 'path';
import { Router } from 'express';
import webpack from 'webpack';

import webpackDevMiddleware from 'webpack-dev-middleware';
import webpackHotMiddleware from 'webpack-hot-middleware';

import { logger } from '@storybook/node-logger';
import { getMiddleware } from './utils/middleware';
import { logConfig } from './logConfig';
import loadConfig from './config';
import loadManagerConfig from './manager/manager-config';
import { resolvePathInStorybookCache } from './utils/resolve-path-in-sb-cache';

const dllPath = path.join(__dirname, '../../dll');

const cache = {};

let previewProcess;
let previewReject;
let resolved = false;

const router = new Router();

export default function (options) {
  const configDir = path.resolve(options.configDir);
  const outputDir = options.smokeTest
    ? resolvePathInStorybookCache('public')
    : path.resolve(options.outputDir || resolvePathInStorybookCache('public'));
  const configType = 'DEVELOPMENT';

  const startTime = process.hrtime();
  let managerTotalTime;
  let previewTotalTime;

  const managerPromise = loadManagerConfig({
    ...options,
    configType,
    outputDir,
    configDir,
    cache,
    corePresets: [require.resolve('./manager/manager-preset.js')],
  }).then((config) => {
    if (options.debugWebpack) {
      logConfig('Manager webpack config', config, logger);
    }
    const managerCompiler = webpack(config);

    const devMiddlewareOptions = {
      publicPath: config.output.publicPath,
      writeToDisk: !!options.smokeTest,
      watchOptions: {
        aggregateTimeout: 2000,
        ignored: /node_modules/,
      },
      // this actually causes 0 (regular) output from wdm & webpack
      logLevel: 'warn',
      clientLogLevel: 'warning',
      noInfo: true,
    };

    const managerDevMiddlewareInstance = webpackDevMiddleware(
      managerCompiler,
      devMiddlewareOptions
    );

    router.get(/\/static\/media\/.*\..*/, (request, response, next) => {
      response.set('Cache-Control', `public, max-age=31536000`);
      next();
    });

    router.use(managerDevMiddlewareInstance);

    return new Promise((resolve, reject) => {
      managerDevMiddlewareInstance.waitUntilValid((stats) => {
        managerTotalTime = process.hrtime(startTime);

        if (!stats) {
          reject(new Error('no stats after building preview'));
        } else if (stats.hasErrors()) {
          reject(stats);
        } else {
          resolve(stats);
        }
      });
    });
  });

  const previewPromise = options.ignorePreview
    ? new Promise((resolve) => resolve())
    : loadConfig({
        configType,
        outputDir,
        cache,
        corePresets: [require.resolve('./preview/preview-preset.js')],
        overridePresets: [require.resolve('./preview/custom-webpack-preset.js')],
        ...options,
      }).then((previewConfig) => {
        if (options.debugWebpack) {
          logConfig('Preview webpack config', previewConfig, logger);
        }

        // remove the leading '/'
        let { publicPath } = previewConfig.output;
        if (publicPath[0] === '/') {
          publicPath = publicPath.slice(1);
        }

        const previewCompiler = webpack(previewConfig);

        const devMiddlewareOptions = {
          publicPath: previewConfig.output.publicPath,
          watchOptions: {
            aggregateTimeout: 1,
            ignored: /node_modules/,
            ...(previewConfig.watchOptions || {}),
          },
          // this actually causes 0 (regular) output from wdm & webpack
          logLevel: 'warn',
          clientLogLevel: 'warning',
          noInfo: true,
          ...previewConfig.devServer,
        };

        const previewDevMiddlewareInstance = webpackDevMiddleware(
          previewCompiler,
          devMiddlewareOptions
        );

        router.use(previewDevMiddlewareInstance);
        router.use(webpackHotMiddleware(previewCompiler));

        return new Promise((resolve, reject) => {
          previewReject = reject;
          previewDevMiddlewareInstance.waitUntilValid((stats) => {
            resolved = true;
            previewTotalTime = process.hrtime(startTime);

            if (!stats) {
              reject(new Error('no stats after building preview'));
            } else if (stats.hasErrors()) {
              reject(stats);
            } else {
              resolve(stats);
            }
          });
          previewProcess = previewDevMiddlewareInstance;
        });
      });

  // custom middleware
  const middlewareFn = getMiddleware(configDir);
  middlewareFn(router);

  managerPromise.catch((e) => {
    try {
      if (!resolved) {
        previewReject();
      }
      previewProcess.close();
      logger.warn('force closed preview build');
    } catch (err) {
      logger.warn('Unable to close preview build!');
    }
  });

  return Promise.all([managerPromise, previewPromise]).then(([managerStats, previewStats]) => {
    router.get('/', (request, response) => {
      response.set('Content-Type', 'text/html');
      response.sendFile(path.join(`${outputDir}/index.html`));
    });
    router.get(/\/sb_dll\/(.+\.js)$/, (request, response) => {
      response.set('Content-Type', 'text/javascript');
      response.sendFile(path.join(`${dllPath}/${request.params[0]}`));
    });
    router.get(/\/sb_dll\/(.+\.LICENCE)$/, (request, response) => {
      response.set('Content-Type', 'text/html');
      response.sendFile(path.join(`${dllPath}/${request.params[0]}`));
    });

    return { previewStats, managerStats, managerTotalTime, previewTotalTime, router };
  });
}
<commit_msg>Revert "fix: avoid overwriting dev config"<commit_after>import path from 'path';
import { Router } from 'express';
import webpack from 'webpack';

import webpackDevMiddleware from 'webpack-dev-middleware';
import webpackHotMiddleware from 'webpack-hot-middleware';

import { logger } from '@storybook/node-logger';
import { getMiddleware } from './utils/middleware';
import { logConfig } from './logConfig';
import loadConfig from './config';
import loadManagerConfig from './manager/manager-config';
import { resolvePathInStorybookCache } from './utils/resolve-path-in-sb-cache';

const dllPath = path.join(__dirname, '../../dll');

const cache = {};

let previewProcess;
let previewReject;
let resolved = false;

const router = new Router();

export default function (options) {
  const configDir = path.resolve(options.configDir);
  const outputDir = options.smokeTest
    ? resolvePathInStorybookCache('public')
    : path.resolve(options.outputDir || resolvePathInStorybookCache('public'));
  const configType = 'DEVELOPMENT';

  const startTime = process.hrtime();
  let managerTotalTime;
  let previewTotalTime;

  const managerPromise = loadManagerConfig({
    configType,
    outputDir,
    configDir,
    cache,
    corePresets: [require.resolve('./manager/manager-preset.js')],
    ...options,
  }).then((config) => {
    if (options.debugWebpack) {
      logConfig('Manager webpack config', config, logger);
    }
    const managerCompiler = webpack(config);

    const devMiddlewareOptions = {
      publicPath: config.output.publicPath,
      writeToDisk: !!options.smokeTest,
      watchOptions: {
        aggregateTimeout: 2000,
        ignored: /node_modules/,
      },
      // this actually causes 0 (regular) output from wdm & webpack
      logLevel: 'warn',
      clientLogLevel: 'warning',
      noInfo: true,
    };

    const managerDevMiddlewareInstance = webpackDevMiddleware(
      managerCompiler,
      devMiddlewareOptions
    );

    router.get(/\/static\/media\/.*\..*/, (request, response, next) => {
      response.set('Cache-Control', `public, max-age=31536000`);
      next();
    });

    router.use(managerDevMiddlewareInstance);

    return new Promise((resolve, reject) => {
      managerDevMiddlewareInstance.waitUntilValid((stats) => {
        managerTotalTime = process.hrtime(startTime);

        if (!stats) {
          reject(new Error('no stats after building preview'));
        } else if (stats.hasErrors()) {
          reject(stats);
        } else {
          resolve(stats);
        }
      });
    });
  });

  const previewPromise = options.ignorePreview
    ? new Promise((resolve) => resolve())
    : loadConfig({
        configType,
        outputDir,
        cache,
        corePresets: [require.resolve('./preview/preview-preset.js')],
        overridePresets: [require.resolve('./preview/custom-webpack-preset.js')],
        ...options,
      }).then((previewConfig) => {
        if (options.debugWebpack) {
          logConfig('Preview webpack config', previewConfig, logger);
        }

        // remove the leading '/'
        let { publicPath } = previewConfig.output;
        if (publicPath[0] === '/') {
          publicPath = publicPath.slice(1);
        }

        const previewCompiler = webpack(previewConfig);

        const devMiddlewareOptions = {
          publicPath: previewConfig.output.publicPath,
          watchOptions: {
            aggregateTimeout: 1,
            ignored: /node_modules/,
            ...(previewConfig.watchOptions || {}),
          },
          // this actually causes 0 (regular) output from wdm & webpack
          logLevel: 'warn',
          clientLogLevel: 'warning',
          noInfo: true,
          ...previewConfig.devServer,
        };

        const previewDevMiddlewareInstance = webpackDevMiddleware(
          previewCompiler,
          devMiddlewareOptions
        );

        router.use(previewDevMiddlewareInstance);
        router.use(webpackHotMiddleware(previewCompiler));

        return new Promise((resolve, reject) => {
          previewReject = reject;
          previewDevMiddlewareInstance.waitUntilValid((stats) => {
            resolved = true;
            previewTotalTime = process.hrtime(startTime);

            if (!stats) {
              reject(new Error('no stats after building preview'));
            } else if (stats.hasErrors()) {
              reject(stats);
            } else {
              resolve(stats);
            }
          });
          previewProcess = previewDevMiddlewareInstance;
        });
      });

  // custom middleware
  const middlewareFn = getMiddleware(configDir);
  middlewareFn(router);

  managerPromise.catch((e) => {
    try {
      if (!resolved) {
        previewReject();
      }
      previewProcess.close();
      logger.warn('force closed preview build');
    } catch (err) {
      logger.warn('Unable to close preview build!');
    }
  });

  return Promise.all([managerPromise, previewPromise]).then(([managerStats, previewStats]) => {
    router.get('/', (request, response) => {
      response.set('Content-Type', 'text/html');
      response.sendFile(path.join(`${outputDir}/index.html`));
    });
    router.get(/\/sb_dll\/(.+\.js)$/, (request, response) => {
      response.set('Content-Type', 'text/javascript');
      response.sendFile(path.join(`${dllPath}/${request.params[0]}`));
    });
    router.get(/\/sb_dll\/(.+\.LICENCE)$/, (request, response) => {
      response.set('Content-Type', 'text/html');
      response.sendFile(path.join(`${dllPath}/${request.params[0]}`));
    });

    return { previewStats, managerStats, managerTotalTime, previewTotalTime, router };
  });
}
<|endoftext|>


<commit_before>(function()
{
  angular
    .module('history')
    .controller('HistoryController', HistoryController);

  HistoryController.$inject = ['$scope', '$ionicPopup', '$ionicActionSheet', '$filter', 'localStorage', 'FooseyService', 'SettingsService'];

  function HistoryController($scope, $ionicPopup, $ionicActionSheet, $filter, localStorage, FooseyService, SettingsService)
  {
    // some variables
    var loaded = 0;
    var gamesToLoad = 30;

    // create a pull-to-refresh function
    $scope.refresh = refresh;

    // initialize the page
    $scope.removing = false;
    $scope.loading = true;
    $scope.refresh();
    $scope.loadMore = loadMore;
    $scope.show = show;
    $scope.showElo = SettingsService.showElo;
    // toggleFilter('Peter');
    // clearFilters();

    // refresh page function
    function refresh()
    {
      // load from local storage
      $scope.dates = localStorage.getObject('history');

      // get most recent games and group by the date
      FooseyService.getGames(gamesToLoad, 0)
      .then(function successCallback(result)
      {
        // get games from server
        $scope.games = result;
        loaded += result.length;

        // filter by name
        applyFilters();

        // sort the games by date
        $scope.dates = groupByDate($scope.filteredGames);

        // store them to local storage
        localStorage.setObject('history', $scope.dates);
        $scope.error = false;

        done();
      }, function errorCallback(response)
      {
        $scope.error = true;
        done();
      });
    }

    // infinite scroll
    function loadMore()
    {
      console.log("Loading new games starting from " + loaded + " to " + (loaded + gamesToLoad));
      FooseyService.getGames(gamesToLoad, loaded + gamesToLoad)
      .then(function successCallback(result)
      {
        // if no games have been loaded yet, we can't do anything
        if (!$scope.games) return;

        // push new games to the end of the games list
        $scope.games.push.apply($scope.games, result);
        console.log("Loaded " + result.length);
        loaded += result.length;

        // see if we can load more games or not
        $scope.allLoaded = $scope.games[$scope.games.length - 1].id === 0;

        // filter by name
        applyFilters();

        // sort the games by date
        $scope.dates = groupByDate($scope.filteredGames);

        // broadcast
        $scope.$broadcast('scroll.infiniteScrollComplete');
      })
    }

    // group the games by date
    function groupByDate(games)
    {
      return _.chain(games)
      .groupBy('date')
      .pairs()
      .map(function (currentItem)
      {
        return _.object(_.zip(['date', 'games'], currentItem));
      })
      .value();
    }

    // turns off spinner and notifies
    function done()
    {
      $scope.$broadcast('scroll.refreshComplete');
      $scope.$broadcast('scroll.infiniteScrollComplete');
      $scope.removing = false;
      $scope.loading = false;
    }

    // show the action sheet for deleting games
    function show(game)
    {
      // Show the action sheet
      $ionicActionSheet.show(
      {
        titleText: $filter('time')(game.timestamp),
        destructiveText: 'Remove Game',
        cancelText: 'Cancel',
        destructiveButtonClicked: function(index)
        {
          confirmRemove(game);
          return true;
        }
      });
    };

    // confirm that they actually want to remove
    function confirmRemove(game)
    {
      if ($scope.removing)
      {
        var alertPopup = $ionicPopup.alert({
          title: 'Can\'t Remove Game',
          template: 'Another game is already being removed at this time. Try again later.'
        });
      }
      else
      {
        var confirmPopup = $ionicPopup.confirm({
          title: 'Remove This Game',
          template: 'Are you sure you want to remove this game? This cannot be undone.'
        });

        // if yes, delete the last game
        confirmPopup.then(function(positive) {
          if(positive) {
            remove(game);
          }
        });
      }
    }

    // Remove game
    function remove(game)
    {
      // remove game from UI and re-sort by date
      var index = _.indexOf(_.pluck($scope.games, 'gameID'), game.gameID);
      $scope.games.splice(index, 1);
      $scope.dates = groupByDate($scope.games);
      localStorage.setObject('history', $scope.dates)

      // remove from server
      $scope.removing = true;
      $scope.loading = true;
      FooseyService.removeGame(game.gameID)
      .then(function()
      {
        refresh();
      });
    }

    function toggleFilter(name)
    {
      var filters = localStorage.getObject('filters');
      filters     = _.xor(filters, [name]);
      localStorage.setObject('filters', filters);
    }

    function clearFilters()
    {
      localStorage.setObject('filters', []);
    }

    function applyFilters()
    {
      $scope.filteredGames = [];
      var filters = localStorage.getObject('filters');
      if (filters && filters.length > 0)
      {
        _.forEach($scope.games, function(game)
        {
          var include = true
          _.forEach(filters, function(name)
          {
            if (!gameIncludes(game, name))
              include = false;
          });
          if (include) $scope.filteredGames.push(game);
        });
      }
      else
      {
        $scope.filteredGames = $scope.games
      }
    }

    function gameIncludes(game, name)
    {
      var include = false;
      _.forEach(game.teams, function(team)
      {
        if (_.includes(team.players, name))
          include = true;
      })
      return include;
    }
  }
})();<commit_msg>Fixed history reload bug<commit_after>(function()
{
  angular
    .module('history')
    .controller('HistoryController', HistoryController);

  HistoryController.$inject = ['$scope', '$ionicPopup', '$ionicActionSheet', '$filter', 'localStorage', 'FooseyService', 'SettingsService'];

  function HistoryController($scope, $ionicPopup, $ionicActionSheet, $filter, localStorage, FooseyService, SettingsService)
  {
    // some variables
    var loaded = 0;
    var gamesToLoad = 30;

    // create a pull-to-refresh function
    $scope.refresh = refresh;

    // initialize the page
    $scope.removing = false;
    $scope.loading = true;
    $scope.refresh();
    $scope.loadMore = loadMore;
    $scope.show = show;
    $scope.showElo = SettingsService.showElo;
    // toggleFilter('Peter');
    // clearFilters();

    // refresh page function
    function refresh()
    {
      // load from local storage
      $scope.dates = localStorage.getObject('history');
      loaded = 0;

      // get most recent games and group by the date
      FooseyService.getGames(gamesToLoad, 0)
      .then(function successCallback(result)
      {
        // get games from server
        $scope.games = result;
        loaded += result.length;

        // filter by name
        applyFilters();

        // sort the games by date
        $scope.dates = groupByDate($scope.filteredGames);

        // store them to local storage
        localStorage.setObject('history', $scope.dates);
        $scope.error = false;

        done();
      }, function errorCallback(response)
      {
        $scope.error = true;
        done();
      });
    }

    // infinite scroll
    function loadMore()
    {
      console.log("Loading new games starting from " + loaded + " to " + (loaded + gamesToLoad));
      FooseyService.getGames(gamesToLoad, loaded + gamesToLoad)
      .then(function successCallback(result)
      {
        // if no games have been loaded yet, we can't do anything
        if (!$scope.games) return;

        // push new games to the end of the games list
        $scope.games.push.apply($scope.games, result);
        console.log("Loaded " + result.length);
        loaded += result.length;

        // see if we can load more games or not
        $scope.allLoaded = $scope.games[$scope.games.length - 1].id === 0;

        // filter by name
        applyFilters();

        // sort the games by date
        $scope.dates = groupByDate($scope.filteredGames);

        // broadcast
        $scope.$broadcast('scroll.infiniteScrollComplete');
      })
    }

    // group the games by date
    function groupByDate(games)
    {
      return _.chain(games)
      .groupBy('date')
      .pairs()
      .map(function (currentItem)
      {
        return _.object(_.zip(['date', 'games'], currentItem));
      })
      .value();
    }

    // turns off spinner and notifies
    function done()
    {
      $scope.$broadcast('scroll.refreshComplete');
      $scope.$broadcast('scroll.infiniteScrollComplete');
      $scope.removing = false;
      $scope.loading = false;
    }

    // show the action sheet for deleting games
    function show(game)
    {
      // Show the action sheet
      $ionicActionSheet.show(
      {
        titleText: $filter('time')(game.timestamp),
        destructiveText: 'Remove Game',
        cancelText: 'Cancel',
        destructiveButtonClicked: function(index)
        {
          confirmRemove(game);
          return true;
        }
      });
    };

    // confirm that they actually want to remove
    function confirmRemove(game)
    {
      if ($scope.removing)
      {
        var alertPopup = $ionicPopup.alert({
          title: 'Can\'t Remove Game',
          template: 'Another game is already being removed at this time. Try again later.'
        });
      }
      else
      {
        var confirmPopup = $ionicPopup.confirm({
          title: 'Remove This Game',
          template: 'Are you sure you want to remove this game? This cannot be undone.'
        });

        // if yes, delete the last game
        confirmPopup.then(function(positive) {
          if(positive) {
            remove(game);
          }
        });
      }
    }

    // Remove game
    function remove(game)
    {
      // remove game from UI and re-sort by date
      var index = _.indexOf(_.pluck($scope.games, 'gameID'), game.gameID);
      $scope.games.splice(index, 1);
      $scope.dates = groupByDate($scope.games);
      localStorage.setObject('history', $scope.dates)

      // remove from server
      $scope.removing = true;
      $scope.loading = true;
      FooseyService.removeGame(game.gameID)
      .then(function()
      {
        refresh();
      });
    }

    function toggleFilter(name)
    {
      var filters = localStorage.getObject('filters');
      filters     = _.xor(filters, [name]);
      localStorage.setObject('filters', filters);
    }

    function clearFilters()
    {
      localStorage.setObject('filters', []);
    }

    function applyFilters()
    {
      $scope.filteredGames = [];
      var filters = localStorage.getObject('filters');
      if (filters && filters.length > 0)
      {
        _.forEach($scope.games, function(game)
        {
          var include = true
          _.forEach(filters, function(name)
          {
            if (!gameIncludes(game, name))
              include = false;
          });
          if (include) $scope.filteredGames.push(game);
        });
      }
      else
      {
        $scope.filteredGames = $scope.games
      }
    }

    function gameIncludes(game, name)
    {
      var include = false;
      _.forEach(game.teams, function(team)
      {
        if (_.includes(team.players, name))
          include = true;
      })
      return include;
    }
  }
})();<|endoftext|>


<commit_before>NGApp.factory('MapService', function($rootScope, $resource, $routeParams) {
	var service = {
		icon: {
			car: {
				url: '/assets/cockpit/images/map-icon-driver-car.png',
				size: new google.maps.Size(26,35),
				scaledSize: new google.maps.Size(26,35),
				origin: new google.maps.Point(0, 0)
			},
			bike: {
				url: '/assets/cockpit/images/map-icon-driver-bike.png',
				size: new google.maps.Size(26,35),
				scaledSize: new google.maps.Size(26,35),
				origin: new google.maps.Point(0, 0)
			},
			customer: {
				url: '/assets/cockpit/images/map-icon-customer.png',
				size: new google.maps.Size(26,35),
				scaledSize: new google.maps.Size(26,35),
				origin: new google.maps.Point(0, 0)
			},
			restaurant: {
				url: '/assets/cockpit/images/map-icon-restaurant.png',
				size: new google.maps.Size(26,35),
				scaledSize: new google.maps.Size(26,35),
				origin: new google.maps.Point(0, 0)
			},
			dot: {
				url: '/assets/cockpit/images/map-icon-dot.png',
				size: new google.maps.Size(8,8),
				scaledSize: new google.maps.Size(8,8),
				origin: new google.maps.Point(0, 0)
			}
		}
	};

	service.styles = {
		cockpit: [
		{"featureType":"water","elementType":"geometry","stylers":[{"color":"#333739"}]},
		{"featureType":"landscape","elementType":"geometry","stylers":[{"color":"#265754"}]},
		{"featureType":"poi","stylers":[{"color":"#31736e"},{"lightness":-7}]},
		{"featureType":"road.highway","elementType":"geometry","stylers":[{"color":"#3baaa3"},{"lightness":-28}]},
		{"featureType":"road.arterial","elementType":"geometry","stylers":[{"color":"#3baaa3"},{"visibility":"on"},{"lightness":-15}]},
		{"featureType":"road.local",
			"elementType":"geometry","stylers":[{"color":"#308a84"},{"lightness":-18}]},
			{"elementType":"labels.text.fill","stylers":[{"color":"#ffffff"}]},
			{"elementType":"labels.text.stroke","stylers":[{"visibility":"off"}]},
		{"featureType":"transit","elementType":"geometry","stylers":[{"color":"#38a9a1"},{"lightness":-34}]},
		{"featureType":"administrative","elementType":"geometry","stylers":[{"visibility":"on"},{"color":"#388a84"},{"weight":0.8}]},
		{"featureType":"poi.park","stylers":[{"color":"#225652"}]},
		{"featureType":"road","elementType":"geometry.stroke","stylers":[{"color":"#308a84"},{"weight":0.1},{"lightness":10}]}],
	};

	service.style = function(map) {
		map.setOptions({styles: service.styles.cockpit});
	};

	var maps = {};

	service.reset = function(id) {
		maps[id] = null;
	};

	service.trackStaff = function(params) {
		var map = params.map;

		if (!maps[params.id]) {
			maps[params.id] = {markers: {}};
			params.scope.$on('$destroy', function() {
				service.reset(params.id);
			});
		}

		var locs = {};

		locs[params.staff.location.lat] = params.staff.location.lon;

		for (var x in params.locations) {
			if (locs[params.locations[x].lat] == params.locations[x].lon) {
				continue;
			}
			new google.maps.Marker({
				map: map,
				position: new google.maps.LatLng(parseFloat(params.locations[x].lat), parseFloat(params.locations[x].lon)+(x/100)),
				zIndex: 99,
				icon: service.icon.dot
			});
			locs[params.locations[x].lat] = params.locations[x].lon;
		}

		if (maps[params.id].markers.current) {
			maps[params.id].markers.current.setMap(null);
		}

		var myLatlng = new google.maps.LatLng(parseFloat(params.staff.location.lat), parseFloat(params.staff.location.lon));

		map.setCenter(myLatlng);
		maps[params.id].markers.current = new google.maps.Marker({
			map: map,
			position: myLatlng,
			zIndex: 100,
			icon: params.staff.vehicle == 'car' ? service.icon.car : service.icon.bike
		});
	};

	service.trackOrder = function(params) {
		var map = params.map;
		var driver = new google.maps.LatLng(parseFloat(params.driver.location.lat), parseFloat(params.driver.location.lon));
		var restaurant = new google.maps.LatLng(parseFloat(params.restaurant.loc_lat), parseFloat(params.restaurant.loc_long));

		if (!maps[params.id]) {
			maps[params.id] = {markers: {}};
			params.scope.$on('$destroy', function() {
				service.reset(params.id);
			});
		}

		var getDirections = function() {
			// directions render
			if (maps[params.id].markers.directions){
				maps[params.id].markers.directions.setMap(null);
			}

			var dest;
			if (params.order.status.status == 'accepted' || params.order.status.status == 'transfered') {
				//dest = restaurant;
				dest = maps[params.id].markers.customerLocation;
			} else if (params.order.status.status == 'pickedup') {
				dest = maps[params.id].markers.customerLocation;
			} else if (!maps[params.id].markers.directions) {
				map.setCenter(restaurant);
			} else {
				return;
			}

			var directionsService = new google.maps.DirectionsService();
			maps[params.id].markers.directions = new google.maps.DirectionsRenderer({suppressMarkers: true});
			maps[params.id].markers.directions.setMap(map);

			var routeParams = {
				origin: driver,
				destination: dest,
				travelMode: params.driver.vehicle == 'car' ? google.maps.TravelMode.DRIVING : google.maps.TravelMode.BICYCLING
			};

			if (params.order.status.status == 'accepted' || params.order.status.status == 'transfered') {
				routeParams.waypoints = [{location: restaurant,stopover: true}];
			}

			directionsService.route(routeParams, function(response, status) {
				console.debug('Got directions response: ', response);
				params.scope.$broadcast('order-route-' + params.order.id_order, response.routes[0].legs);

				if (status === google.maps.DirectionsStatus.OK) {
					maps[params.id].markers.directions.setDirections(response);
				}
			});
		}

		// restaurant marker
		if (!maps[params.id].markers.restaurant) {
			maps[params.id].markers.restaurant = new google.maps.Marker({
				map: map,
				position: restaurant,
				zIndex: 98,
				icon: service.icon.restaurant
			});
		}

		// driver marker
		if (maps[params.id].markers.driver) {
			if (maps[params.id].markers.driverLat == params.driver.location.lat && maps[params.id].markers.driverLon == params.driver.location.lon) {
				// no updates
				console.debug('No updated driver position');
				return;
			}
			maps[params.id].markers.driver.setMap(null);
			getDirections();
		}
		maps[params.id].markers.driverLat = params.driver.location.lat;
		maps[params.id].markers.driverLon = params.driver.location.lon;

		maps[params.id].markers.driver = new google.maps.Marker({
			map: map,
			position: driver,
			zIndex: 100,
			icon: params.driver.vehicle == 'car' ? service.icon.car : service.icon.bike
		});

		// customer marker
		if (!maps[params.id].markers.customer) {
			var geocoder = new google.maps.Geocoder();

			geocoder.geocode({address: params.order.address}, function (results, status) {
				if (status == google.maps.GeocoderStatus.OK) {
					console.debug('Got geocoded result: ', results[0]);

					maps[params.id].markers.customerLocation = results[0].geometry.location;

					maps[params.id].markers.customer = new google.maps.Marker({
						map: map,
						position: results[0].geometry.location,
						zIndex: 99,
						icon: service.icon.customer
					});

					getDirections();
				} else {
					console.error('Could not geocode address: ', d.address);
				}
			});
		}

	};

	return service;
} );<commit_msg>maps tweaks<commit_after>NGApp.factory('MapService', function($rootScope, $resource, $routeParams) {
	var service = {
		icon: {
			car: {
				url: '/assets/cockpit/images/map-icon-driver-car.png',
				size: new google.maps.Size(26,35),
				scaledSize: new google.maps.Size(26,35),
				origin: new google.maps.Point(0, 0)
			},
			bike: {
				url: '/assets/cockpit/images/map-icon-driver-bike.png',
				size: new google.maps.Size(26,35),
				scaledSize: new google.maps.Size(26,35),
				origin: new google.maps.Point(0, 0)
			},
			customer: {
				url: '/assets/cockpit/images/map-icon-customer.png',
				size: new google.maps.Size(26,35),
				scaledSize: new google.maps.Size(26,35),
				origin: new google.maps.Point(0, 0)
			},
			restaurant: {
				url: '/assets/cockpit/images/map-icon-restaurant.png',
				size: new google.maps.Size(26,35),
				scaledSize: new google.maps.Size(26,35),
				origin: new google.maps.Point(0, 0)
			},
			dot: {
				url: '/assets/cockpit/images/map-icon-dot.png',
				size: new google.maps.Size(8,8),
				scaledSize: new google.maps.Size(8,8),
				origin: new google.maps.Point(0, 0)
			}
		}
	};

	service.styles = {
		cockpit: [
		{"featureType":"water","elementType":"geometry","stylers":[{"color":"#333739"}]},
		{"featureType":"landscape","elementType":"geometry","stylers":[{"color":"#265754"}]},
		{"featureType":"poi","stylers":[{"color":"#31736e"},{"lightness":-7}]},
		{"featureType":"road.highway","elementType":"geometry","stylers":[{"color":"#3baaa3"},{"lightness":-28}]},
		{"featureType":"road.arterial","elementType":"geometry","stylers":[{"color":"#3baaa3"},{"visibility":"on"},{"lightness":-15}]},
		{"featureType":"road.local",
			"elementType":"geometry","stylers":[{"color":"#308a84"},{"lightness":-18}]},
			{"elementType":"labels.text.fill","stylers":[{"color":"#ffffff"}]},
			{"elementType":"labels.text.stroke","stylers":[{"visibility":"off"}]},
		{"featureType":"transit","elementType":"geometry","stylers":[{"color":"#38a9a1"},{"lightness":-34}]},
		{"featureType":"administrative","elementType":"geometry","stylers":[{"visibility":"on"},{"color":"#388a84"},{"weight":0.8}]},
		{"featureType":"poi.park","stylers":[{"color":"#225652"}]},
		{"featureType":"road","elementType":"geometry.stroke","stylers":[{"color":"#308a84"},{"weight":0.1},{"lightness":10}]}],
	};

	service.style = function(map) {
		map.setOptions({styles: service.styles.cockpit});
	};

	var maps = {};

	service.reset = function(id) {
		maps[id] = null;
	};

	service.trackStaff = function(params) {
		var map = params.map;

		if (!maps[params.id]) {
			maps[params.id] = {markers: {}};
			params.scope.$on('$destroy', function() {
				service.reset(params.id);
			});
		}

		var locs = {};

		locs[params.staff.location.lat] = params.staff.location.lon;

		for (var x in params.locations) {
			if (locs[params.locations[x].lat] == params.locations[x].lon) {
				continue;
			}
			new google.maps.Marker({
				map: map,
				position: new google.maps.LatLng(parseFloat(params.locations[x].lat), parseFloat(params.locations[x].lon)+(x/100)),
				zIndex: 99,
				icon: service.icon.dot
			});
			locs[params.locations[x].lat] = params.locations[x].lon;
		}

		if (maps[params.id].markers.current) {
			maps[params.id].markers.current.setMap(null);
		}

		var myLatlng = new google.maps.LatLng(parseFloat(params.staff.location.lat), parseFloat(params.staff.location.lon));

		map.setCenter(myLatlng);
		maps[params.id].markers.current = new google.maps.Marker({
			map: map,
			position: myLatlng,
			zIndex: 100,
			icon: params.staff.vehicle == 'car' ? service.icon.car : service.icon.bike
		});
	};

	service.trackOrder = function(params) {
		var map = params.map;
		var driver = new google.maps.LatLng(parseFloat(params.driver.location.lat), parseFloat(params.driver.location.lon));
		var restaurant = new google.maps.LatLng(parseFloat(params.restaurant.loc_lat), parseFloat(params.restaurant.loc_long));

		if (!maps[params.id]) {
			maps[params.id] = {markers: {}};
			params.scope.$on('$destroy', function() {
				service.reset(params.id);
			});
		}

		var getDirections = function() {
			// directions render
			if (maps[params.id].markers.directions){
				maps[params.id].markers.directions.setMap(null);
			}

			var dest;
			if (params.order.status.status == 'accepted' || params.order.status.status == 'transfered') {
				//dest = restaurant;
				dest = maps[params.id].markers.customerLocation;
			} else if (params.order.status.status == 'pickedup') {
				dest = maps[params.id].markers.customerLocation;
			} else if (!maps[params.id].markers.directions) {
				map.setCenter(restaurant);
			} else {
				return;
			}

			var directionsService = new google.maps.DirectionsService();
			maps[params.id].markers.directions = new google.maps.DirectionsRenderer({suppressMarkers: true});
			maps[params.id].markers.directions.setMap(map);

			var routeParams = {
				origin: driver,
				destination: dest,
				travelMode: params.driver.vehicle == 'car' ? google.maps.TravelMode.DRIVING : google.maps.TravelMode.BICYCLING
			};

			if (params.order.status.status == 'accepted' || params.order.status.status == 'transfered') {
				routeParams.waypoints = [{location: restaurant,stopover: true}];
			}

			directionsService.route(routeParams, function(response, status) {
				console.debug('Got directions response: ', response);
				params.scope.$broadcast('order-route-' + params.order.id_order, response.routes[0].legs);

				if (status === google.maps.DirectionsStatus.OK) {
					maps[params.id].markers.directions.setDirections(response);
				}
			});
		}

		// restaurant marker
		if (!maps[params.id].markers.restaurant) {
			maps[params.id].markers.restaurant = new google.maps.Marker({
				map: map,
				position: restaurant,
				zIndex: 98,
				icon: service.icon.restaurant
			});
		}

		// driver marker
		if (params.order.status.status != 'delivered') {
			if (maps[params.id].markers.driver) {
				if (maps[params.id].markers.driverLat == params.driver.location.lat && maps[params.id].markers.driverLon == params.driver.location.lon) {
					// no updates
					console.debug('No updated driver position');
					return;
				}
				maps[params.id].markers.driver.setMap(null);
				getDirections();
			}
			maps[params.id].markers.driverLat = params.driver.location.lat;
			maps[params.id].markers.driverLon = params.driver.location.lon;

			maps[params.id].markers.driver = new google.maps.Marker({
				map: map,
				position: driver,
				zIndex: 100,
				icon: params.driver.vehicle == 'car' ? service.icon.car : service.icon.bike
			});
		}

		// customer marker
		if (!maps[params.id].markers.customer) {
			var geocoder = new google.maps.Geocoder();

			geocoder.geocode({address: params.order.address}, function (results, status) {
				if (status == google.maps.GeocoderStatus.OK) {
					console.debug('Got geocoded result: ', results[0]);

					maps[params.id].markers.customerLocation = results[0].geometry.location;

					maps[params.id].markers.customer = new google.maps.Marker({
						map: map,
						position: results[0].geometry.location,
						zIndex: 99,
						icon: service.icon.customer
					});

					getDirections();
				} else {
					console.error('Could not geocode address: ', d.address);
				}
			});
		}

	};

	return service;
} );<|endoftext|>


<commit_before>/*jshint node: true, -W106 */
'use strict';

/*
* Name : legendModel.js
* Module : Lib::DataTier::LegendModel
* Location : /lib/dataTier/graph
*
* History :
*
* Version   Date         Programmer         Description
* =========================================================
* 0.0.1     2015-05-13   Filippo Rampado    Initial code
* =========================================================
*/
function LegendModel(params) {

	this._position='NE';
	this._fontColor='#000000';
	this._backgroundColor='#FFFFFF';

	if(params.position!==undefined && (
		(params.position === 'N') ||
		(params.position === 'E') ||
		(params.position === 'W') ||
		(params.position === 'S') ||
		(params.position === 'NE') ||
		(params.position === 'NW') ||
		(params.position === 'SE') ||
		(params.position === 'SW'))){
		this._position=params.position;
	}
	if(params.fontColor!==undefined && (/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(params.fontColor))){
		this._fontColor=params.fontColor;
	}
	if(params.backgroundColor!==undefined && (/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(params.backgroundColor))){
		this._backgroundColor=params.backgroundColor;
	}
}

LegendModel.prototype.getProperties=function(){
	return {
		position: this._position,
		fontColor: this._fontColor,
		backgroundColor: this._backgroundColor
	};
};

module.exports = LegendModel;<commit_msg>GraphModel test<commit_after>/*jshint node: true, -W106 */
'use strict';

/*
* Name : legendModel.js
* Module : Lib::DataTier::LegendModel
* Location : /lib/dataTier/graph
*
* History :
*
* Version   Date         Programmer         Description
* =========================================================
* 0.0.1     2015-05-13   Filippo Rampado    Initial code
* =========================================================
*/
function LegendModel(params) {

	this._position='NE';
	this._fontColor='#000000';
	this._backgroundColor='#FFFFFF';

	if(params===undefined) {
		return;
	}

	if(params.position!==undefined && (
		(params.position === 'N') ||
		(params.position === 'E') ||
		(params.position === 'W') ||
		(params.position === 'S') ||
		(params.position === 'NE') ||
		(params.position === 'NW') ||
		(params.position === 'SE') ||
		(params.position === 'SW'))){
		this._position=params.position;
	}
	if(params.fontColor!==undefined && (/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(params.fontColor))){
		this._fontColor=params.fontColor;
	}
	if(params.backgroundColor!==undefined && (/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(params.backgroundColor))){
		this._backgroundColor=params.backgroundColor;
	}
}

LegendModel.prototype.getProperties=function(){
	return {
		position: this._position,
		fontColor: this._fontColor,
		backgroundColor: this._backgroundColor
	};
};

module.exports = LegendModel;<|endoftext|>


<commit_before>var utils = require('../../utils');

module.exports = function(mongoose) {

  /**
   * Paginates and executes a query
   */
  mongoose.Query.prototype.paginate = function paginate(page, limit, callback) {

    // The number of pages to show
    page  = parseInt(page, 10) || 1;
    limit = parseInt(limit, 10) || 20;

    if(page  < 1) page = 1;
    if(limit < 1) limit = 1;

    var skip  = (page * limit) - limit;
    var query = this.skip(skip).limit(limit);

    if(!callback) return query;

    query.exec(function(fErr, result) {
      if(fErr) return callback(fErr, null, null);

      query.model.count(query._conditions).exec(function(cErr, count) {
        if(cErr) return callback(cErr, null, null);
        var totalPages = Math.ceil(count / limit);

        var info = {
          enabled: count > limit,
          items: {
            total: count,
            remaining: limit < count ? count - limit : 0,
            limit: limit
          },
          pages: {
            current: page,
            total: totalPages || 1,
            prev: page > 1 && page <= totalPages ? page - 1 : null,
            next: page < totalPages ? page + 1 : null,
            first: 1,
            last: totalPages
          }
        };

        return callback(null, result, info);
      });
    });
  };

};
<commit_msg>MongoDB: Fix pagination for last page<commit_after>var utils = require('../../utils');

module.exports = function(mongoose) {

  /**
   * Paginates and executes a query
   */
  mongoose.Query.prototype.paginate = function paginate(page, limit, callback) {

    // The number of pages to show
    page  = parseInt(page, 10) || 1;
    limit = parseInt(limit, 10) || 20;

    if(page  < 1) page = 1;
    if(limit < 1) limit = 1;

    var skip  = (page * limit) - limit;
    var query = this.skip(skip).limit(limit);

    if(!callback) return query;

    query.exec(function(fErr, result) {
      if(fErr) return callback(fErr, null, null);

      query.model.count(query._conditions).exec(function(cErr, count) {
        if(cErr) return callback(cErr, null, null);
        var totalPages = Math.ceil(count / limit);

        var info = {
          enabled: count > limit,
          items: {
            total: count,
            remaining: limit < count ? count - limit : 0,
            limit: limit
          },
          pages: {
            current: page,
            total: totalPages || 1,
            prev: page > 1 && page <= totalPages ? page - 1 : null,
            next: page < totalPages ? page + 1 : null,
            first: 1,
            last: totalPages || 1
          }
        };

        return callback(null, result, info);
      });
    });
  };

};
<|endoftext|>


<commit_before><commit_msg>added translate for missingRequiredMetafield es_ES (#3242)<commit_after><|endoftext|>


<commit_before>/*jshint camelcase: false */

/**
 * @class fileInfo
 * @classdesc fileInfo class, stores information regarding a file/folder
 * @param 	{string}	name 	name of file/folder
 * @param 	{string}	type    "file" => file ; "dir" => folder
 * @param 	{string}	attr 	attributes of file like size, time added etc.
 */
function fileInfo(name, type, attr) {
	this.name = name;
	this.type = type;
	this.fileInfo = {};

	for (var key in attr) {
		this.fileInfo[key] = attr[key];
	}
}

/**
 * Gets the name of file/folder
 * @returns 	{string}	name of file/folder
 */
fileInfo.prototype.getName = function() {
	var name = this.name.split('/');
	name = name.filter(function(n){ return n !== ''; });
	var send = name[name.length - 1];

	return send;
};

/**
 * Gets path of file/folder
 * @returns 	{string} 	Path of file/folder
 */
fileInfo.prototype.getPath = function() {
	var name = this.name.split('/');
	name = name.filter(function(n){ return n !== ''; });
	var send = '/';
	for (var i=0;i<name.length-1;i++) {
		send += name[i] + '/';
	}

	return send;
};

/**
 * Gets size of the file/folder
 * @returns 	{Number} 	Size of file/folder
 */
fileInfo.prototype.getSize = function() {
	return parseInt(this.fileInfo.getcontentlength) || null;
};

/**
 * Gets ETag of file/folder
 * @returns 	{string} 	ETag of file/folder
 */
fileInfo.prototype.getETag = function() {
	return this.fileInfo.getetag || null;
};

/**
 * Gets content-type of file/folder
 * @returns 	{string} 	content-type of file/folder
 */
fileInfo.prototype.getContentType = function() {
	var type = this.fileInfo.getcontenttype;
	if (this.isDir()) {
		type = 'httpd/unix-directory';
	}
	return type;
};

/**
 * Gets last modified time of file/folder
 * @returns 	{Number} 	Last modified time of file/folder
 */
fileInfo.prototype.getLastModified = function() {
	return new Date(this.fileInfo.getlastmodified);
};

/**
 * Checks wether the information is for a folder
 * @returns 	{boolean} 	true if folder
 */
fileInfo.prototype.isDir = function() {
	return this.type === 'dir' ? true : false;
};

module.exports = fileInfo;<commit_msg>FileInfo parsing fixed<commit_after>/*jshint camelcase: false */

/**
 * @class fileInfo
 * @classdesc fileInfo class, stores information regarding a file/folder
 * @param 	{string}	name 	name of file/folder
 * @param 	{string}	type    "file" => file ; "dir" => folder
 * @param 	{string}	attr 	attributes of file like size, time added etc.
 */
function fileInfo(name, type, attr) {
	this.name = name;
	this.type = type;
	this.fileInfo = {};

	for (var key in attr) {
		this.fileInfo[key] = attr[key];
	}
}

/**
 * Gets the name of file/folder
 * @returns 	{string}	name of file/folder
 */
fileInfo.prototype.getName = function() {
	var name = this.name.split('/');
	name = name.filter(function(n){ return n !== ''; });
	var send = name[name.length - 1];

	return send;
};

/**
 * Gets path of file/folder
 * @returns 	{string} 	Path of file/folder
 */
fileInfo.prototype.getPath = function() {
	var name = this.name.split('/');
	name = name.filter(function(n){ return n !== ''; });
	var send = '/';
	for (var i=0;i<name.length-1;i++) {
		send += name[i] + '/';
	}

	return send;
};

/**
 * Gets size of the file/folder
 * @returns 	{Number} 	Size of file/folder
 */
fileInfo.prototype.getSize = function() {
	return parseInt(this.fileInfo['d:getcontentlength']) || null;
};

/**
 * Gets ETag of file/folder
 * @returns 	{string} 	ETag of file/folder
 */
fileInfo.prototype.getETag = function() {
	return this.fileInfo.['d:getetag'] || null;
};

/**
 * Gets content-type of file/folder
 * @returns 	{string} 	content-type of file/folder
 */
fileInfo.prototype.getContentType = function() {
	var type = this.fileInfo.['d:getcontenttype'];
	if (this.isDir()) {
		type = 'httpd/unix-directory';
	}
	return type;
};

/**
 * Gets last modified time of file/folder
 * @returns 	{Number} 	Last modified time of file/folder
 */
fileInfo.prototype.getLastModified = function() {
	return new Date(this.fileInfo.['d:getlastmodified']);
};

/**
 * Checks wether the information is for a folder
 * @returns 	{boolean} 	true if folder
 */
fileInfo.prototype.isDir = function() {
	return this.type === 'dir' ? true : false;
};

module.exports = fileInfo;<|endoftext|>