<commit_before>import {
  generateGrid,
  get,
  getNeighborsGrid,
  distanceFromTo,
  getWithinGrid,
  getFromVector2d,
  hexToVector2d,
} from 'pura/hex';
import { pathTo } from 'pura/path/pathTo';
import { flatten, clear } from 'pura/array';
import { set, magnitudeSqr, addSet, subtract, subtractSet, scale, scaleSet } from 'pura/vector/tuple';
import { animateFowardNoRepeat } from 'animation';
import { easeInOutQuart } from 'easing';
import { calcWorldPosition } from 'camera';
import characterData from 'characters';

export const cameraOffset = [0, -150];

export const gridScale = 20;

export const grid = generateGrid(5);
export const optionHexes = [];
export const turnOrder = [];

export const initializeMap = (characters) => {
  console.log(`initializeMap`);
  console.log(`initializeMap: adding new turn order`);
  clear(turnOrder);
  turnOrder.push(...characters.map(([name, position]) => ([
    characterData[name], // Store Character Data
    characterData[name].maxHealth, // Set Health at start to max Health
    scaleSet(hexToVector2d(position), 20), // Set Position to a Vector instead of hex
    [], // Array of status Effects
  ])));
  console.log(`initializeMap: reset battleData`);
  // battleData = new Map(flatten(grid).map(hex => [hex, {
  //   hex,
  //   status: [],
  //   position: null,
  //   points: null,
  // }]));
  console.log(`initializeMap: Done`);
};

export const getGridHex = get(grid);
export const getHexFromVector2d = getFromVector2d(grid);
export const getGridHexFromVector2d =
  position =>
    getHexFromVector2d(scale(position, 1 / 20));
export const getGridHexFromClick =
  position =>
    getHexFromVector2d(scaleSet(calcWorldPosition(position), 1 / 20));
export const getVector2dFromHex =
  hex =>
    scaleSet(hexToVector2d(hex), 20);

export const battleData = new Map(flatten(grid).map(hex => [hex, {
  hex,
  status: [],
  position: null,
  points: null,
}]));

export const getPathToTarget = pathTo(
  getNeighborsGrid(grid),
  (_, dst) => getCharacterAtHex(dst) ? 40 : 1,
  (hex, dest) => distanceFromTo(hex, dest),
  1000
);

export const getGridHexesWithin = getWithinGrid(grid);
export const getMovementOptions =
  (position, movement) =>
    getGridHexesWithin(position, movement)
      .filter(hex => !turnOrder.find(([, health, position]) => getGridHexFromVector2d(position) === hex && health > 0));

export const getNearbyCharacters =
  (type) =>
    (position, range) =>
      turnOrder.filter(
        ([data, health, cPosition]) =>
          data.type === type &&
          health > 0 &&
          distanceFromTo(getGridHexFromVector2d(position), getGridHexFromVector2d(cPosition)) <= range
      );

export const getNearbyAllies = getNearbyCharacters(true);
export const getNearbyEnemies = getNearbyCharacters(false);

export const getCharacterAtHex =
  (hex) =>
    turnOrder.find(([, health, position]) => getGridHexFromVector2d(position) === hex && health > 0);

export const moveCharacter =
  (position, destination, duration) => {
    const start = [...position];
    const diff = subtractSet([...destination], start);
    const progress = animateFowardNoRepeat(duration);
    return () => {
      const delta = easeInOutQuart(progress());
      set(position, ...addSet(scale(diff, delta), start));
      return delta === 1;
    };
  };
<commit_msg>Remove unused methods<commit_after>import {
  generateGrid,
  get,
  getNeighborsGrid,
  distanceFromTo,
  getWithinGrid,
  getFromVector2d,
  hexToVector2d,
} from 'pura/hex';
import { pathTo } from 'pura/path/pathTo';
import { flatten, clear } from 'pura/array';
import { set, addSet, subtractSet, scale, scaleSet } from 'pura/vector/tuple';
import { animateFowardNoRepeat } from 'animation';
import { easeInOutQuart } from 'easing';
import { calcWorldPosition } from 'camera';
import characterData from 'characters';

export const cameraOffset = [0, -150];

export const gridScale = 20;

export const grid = generateGrid(5);
export const optionHexes = [];
export const turnOrder = [];

export const initializeMap = (characters) => {
  console.log(`initializeMap`);
  console.log(`initializeMap: adding new turn order`);
  clear(turnOrder);
  turnOrder.push(...characters.map(([name, position]) => ([
    characterData[name], // Store Character Data
    characterData[name].maxHealth, // Set Health at start to max Health
    scaleSet(hexToVector2d(position), 20), // Set Position to a Vector instead of hex
    [], // Array of status Effects
  ])));
  console.log(`initializeMap: reset battleData`);
  // battleData = new Map(flatten(grid).map(hex => [hex, {
  //   hex,
  //   status: [],
  //   position: null,
  //   points: null,
  // }]));
  console.log(`initializeMap: Done`);
};

export const getGridHex = get(grid);
export const getHexFromVector2d = getFromVector2d(grid);
export const getGridHexFromVector2d =
  position =>
    getHexFromVector2d(scale(position, 1 / 20));
export const getGridHexFromClick =
  position =>
    getHexFromVector2d(scaleSet(calcWorldPosition(position), 1 / 20));
export const getVector2dFromHex =
  hex =>
    scaleSet(hexToVector2d(hex), 20);

export const battleData = new Map(flatten(grid).map(hex => [hex, {
  hex,
  status: [],
  position: null,
  points: null,
}]));

export const getPathToTarget = pathTo(
  getNeighborsGrid(grid),
  (_, dst) => getCharacterAtHex(dst) ? 40 : 1,
  (hex, dest) => distanceFromTo(hex, dest),
  1000
);

export const getGridHexesWithin = getWithinGrid(grid);
export const getMovementOptions =
  (position, movement) =>
    getGridHexesWithin(position, movement)
      .filter(hex => !turnOrder.find(([, health, position]) => getGridHexFromVector2d(position) === hex && health > 0));

export const getNearbyCharacters =
  (type) =>
    (position, range) =>
      turnOrder.filter(
        ([data, health, cPosition]) =>
          data.type === type &&
          health > 0 &&
          distanceFromTo(getGridHexFromVector2d(position), getGridHexFromVector2d(cPosition)) <= range
      );

export const getNearbyAllies = getNearbyCharacters(true);
export const getNearbyEnemies = getNearbyCharacters(false);

export const getCharacterAtHex =
  (hex) =>
    turnOrder.find(([, health, position]) => getGridHexFromVector2d(position) === hex && health > 0);

export const moveCharacter =
  (position, destination, duration) => {
    const start = [...position];
    const diff = subtractSet([...destination], start);
    const progress = animateFowardNoRepeat(duration);
    return () => {
      const delta = easeInOutQuart(progress());
      set(position, ...addSet(scale(diff, delta), start));
      return delta === 1;
    };
  };
<|endoftext|>


<commit_before>var fill = fill || {};
fill.classes = fill.classes || {};

(function($){

    var DATA_REGEX = /\b([\w|-]+)\s*:\s*([\w|"|'|\*]+)\s*;?/g;

    var region = function(el, options){
        this.el = el;
        this._init(options);
    };

    region.prototype.type = "Region";

    /**
     * Initializes the Region which is pretty much just merging the
     * supplied option set with the defaults
     * @param options
     * @private
     */
    region.prototype._init = function(options){
        var str, val, contentClass, defaults;

        this._computed = {};

        //Save off the original style attributes so we can reset things properly if
        //destroy is called
        this._origStyle = this.el.attr("style");

        this.el.css( { "position" : "absolute" });

        defaults = { row : -1, col: -1,
                        rowSpan: 1, colSpan: 1,
                        contentClass : "",
                        top : false, right: false, bottom: false, left: false };
        this._properties = $.extend({}, defaults, options);

        str = this.el.data("fill");
        if (str) {
            while(null !== (match = DATA_REGEX.exec(str))){
                if (3===match.length){
                    val = match[2];
                    if (!isNaN(val))
                        val = parseInt(val, 10);
                    this._properties[match[1]] = val;
                }
            }
        }
        //alert(JSON.stringify(this._properties));
        //If the caller supplied a content class to make styling things a little easier, apply it to the region
        //wrapper here
        contentClass = "";
        if (this._properties.contentClass && "" !== this._properties.contentClass.trim())
            contentClass = this._properties.contentClass;

        //Wrap the fill region element in a div. This will allow us to apply padding to the regions and still make
        //it easy for the user to stylize the original element. Borders, for example would be applied on the outside edges
        //of the padding (negating the purpose of the padding) if we don't do this wrapping.
        this.el.wrapInner("

");
    };

    /**
     * Property getter
     */
    region.prototype.get = function(name){
        if (typeof this._computed[name] !== 'undefined')
            return(this._computed[name]);
        else if (typeof this._properties[name] !== 'undefined')
            return(this._properties[name]);
        return(null);
    };

    /**
     * Property setter
     * @param name
     * @param value
     */
    region.prototype.setComputed = function(name, value){
        this._computed[name] = value;
    };

    /**
     * Sets flags indicating if this is an edge region and which edges it lies on
     * @param top
     * @param right
     * @param bottom
     * @param left
     */
    region.prototype.setEdges = function(top, right, bottom, left){
        var removeClass;

        this._properties.top = top;
        this._properties.right = right;
        this._properties.bottom = bottom;
        this._properties.left = left;

        //Add edge classes to this top level element. This is a convenience to enable
        //users to style these regions a little easier (for example custom padding)
        this.el.addClass("fill"
                            + (top ? " fill-top" : "")
                            + (right ? " fill-right" : "")
                            + (bottom ? " fill-bottom" : "")
                            + (left ? " fill-left" : ""));

        //Remove the edge classes in case they were set previously
        removeClass = "";
        if (!top)
            removeClass += "fill-top ";
        if (!right)
            removeClass += "fill-right ";
        if (!bottom)
            removeClass += "fill-bottom ";
        if (!left)
            removeClass += "fill-left ";
        this.el.removeClass(removeClass);
    };

    /**
     * Fires a resize event if the region's width or height has changed.
     */
    region.prototype.fireResizeEvent = function(){
        var width, height;

        width = this.el.width();
        height = this.el.height();

        //Populate the event with the old dimensions before we store the new ones
        data = {
                    previous : { width: this._properties.width,
                                    height: this._properties.height },
                    current : {}
                };

        this._properties.width = width;
        this._properties.height = height;

        //Check to see if anything actually changed before firing off the resize event.
        // Also don't fire a resize event if this is the first time the width and height are
        //being set
        if (undefined !== data.previous.width && (data.previous.width !== width || data.previous.height !== height)) {

            data.current.width = width;
            data.current.height = height;

            this.el.trigger("fillresize", data);
        }

        //console.log("Row=" + this._properties.row + " Col=" + this._properties.col + " Size=" + width+"x" + height);
    };

    /**
     * Reverts the region to its original state (before the fill plugin was applied)
     */
    region.prototype.destroy = function(){

        //Remove the .fill-region-wrapper we added at init time.
        this.el.html($("> .fill-region-wrapper", this.el).html());
        //Remove the css we applied (as a style attribute) to position/size everything
        if (this._origStyle)
            this.el.attr("style", this._origStyle);
        else
            this.el.removeAttr("style");
        //Remove the convenience edge classes we may have added
        this.el.removeClass("fill fill-top fill-right fill-bottom fill-left");
    };

    fill.classes.Region = region;

})(jQuery);<commit_msg>Readded border-box sizing after refactoring how paddign is applied<commit_after>var fill = fill || {};
fill.classes = fill.classes || {};

(function($){

    var DATA_REGEX = /\b([\w|-]+)\s*:\s*([\w|"|'|\*]+)\s*;?/g;

    var region = function(el, options){
        this.el = el;
        this._init(options);
    };

    region.prototype.type = "Region";

    /**
     * Initializes the Region which is pretty much just merging the
     * supplied option set with the defaults
     * @param options
     * @private
     */
    region.prototype._init = function(options){
        var str, val, contentClass, defaults;

        this._computed = {};

        //Save off the original style attributes so we can reset things properly if
        //destroy is called
        this._origStyle = this.el.attr("style");

        this.el.css( { "position" : "absolute" });

        defaults = { row : -1, col: -1,
                        rowSpan: 1, colSpan: 1,
                        contentClass : "",
                        top : false, right: false, bottom: false, left: false };
        this._properties = $.extend({}, defaults, options);

        str = this.el.data("fill");
        if (str) {
            while(null !== (match = DATA_REGEX.exec(str))){
                if (3===match.length){
                    val = match[2];
                    if (!isNaN(val))
                        val = parseInt(val, 10);
                    this._properties[match[1]] = val;
                }
            }
        }
        //alert(JSON.stringify(this._properties));
        //If the caller supplied a content class to make styling things a little easier, apply it to the region
        //wrapper here
        contentClass = "";
        if (this._properties.contentClass && "" !== this._properties.contentClass.trim())
            contentClass = this._properties.contentClass;

        //Wrap the fill region element in a div. This will allow us to apply padding to the regions and still make
        //it easy for the user to stylize the original element. Borders, for example would be applied on the outside edges
        //of the padding (negating the purpose of the padding) if we don't do this wrapping.
        this.el.wrapInner("

");
    };

    /**
     * Property getter
     */
    region.prototype.get = function(name){
        if (typeof this._computed[name] !== 'undefined')
            return(this._computed[name]);
        else if (typeof this._properties[name] !== 'undefined')
            return(this._properties[name]);
        return(null);
    };

    /**
     * Property setter
     * @param name
     * @param value
     */
    region.prototype.setComputed = function(name, value){
        this._computed[name] = value;
    };

    /**
     * Sets flags indicating if this is an edge region and which edges it lies on
     * @param top
     * @param right
     * @param bottom
     * @param left
     */
    region.prototype.setEdges = function(top, right, bottom, left){
        var removeClass;

        this._properties.top = top;
        this._properties.right = right;
        this._properties.bottom = bottom;
        this._properties.left = left;

        //Add edge classes to this top level element. This is a convenience to enable
        //users to style these regions a little easier (for example custom padding)
        this.el.addClass("fill"
                            + (top ? " fill-top" : "")
                            + (right ? " fill-right" : "")
                            + (bottom ? " fill-bottom" : "")
                            + (left ? " fill-left" : ""));

        //Remove the edge classes in case they were set previously
        removeClass = "";
        if (!top)
            removeClass += "fill-top ";
        if (!right)
            removeClass += "fill-right ";
        if (!bottom)
            removeClass += "fill-bottom ";
        if (!left)
            removeClass += "fill-left ";
        this.el.removeClass(removeClass);
    };

    /**
     * Fires a resize event if the region's width or height has changed.
     */
    region.prototype.fireResizeEvent = function(){
        var width, height;

        width = this.el.width();
        height = this.el.height();

        //Populate the event with the old dimensions before we store the new ones
        data = {
                    previous : { width: this._properties.width,
                                    height: this._properties.height },
                    current : {}
                };

        this._properties.width = width;
        this._properties.height = height;

        //Check to see if anything actually changed before firing off the resize event.
        // Also don't fire a resize event if this is the first time the width and height are
        //being set
        if (undefined !== data.previous.width && (data.previous.width !== width || data.previous.height !== height)) {

            data.current.width = width;
            data.current.height = height;

            this.el.trigger("fillresize", data);
        }

        //console.log("Row=" + this._properties.row + " Col=" + this._properties.col + " Size=" + width+"x" + height);
    };

    /**
     * Reverts the region to its original state (before the fill plugin was applied)
     */
    region.prototype.destroy = function(){

        //Remove the .fill-region-wrapper we added at init time.
        this.el.html($("> .fill-region-wrapper", this.el).html());
        //Remove the css we applied (as a style attribute) to position/size everything
        if (this._origStyle)
            this.el.attr("style", this._origStyle);
        else
            this.el.removeAttr("style");
        //Remove the convenience edge classes we may have added
        this.el.removeClass("fill fill-top fill-right fill-bottom fill-left");
    };

    fill.classes.Region = region;

})(jQuery);<|endoftext|>


<commit_before>import * as d3 from "d3-selection";
import {transition, attrTween} from "d3-transition";
import {timeout} from "d3-timer";
import {interpolateTransformSvg} from "d3-interpolate";
import {zoomTransform} from "d3-zoom";
import {createElement, extractElementData, replaceElement} from "./element";
import {shallowCopyObject} from "./utils";
import {createZoomBehavior, getTranslatedZoomTransform, translateZoomBehaviorTransform} from "./zoom";
import {pathTween} from "./tweening";
import {isEdgeElement} from "./data";
import {isEdgeElementParent} from "./data";

export default function(callback) {

    if (this._busy) {
        this._queue.push(this.render);
        return this;
    }
    this._dispatch.call('renderStart', this);

    if (this._transitionFactory) {
        timeout(function () { // Decouple from time spent. See https://github.com/d3/d3-timer/issues/27
            this._transition = transition(this._transitionFactory());
            _render.call(this, callback);
        }.bind(this), 0);
    } else {
        _render.call(this, callback);
    }
    return this;
}

function _render(callback) {

    var transitionInstance = this._transition;
    var fade = this._fade && transitionInstance != null;
    var tweenPaths = this._tweenPaths;
    var tweenShapes = this._tweenShapes;
    var convertEqualSidedPolygons = this._convertEqualSidedPolygons;
    var tweenPrecision = this._tweenPrecision;
    var growEnteringEdges = this._growEnteringEdges && transitionInstance != null;
    var attributer = this._attributer;
    var graphvizInstance = this;

    function insertSvg(element) {
        var children = element.selectAll(function () {
            return element.node().childNodes;
        });

        children = children
          .data(function (d) {
              return d.children;
          }, function (d) {
              return d.key;
          });
        var childrenEnter = children
          .enter()
          .append(function(d) {
              var element = createElement(d);
              if (d.tag == '#text' && fade) {
                  element.nodeValue = d.text;
              }
              return element;
          });

        if (fade || (growEnteringEdges && isEdgeElementParent(element.datum()))) {
            var childElementsEnter = childrenEnter
                .filter(function(d) {
                    return d.tag[0] == '#' ? null : this;
                })
                .each(function (d) {
                    var childEnter = d3.select(this);
                    for (var attributeName of Object.keys(d.attributes)) {
                        var attributeValue = d.attributes[attributeName];
                        childEnter
                            .attr(attributeName, attributeValue);
                    }
                });
            childElementsEnter
              .filter(function(d) {
                    return d.tag == 'svg' || d.tag == 'g' ? null : this;
              })
                .style("opacity", 0.0);
        }
        var childrenExit = children
          .exit();
        if (attributer) {
            childrenExit.each(attributer);
        }
        if (transitionInstance) {
            childrenExit = childrenExit
                .transition(transitionInstance);
            if (fade) {
                childrenExit
                  .filter(function(d) {
                      return d.tag[0] == '#' ? null : this;
                  })
                    .style("opacity", 0.0);
            }
        }
        childrenExit = childrenExit
            .remove()
        children = childrenEnter
            .merge(children);
        children.each(function(childData) {
            attributeElement.call(this, childData);
        });
    }

    function attributeElement(childData) {
        var child = d3.select(this);
        if (attributer) {
            child.each(attributer);
        }
        var tag = childData.tag;
        var attributes = childData.attributes;
        var convertShape = false;
        if (tweenShapes && transitionInstance && childData.alternativeOld) {
            if (this.nodeName == 'polygon' || this.nodeName == 'ellipse') {
                convertShape = true;
                var prevData = extractElementData(child);
                if (this.nodeName == 'polygon' && tag == 'polygon') {
                    var prevPoints = prevData.attributes.points;
                    if (prevPoints == null) {
                        convertShape = false;
                    } else if (!convertEqualSidedPolygons) {
                        var nPrevPoints = prevPoints.split(' ').length;
                        var points = childData.attributes.points;
                        var nPoints = points.split(' ').length;
                        if (nPoints == nPrevPoints) {
                            convertShape = false;
                        }
                    }
                } else if (this.nodeName == 'ellipse' && tag == 'ellipse') {
                    convertShape = false;
                }
            }
            if (convertShape) {
                var prevPathData = childData.alternativeOld;
                var pathElement = replaceElement(child, prevPathData);
                pathElement.data([childData], function () {
                    return childData.key;
                });
                var newPathData = childData.alternativeNew;
                child = pathElement;
                tag = 'path';
                attributes = newPathData.attributes;
            }
        }
        var childTransition = child;
        if (transitionInstance) {
            childTransition = childTransition
                .transition(transitionInstance);
            if (fade) {
                childTransition
                  .filter(function(d) {
                      return d.tag[0] == '#' ? null : this;
                  })
                    .style("opacity", 1.0);
            }
            childTransition
              .filter(function(d) {
                  return d.tag[0] == '#' ? null : this;
              })
                .on("end", function() {
                    d3.select(this)
                        .attr('style', null);
                });
        }
        var growThisPath = growEnteringEdges && tag == 'path' && childData.offset;
        if (growThisPath) {
            var totalLength = childData.totalLength;
            child
                .attr("stroke-dasharray", totalLength + " " + totalLength)
                .attr("stroke-dashoffset", totalLength)
                .attr('transform', 'translate(' + childData.offset.x + ',' + childData.offset.y + ')');
            childTransition
                .attr("stroke-dashoffset", 0)
                .attr('transform', 'translate(0,0)')
                .on("start", function() {
                    d3.select(this)
                        .style('opacity', null);
                })
                .on("end", function() {
                    d3.select(this)
                        .attr('stroke-dashoffset', null)
                        .attr('stroke-dasharray', null)
                        .attr('transform', null);
                });
        }
        var moveThisPolygon = growEnteringEdges && tag == 'polygon' && isEdgeElement(childData) && childData.offset;
        if (moveThisPolygon) {
            var edgePath = d3.select(child.node().parentNode.querySelector("path"));
            if (edgePath.node().getPointAtLength) {
                var p0 = edgePath.node().getPointAtLength(0);
                var p1 = edgePath.node().getPointAtLength(childData.totalLength);
                var p2 = edgePath.node().getPointAtLength(childData.totalLength - 1);
                var angle1 = Math.atan2(p1.y - p2.y, p1.x - p2.x) * 180 / Math.PI;
            } else { // Test workaround until https://github.com/tmpvar/jsdom/issues/1330 is fixed
                var p0 = {x: 0, y: 0};
                var p1 = {x: 100, y: 100};
                var angle1 = 0;
            }
            var x = p0.x - p1.x + childData.offset.x;
            var y = p0.y - p1.y + childData.offset.y;
            child
                .attr('transform', 'translate(' + x + ',' + y + ')');
            childTransition
                .attrTween("transform", function () {
                    return function (t) {
                        if (edgePath.node().getPointAtLength) {
                            var p = edgePath.node().getPointAtLength(childData.totalLength * t);
                            var p2 = edgePath.node().getPointAtLength(childData.totalLength * t + 1);
                            var angle = Math.atan2(p2.y - p.y, p2.x - p.x) * 180 / Math.PI - angle1;
                        } else { // Test workaround until https://github.com/tmpvar/jsdom/issues/1330 is fixed
                            var p = {x: 100.0 * t, y: 100.0 *t};
                            var angle = 0;
                        }
                        x = p.x - p1.x + childData.offset.x * (1 - t);
                        y = p.y - p1.y + childData.offset.y * (1 - t);
                        return 'translate(' + x + ',' + y + ') rotate(' + angle + ' ' + p1.x + ' ' + p1.y + ')';
                    }
                })
                .on("start", function() {
                    d3.select(this)
                        .style('opacity', null);
                })
                .on("end", function() {
                    d3.select(this).attr('transform', null);
                });
        }
        var tweenThisPath = tweenPaths && transitionInstance && tag == 'path' && child.attr('d') != null;
        for (var attributeName of Object.keys(attributes)) {
            var attributeValue = attributes[attributeName];
            if (tweenThisPath && attributeName == 'd') {
                var points = (childData.alternativeOld || childData).points;
                if (points) {
                    childTransition
                        .attrTween("d", pathTween(points, attributeValue));
                }
            } else {
                if (attributeName == 'transform' && childData.translation) {
                    childTransition
                        .on("start", function () {
                            if (graphvizInstance._zoomBehavior) {
                                // Update the transform to transition to just before the transition starts
                                // in order to catch changes between the transition scheduling to its start.
                                childTransition
                                    .tween("attr.transform", function() {
                                        var node = this;
                                        return function(t) {
                                            node.setAttribute("transform", interpolateTransformSvg(zoomTransform(graphvizInstance._zoomSelection.node()).toString(), getTranslatedZoomTransform.call(graphvizInstance, child).toString())(t));
                                        };
                                    });
                            }
                        })
                        .on("end", function () {
                            // Update the zoom transform to the new translated transform
                            if (graphvizInstance._zoomBehavior) {
                                translateZoomBehaviorTransform.call(graphvizInstance, child);
                            }
                        })
                }
                childTransition
                    .attr(attributeName, attributeValue);
            }
        }
        if (convertShape) {
            childTransition
                .on("end", function (d, i, nodes) {
                    if (this.nodeName != d.tag) {
                        pathElement = d3.select(this);
                        var newElement = replaceElement(pathElement, d);
                        newElement.data([d], function () {
                            return d.key;
                        });
                    }
                })
        }
        if (childData.text) {
            childTransition
                .text(childData.text);
        }
        insertSvg(child);
    }

    var root = this._selection;

    if (transitionInstance != null) {
        // Ensure orignal SVG shape elements are restored after transition before rendering new graph
        var jobs = this._jobs;
        if (graphvizInstance._active) {
            jobs.push(null);
            return this;
        } else {
            root
              .transition(transitionInstance)
              .transition()
                .duration(0)
                .on("end" , function () {
                    graphvizInstance._active = false;
                    if (jobs.length != 0) {
                        jobs.shift();
                        graphvizInstance.render();
                    }
                });
            this._active = true;
        }
    }

    if (transitionInstance != null) {
        root
          .transition(transitionInstance)
            .on("start" , function () {
                graphvizInstance._dispatch.call('transitionStart', graphvizInstance);
            })
            .on("end" , function () {
                graphvizInstance._dispatch.call('transitionEnd', graphvizInstance);
            })
          .transition()
            .duration(0)
            .on("start" , function () {
                graphvizInstance._dispatch.call('restoreEnd', graphvizInstance);
                graphvizInstance._dispatch.call('end', graphvizInstance);
                if (callback) {
                    callback.call(graphvizInstance);
                }
            });
    }

    var data = this._data;

    root
        .datum({attributes: {}, children: [data]});
    insertSvg(root);

    if (this._zoom && !this._zoomBehavior) {
        createZoomBehavior.call(this);
    }

    graphvizInstance._dispatch.call('renderEnd', graphvizInstance);

    if (transitionInstance == null) {
        this._dispatch.call('end', this);
        if (callback) {
            callback.call(this);
        }
    }

    return this;
};
<commit_msg>Refactor: simplify call to attributing function<commit_after>import * as d3 from "d3-selection";
import {transition, attrTween} from "d3-transition";
import {timeout} from "d3-timer";
import {interpolateTransformSvg} from "d3-interpolate";
import {zoomTransform} from "d3-zoom";
import {createElement, extractElementData, replaceElement} from "./element";
import {shallowCopyObject} from "./utils";
import {createZoomBehavior, getTranslatedZoomTransform, translateZoomBehaviorTransform} from "./zoom";
import {pathTween} from "./tweening";
import {isEdgeElement} from "./data";
import {isEdgeElementParent} from "./data";

export default function(callback) {

    if (this._busy) {
        this._queue.push(this.render);
        return this;
    }
    this._dispatch.call('renderStart', this);

    if (this._transitionFactory) {
        timeout(function () { // Decouple from time spent. See https://github.com/d3/d3-timer/issues/27
            this._transition = transition(this._transitionFactory());
            _render.call(this, callback);
        }.bind(this), 0);
    } else {
        _render.call(this, callback);
    }
    return this;
}

function _render(callback) {

    var transitionInstance = this._transition;
    var fade = this._fade && transitionInstance != null;
    var tweenPaths = this._tweenPaths;
    var tweenShapes = this._tweenShapes;
    var convertEqualSidedPolygons = this._convertEqualSidedPolygons;
    var tweenPrecision = this._tweenPrecision;
    var growEnteringEdges = this._growEnteringEdges && transitionInstance != null;
    var attributer = this._attributer;
    var graphvizInstance = this;

    function insertSvg(element) {
        var children = element.selectAll(function () {
            return element.node().childNodes;
        });

        children = children
          .data(function (d) {
              return d.children;
          }, function (d) {
              return d.key;
          });
        var childrenEnter = children
          .enter()
          .append(function(d) {
              var element = createElement(d);
              if (d.tag == '#text' && fade) {
                  element.nodeValue = d.text;
              }
              return element;
          });

        if (fade || (growEnteringEdges && isEdgeElementParent(element.datum()))) {
            var childElementsEnter = childrenEnter
                .filter(function(d) {
                    return d.tag[0] == '#' ? null : this;
                })
                .each(function (d) {
                    var childEnter = d3.select(this);
                    for (var attributeName of Object.keys(d.attributes)) {
                        var attributeValue = d.attributes[attributeName];
                        childEnter
                            .attr(attributeName, attributeValue);
                    }
                });
            childElementsEnter
              .filter(function(d) {
                    return d.tag == 'svg' || d.tag == 'g' ? null : this;
              })
                .style("opacity", 0.0);
        }
        var childrenExit = children
          .exit();
        if (attributer) {
            childrenExit.each(attributer);
        }
        if (transitionInstance) {
            childrenExit = childrenExit
                .transition(transitionInstance);
            if (fade) {
                childrenExit
                  .filter(function(d) {
                      return d.tag[0] == '#' ? null : this;
                  })
                    .style("opacity", 0.0);
            }
        }
        childrenExit = childrenExit
            .remove()
        children = childrenEnter
            .merge(children);
        children.each(attributeElement);
    }

    function attributeElement(childData) {
        var child = d3.select(this);
        if (attributer) {
            child.each(attributer);
        }
        var tag = childData.tag;
        var attributes = childData.attributes;
        var convertShape = false;
        if (tweenShapes && transitionInstance && childData.alternativeOld) {
            if (this.nodeName == 'polygon' || this.nodeName == 'ellipse') {
                convertShape = true;
                var prevData = extractElementData(child);
                if (this.nodeName == 'polygon' && tag == 'polygon') {
                    var prevPoints = prevData.attributes.points;
                    if (prevPoints == null) {
                        convertShape = false;
                    } else if (!convertEqualSidedPolygons) {
                        var nPrevPoints = prevPoints.split(' ').length;
                        var points = childData.attributes.points;
                        var nPoints = points.split(' ').length;
                        if (nPoints == nPrevPoints) {
                            convertShape = false;
                        }
                    }
                } else if (this.nodeName == 'ellipse' && tag == 'ellipse') {
                    convertShape = false;
                }
            }
            if (convertShape) {
                var prevPathData = childData.alternativeOld;
                var pathElement = replaceElement(child, prevPathData);
                pathElement.data([childData], function () {
                    return childData.key;
                });
                var newPathData = childData.alternativeNew;
                child = pathElement;
                tag = 'path';
                attributes = newPathData.attributes;
            }
        }
        var childTransition = child;
        if (transitionInstance) {
            childTransition = childTransition
                .transition(transitionInstance);
            if (fade) {
                childTransition
                  .filter(function(d) {
                      return d.tag[0] == '#' ? null : this;
                  })
                    .style("opacity", 1.0);
            }
            childTransition
              .filter(function(d) {
                  return d.tag[0] == '#' ? null : this;
              })
                .on("end", function() {
                    d3.select(this)
                        .attr('style', null);
                });
        }
        var growThisPath = growEnteringEdges && tag == 'path' && childData.offset;
        if (growThisPath) {
            var totalLength = childData.totalLength;
            child
                .attr("stroke-dasharray", totalLength + " " + totalLength)
                .attr("stroke-dashoffset", totalLength)
                .attr('transform', 'translate(' + childData.offset.x + ',' + childData.offset.y + ')');
            childTransition
                .attr("stroke-dashoffset", 0)
                .attr('transform', 'translate(0,0)')
                .on("start", function() {
                    d3.select(this)
                        .style('opacity', null);
                })
                .on("end", function() {
                    d3.select(this)
                        .attr('stroke-dashoffset', null)
                        .attr('stroke-dasharray', null)
                        .attr('transform', null);
                });
        }
        var moveThisPolygon = growEnteringEdges && tag == 'polygon' && isEdgeElement(childData) && childData.offset;
        if (moveThisPolygon) {
            var edgePath = d3.select(child.node().parentNode.querySelector("path"));
            if (edgePath.node().getPointAtLength) {
                var p0 = edgePath.node().getPointAtLength(0);
                var p1 = edgePath.node().getPointAtLength(childData.totalLength);
                var p2 = edgePath.node().getPointAtLength(childData.totalLength - 1);
                var angle1 = Math.atan2(p1.y - p2.y, p1.x - p2.x) * 180 / Math.PI;
            } else { // Test workaround until https://github.com/tmpvar/jsdom/issues/1330 is fixed
                var p0 = {x: 0, y: 0};
                var p1 = {x: 100, y: 100};
                var angle1 = 0;
            }
            var x = p0.x - p1.x + childData.offset.x;
            var y = p0.y - p1.y + childData.offset.y;
            child
                .attr('transform', 'translate(' + x + ',' + y + ')');
            childTransition
                .attrTween("transform", function () {
                    return function (t) {
                        if (edgePath.node().getPointAtLength) {
                            var p = edgePath.node().getPointAtLength(childData.totalLength * t);
                            var p2 = edgePath.node().getPointAtLength(childData.totalLength * t + 1);
                            var angle = Math.atan2(p2.y - p.y, p2.x - p.x) * 180 / Math.PI - angle1;
                        } else { // Test workaround until https://github.com/tmpvar/jsdom/issues/1330 is fixed
                            var p = {x: 100.0 * t, y: 100.0 *t};
                            var angle = 0;
                        }
                        x = p.x - p1.x + childData.offset.x * (1 - t);
                        y = p.y - p1.y + childData.offset.y * (1 - t);
                        return 'translate(' + x + ',' + y + ') rotate(' + angle + ' ' + p1.x + ' ' + p1.y + ')';
                    }
                })
                .on("start", function() {
                    d3.select(this)
                        .style('opacity', null);
                })
                .on("end", function() {
                    d3.select(this).attr('transform', null);
                });
        }
        var tweenThisPath = tweenPaths && transitionInstance && tag == 'path' && child.attr('d') != null;
        for (var attributeName of Object.keys(attributes)) {
            var attributeValue = attributes[attributeName];
            if (tweenThisPath && attributeName == 'd') {
                var points = (childData.alternativeOld || childData).points;
                if (points) {
                    childTransition
                        .attrTween("d", pathTween(points, attributeValue));
                }
            } else {
                if (attributeName == 'transform' && childData.translation) {
                    childTransition
                        .on("start", function () {
                            if (graphvizInstance._zoomBehavior) {
                                // Update the transform to transition to just before the transition starts
                                // in order to catch changes between the transition scheduling to its start.
                                childTransition
                                    .tween("attr.transform", function() {
                                        var node = this;
                                        return function(t) {
                                            node.setAttribute("transform", interpolateTransformSvg(zoomTransform(graphvizInstance._zoomSelection.node()).toString(), getTranslatedZoomTransform.call(graphvizInstance, child).toString())(t));
                                        };
                                    });
                            }
                        })
                        .on("end", function () {
                            // Update the zoom transform to the new translated transform
                            if (graphvizInstance._zoomBehavior) {
                                translateZoomBehaviorTransform.call(graphvizInstance, child);
                            }
                        })
                }
                childTransition
                    .attr(attributeName, attributeValue);
            }
        }
        if (convertShape) {
            childTransition
                .on("end", function (d, i, nodes) {
                    if (this.nodeName != d.tag) {
                        pathElement = d3.select(this);
                        var newElement = replaceElement(pathElement, d);
                        newElement.data([d], function () {
                            return d.key;
                        });
                    }
                })
        }
        if (childData.text) {
            childTransition
                .text(childData.text);
        }
        insertSvg(child);
    }

    var root = this._selection;

    if (transitionInstance != null) {
        // Ensure orignal SVG shape elements are restored after transition before rendering new graph
        var jobs = this._jobs;
        if (graphvizInstance._active) {
            jobs.push(null);
            return this;
        } else {
            root
              .transition(transitionInstance)
              .transition()
                .duration(0)
                .on("end" , function () {
                    graphvizInstance._active = false;
                    if (jobs.length != 0) {
                        jobs.shift();
                        graphvizInstance.render();
                    }
                });
            this._active = true;
        }
    }

    if (transitionInstance != null) {
        root
          .transition(transitionInstance)
            .on("start" , function () {
                graphvizInstance._dispatch.call('transitionStart', graphvizInstance);
            })
            .on("end" , function () {
                graphvizInstance._dispatch.call('transitionEnd', graphvizInstance);
            })
          .transition()
            .duration(0)
            .on("start" , function () {
                graphvizInstance._dispatch.call('restoreEnd', graphvizInstance);
                graphvizInstance._dispatch.call('end', graphvizInstance);
                if (callback) {
                    callback.call(graphvizInstance);
                }
            });
    }

    var data = this._data;

    root
        .datum({attributes: {}, children: [data]});
    insertSvg(root);

    if (this._zoom && !this._zoomBehavior) {
        createZoomBehavior.call(this);
    }

    graphvizInstance._dispatch.call('renderEnd', graphvizInstance);

    if (transitionInstance == null) {
        this._dispatch.call('end', this);
        if (callback) {
            callback.call(this);
        }
    }

    return this;
};
<|endoftext|>


<commit_before>var R = _.repeat = {
    id: 'x-repeat-id',
    each: 'x-repeat-each',
    context: 'html,[x-repeat-init]',
    count: 0,
    initAll: function() {
        D.queryAll(R.context).each(function(context) {
            var init = context.getAttribute('x-repeat-init') || 'DOMContentLoaded',
                listener = function() {
                    D.removeEventListener(init, listener);
                    context.queryAll('[x-repeat]')
                           .not('['+R.id+']')
                           .each(R.init);
                };
            if (init !== 'true') {
                context.setAttribute('x-repeat-init', 'true');
                D.addEventListener(init, listener);
            }
        });
    },
    init: function(el, keep) {
        var selector = el.getAttribute('x-repeat'),
            id = R.count++,
            content = selector && D.query(selector).cloneNode(true) || el,
            anchor = D.createElement('x-repeat');
        content.setAttribute(R.id, id);
        anchor.setAttribute(R.id, id);
        for (var i=0,m=el.attributes.length; i<m; i++) {
            var attr = el.attributes[i];
            if (attr.name === 'x-repeat-none') {
                anchor.value = attr.value || el.innerHTML;
            }
            anchor.setAttribute(attr.name, attr.value);
        }
        R.parent(el).insertBefore(anchor, el.nextSibling);
        _.defprop(anchor, 'content', R[id] = content);
        if (keep !== true) {
            el.remove();
        }
        return id;
    },
    parent: function(el) {
        if (!el.parentNode) {
            D.createDocumentFragment().appendChild(el);
        }
        return el.parentNode;
    },
    repeat: function(parent, anchor, content, val) {
        var repeat = content.cloneNode(true);
        if (val !== undefined && val !== null) {
            repeat.xValue = val;
        }
        parent.insertBefore(repeat, anchor);
        if (repeat.hasAttribute(R.each)) {
            repeat.getAttribute(R.each)
                .split(',')
                .forEach(function(call) {
                    _.resolve(call, window, [repeat, val]);
                });
        }
        return repeat;
    },
    style: D.head.append('style')
};

X.add('repeat', function repeat(val) {
    var parent = R.parent(this),
        id = this.getAttribute(R.id) || R.init(this, true),
        selector = '['+R.id+'="'+id+'"]',
        selectAll = selector+':not(x-repeat)';
    if (val === false) {
        return parent.queryAll(selectAll).remove();
    }
    var anchor = parent.query('x-repeat'+selector),
        content = anchor.content || R[id];
    if (anchor.hasAttribute('x-repeat-first')) {
        anchor = parent.query(selector+'[x-index]') || anchor;
    }
    var ret = Array.isArray(val) ?
        val.map(function(v){ return R.repeat(parent, anchor, content, v); }) :
        R.repeat(parent, anchor, content, val);
    parent.queryAll(selectAll).each('setAttribute', 'x-index', '${i}');
    return ret;
}, [Element]);

R.style.textContent = '[x-repeat] { display: none }';
R.initAll();//early availability
D.addEventListener('DOMContentLoaded', function() {
    R.initAll();//eventual consistency
    R.style.textContent = "\nx-repeat { display: none }"+
                          "\nx-repeat[x-repeat-none] { display: inline-block; }"+
                          "\n["+R.id+"] + x-repeat[x-repeat-none] { display: none; }";
});
<commit_msg>be more independent and timely with head style insertion<commit_after>var R = _.repeat = {
    id: 'x-repeat-id',
    each: 'x-repeat-each',
    context: 'html,[x-repeat-init]',
    count: 0,
    initAll: function() {
        D.queryAll(R.context).each(function(context) {
            var init = context.getAttribute('x-repeat-init') || 'DOMContentLoaded',
                listener = function() {
                    D.removeEventListener(init, listener);
                    context.queryAll('[x-repeat]')
                           .not('['+R.id+']')
                           .each(R.init);
                };
            if (init !== 'true') {
                context.setAttribute('x-repeat-init', 'true');
                D.addEventListener(init, listener);
            }
        });
    },
    init: function(el, keep) {
        var selector = el.getAttribute('x-repeat'),
            id = R.count++,
            content = selector && D.query(selector).cloneNode(true) || el,
            anchor = D.createElement('x-repeat');
        content.setAttribute(R.id, id);
        anchor.setAttribute(R.id, id);
        for (var i=0,m=el.attributes.length; i<m; i++) {
            var attr = el.attributes[i];
            if (attr.name === 'x-repeat-none') {
                anchor.value = attr.value || el.innerHTML;
            }
            anchor.setAttribute(attr.name, attr.value);
        }
        R.parent(el).insertBefore(anchor, el.nextSibling);
        _.defprop(anchor, 'content', R[id] = content);
        if (keep !== true) {
            el.remove();
        }
        return id;
    },
    parent: function(el) {
        if (!el.parentNode) {
            D.createDocumentFragment().appendChild(el);
        }
        return el.parentNode;
    },
    repeat: function(parent, anchor, content, val) {
        var repeat = content.cloneNode(true);
        if (val !== undefined && val !== null) {
            repeat.xValue = val;
        }
        parent.insertBefore(repeat, anchor);
        if (repeat.hasAttribute(R.each)) {
            repeat.getAttribute(R.each)
                .split(',')
                .forEach(function(call) {
                    _.resolve(call, window, [repeat, val]);
                });
        }
        return repeat;
    },
    style: D.createElement('style')
};

X.add('repeat', function repeat(val) {
    var parent = R.parent(this),
        id = this.getAttribute(R.id) || R.init(this, true),
        selector = '['+R.id+'="'+id+'"]',
        selectAll = selector+':not(x-repeat)';
    if (val === false) {
        return parent.queryAll(selectAll).remove();
    }
    var anchor = parent.query('x-repeat'+selector),
        content = anchor.content || R[id];
    if (anchor.hasAttribute('x-repeat-first')) {
        anchor = parent.query(selector+'[x-index]') || anchor;
    }
    var ret = Array.isArray(val) ?
        val.map(function(v){ return R.repeat(parent, anchor, content, v); }) :
        R.repeat(parent, anchor, content, val);
    parent.queryAll(selectAll).each('setAttribute', 'x-index', '${i}');
    return ret;
}, [Element]);

R.style.textContent = '[x-repeat] { display: none }';
D.head.appendChild(R.style);
R.initAll();//early availability
D.addEventListener('DOMContentLoaded', function() {
    R.initAll();//eventual consistency
    R.style.textContent = "\nx-repeat { display: none }"+
                          "\nx-repeat[x-repeat-none] { display: inline-block; }"+
                          "\n["+R.id+"] + x-repeat[x-repeat-none] { display: none; }";
});
<|endoftext|>


<commit_before>/**
 * TODO: Better Docs -- TomF is a terrible person
 * @desc report() sends a errors back to GA as events for wallboards
 *
 * @param {String} idx - idx sent as event action
 * @param {Error} args - concatenated and reported args
 *
 * @return {undefined}
 */

const UA = 'UA-33947856-2';
const endpoint = 'https://ssl.google-analytics.com/collect?';
import log from './log';

function report(idx, ...errors) {
  try {
    const query = [];
    const error = errors.join(' - ');
    const params = {
      v: 1,
      cid: getUID().toString(),
      tid: UA,
      t: 'event',
      ec: location.hostname,
      ea: idx.toString(),
      el: error,
      z: (new Date()).getTime(),
    };
    Object.keys(params).forEach(function(key) {
      let value = params[key];
      query.push(key + '=' + encodeURIComponent(value));
    });
    const src = endpoint + query.join('&');
    new Image().src = src;
    log('reported:', error, src);
  } catch (e) {}
}

export default report;

/*jshint latedef:false*/
function getUID() {
  const cookie = /(optimizelyEndUserId|mt\.v)=([^;]+)/;
  let uid = (new Date()).getTime();
  try {
    uid = cookie.exec(document.cookie)[2];
  } catch (e) {}
  uid = uid.replace(/[^\d\s]/g, '');
  return uid;
}
<commit_msg>Update report.js<commit_after>/**
 * @desc report() sends a errors back to GA as events for wallboards
 *                why a module? b/c not all clients load window.ga so
 *                this just reverse engineers the endpoint using a beacon
 *
 * @param {String} idx - idx sent as event action
 * @param {Error} args - concatenated and reported args
 *
 * @return {undefined}
 */

const UA = 'UA-33947856-2';
const endpoint = 'https://ssl.google-analytics.com/collect?';
import log from './log';

function report(idx, ...errors) {
  try {
    const query = [];
    const error = errors.join(' - ');
    const params = {
      v: 1,
      cid: getUID().toString(),
      tid: UA,
      t: 'event',
      ec: location.hostname,
      ea: idx.toString(),
      el: error,
      z: (new Date()).getTime(),
    };
    Object.keys(params).forEach(function(key) {
      let value = params[key];
      query.push(key + '=' + encodeURIComponent(value));
    });
    const src = endpoint + query.join('&');
    new Image().src = src;
    log('reported:', error, src);
  } catch (e) {}
}

export default report;

/*jshint latedef:false*/
function getUID() {
  const cookie = /(optimizelyEndUserId|mt\.v)=([^;]+)/;
  let uid = (new Date()).getTime();
  try {
    uid = cookie.exec(document.cookie)[2];
  } catch (e) {}
  uid = uid.replace(/[^\d\s]/g, '');
  return uid;
}
<|endoftext|>


<commit_before>import * as ACTION_TYPES from '../../src/constants/action_types'
import { camelizeKeys } from 'humps'
import { s3CredentialsPath } from '../networking/api'
import 'isomorphic-fetch'

function checkStatus(response) {
  if (response.status >= 200 && response.status < 300) {
    return response
  }
  const error = new Error(response.statusText)
  error.response = response
  throw error
}

function parseJSON(response) {
  return (response.status === 200) ? response.json() : response
}

function imageGuid() {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
    const r = Math.random() * 16 | 0;
    const v = (c === 'x' ? r : r & 0x3 | 0x8);
    return v.toString(16)
  })
}

function getFilename(type) {
  return 'ello-' + imageGuid() + type.replace('image/', '.')
}

function getFileKey(prefix, filename) {
  return prefix + '/' + encodeURIComponent(filename)
}

function getAssetUrl(endpoint, key) {
  return endpoint + '/' + key
}

function getUploadData(key, credentials, file) {
  const data = new FormData()
  data.append('key', key)
  data.append('AWSAccessKeyId', credentials.access_key)
  data.append('acl', 'public-read')
  data.append('success_action_status', '201')
  data.append('policy', credentials.policy)
  data.append('signature', credentials.signature)
  data.append('Content-Type', file.type)
  data.append('file', file)
  return data
}

function getCredentialsHeader() {
  return {
    'Authorization': `Bearer ${localStorage.getItem('ello_access_token')}`,
    'Accept': 'application/json',
    'Content-Type': 'application/json',
  }
}

export function uploader() {
  return next => action => {
    const { payload, type, meta } = action

    // This is problematic... :(
    if ((type !== ACTION_TYPES.PROFILE.SAVE_AVATAR &&
         type !== ACTION_TYPES.PROFILE.SAVE_COVER
        ) || !payload) {
      return next(action)
    }

    const { endpoint, file } = payload

    if (!endpoint) return next(action);

    let assetUrl
    const REQUEST = type + '_REQUEST'
    const SUCCESS = type + '_SUCCESS'
    const FAILURE = type + '_FAILURE'

    // dispatch the start of the request
    next({ type: REQUEST, payload, meta: meta })

    function fetchCredentials() {
      return fetch(s3CredentialsPath().path, {
        method: 'GET',
        headers: getCredentialsHeader(),
      })
        .then(checkStatus)
        .then(parseJSON)
    }

    function postAsset(response) {
      const { credentials } = response
      const filename = getFilename(file.type)
      const key = getFileKey(credentials.prefix, filename)
      assetUrl = getAssetUrl(credentials.endpoint, key)

      return fetch(credentials.endpoint, {
        method: 'POST',
        body: getUploadData(key, credentials, file),
      })
        .then(checkStatus)
    }

    function saveLocationToApi() {
      const vo = (type === ACTION_TYPES.PROFILE.SAVE_AVATAR) ? { remote_avatar_url: assetUrl } : { remote_cover_image_url: assetUrl }
      return fetch(endpoint.path, {
        method: 'PATCH',
        headers: getCredentialsHeader(),
        body: JSON.stringify(vo),
      })
        .then(checkStatus)
        .then(parseJSON)
    }

    return (
      fetchCredentials()
      .then(postAsset)
      .then(saveLocationToApi)
      .then(response => {
        payload.response = camelizeKeys(response)
        next({ meta, payload, type: SUCCESS })
        return true
      })
      .catch(error => {
        next({ error, meta, payload, type: FAILURE })
        return false
      })
    )
  }
}

<commit_msg>Fix the authentication for uploads<commit_after>import * as ACTION_TYPES from '../../src/constants/action_types'
import { camelizeKeys } from 'humps'
import { s3CredentialsPath } from '../networking/api'
import 'isomorphic-fetch'

function checkStatus(response) {
  if (response.status >= 200 && response.status < 300) {
    return response
  }
  const error = new Error(response.statusText)
  error.response = response
  throw error
}

function parseJSON(response) {
  return (response.status === 200) ? response.json() : response
}

function imageGuid() {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
    const r = Math.random() * 16 | 0;
    const v = (c === 'x' ? r : r & 0x3 | 0x8);
    return v.toString(16)
  })
}

function getFilename(type) {
  return 'ello-' + imageGuid() + type.replace('image/', '.')
}

function getFileKey(prefix, filename) {
  return prefix + '/' + encodeURIComponent(filename)
}

function getAssetUrl(endpoint, key) {
  return endpoint + '/' + key
}

function getUploadData(key, credentials, file) {
  const data = new FormData()
  data.append('key', key)
  data.append('AWSAccessKeyId', credentials.access_key)
  data.append('acl', 'public-read')
  data.append('success_action_status', '201')
  data.append('policy', credentials.policy)
  data.append('signature', credentials.signature)
  data.append('Content-Type', file.type)
  data.append('file', file)
  return data
}

function getCredentialsHeader(accessToken) {
  return {
    'Authorization': `Bearer ${accessToken}`,
    'Accept': 'application/json',
    'Content-Type': 'application/json',
  }
}

export const uploader = store => next => action => {
  const { payload, type, meta } = action

  // This is problematic... :(
  if ((type !== ACTION_TYPES.PROFILE.SAVE_AVATAR &&
        type !== ACTION_TYPES.PROFILE.SAVE_COVER
      ) || !payload) {
    return next(action)
  }

  const { endpoint, file } = payload

  if (!endpoint) return next(action);

  let assetUrl
  const REQUEST = type + '_REQUEST'
  const SUCCESS = type + '_SUCCESS'
  const FAILURE = type + '_FAILURE'

  // dispatch the start of the request
  next({ type: REQUEST, payload, meta: meta })
  const state = store.getState()
  const accessToken = state.accessToken.token
  function fetchCredentials() {
    return fetch(s3CredentialsPath().path, {
      method: 'GET',
      headers: getCredentialsHeader(accessToken),
    })
      .then(checkStatus)
      .then(parseJSON)
  }

  function postAsset(response) {
    const { credentials } = response
    const filename = getFilename(file.type)
    const key = getFileKey(credentials.prefix, filename)
    assetUrl = getAssetUrl(credentials.endpoint, key)

    return fetch(credentials.endpoint, {
      method: 'POST',
      body: getUploadData(key, credentials, file),
    })
      .then(checkStatus)
  }

  function saveLocationToApi() {
    const vo = (type === ACTION_TYPES.PROFILE.SAVE_AVATAR) ? { remote_avatar_url: assetUrl } : { remote_cover_image_url: assetUrl }
    return fetch(endpoint.path, {
      method: 'PATCH',
      headers: getCredentialsHeader(accessToken),
      body: JSON.stringify(vo),
    })
      .then(checkStatus)
      .then(parseJSON)
  }

  return (
    fetchCredentials()
    .then(postAsset)
    .then(saveLocationToApi)
    .then(response => {
      payload.response = camelizeKeys(response)
      next({ meta, payload, type: SUCCESS })
      return true
    })
    .catch(error => {
      next({ error, meta, payload, type: FAILURE })
      return false
    })
  )
}

<|endoftext|>


<commit_before>function Screen(canvas, resolution) {
    "use strict";

    if (!(canvas instanceof HTMLCanvasElement)) {
        throw new InvalidArgumentError("canvas", "Invalid canvas object passed: " + canvas);
    }

    this.size = new Vector2(canvas.width, canvas.height);
    this.font = "HelveticaNeue Liberation Roboto Sans";
    this.fontColor = "#FFF";
    this.fontSize = 20;

    if (!(resolution instanceof Vector2)) {
        this.resolution = this.size;
    } else {
        this.resolution = resolution;
    }

    var context = canvas.getContext("2d");

    Log.info("Screen initialized. Canvas Size: " + this.size + " Resolution: " + this.resolution, this);

    this.render = function (image, position, size) {
        context.drawImage(image, position.x, position.y, size.x, size.y);
    };

    this.clear = function () {
        context.clearRect(0, 0, this.size.x, this.size.y);
    };

    this.renderText = function (text, position, size, colour, font) {
        if (typeof font === 'undefined') {
            font = this.font;
        } else if (typeof font !== 'string') {
            throw new InvalidArgumentError("font", "Fonts have to be strings containing both the font size and one or more font families. Received: " + font);
        }

        if (typeof size === 'undefined') {
            size = this.fontSize;
        } else if (typeof size !== 'number') {
            throw new InvalidArgumentError("size", "size must be an integer. Received: " + size);
        }

        if (typeof colour === 'undefined') {
            colour = this.fontColor;
        } else if (typeof colour !== 'string') {
            throw new InvalidArgumentError("colour", "Colours have to be strings. Received: " + colour);
        }

        if (typeof position === 'undefined') {
            position = new Vector2();
        } else if (!(position instanceof Vector2)) {
            throw new InvalidArgumentError("position", "Position should be a Vector2. Received: " + position);
        }

        context.font = size + "px " + font;
        context.fillStyle = colour;
        context.fillText(text, position.x, position.y);
    };

    this.addEventListener = function (event, callback) {
        canvas.addEventListener(event, callback);
    };

    this.setOnContextMenu = function (callback) {
        canvas.oncontextmenu = callback;
    };
}

Screen.prototype.toString = function () {
    "use strict";
    return "Screen";
};<commit_msg>Add methods to calculate text dimensions<commit_after>function Screen(canvas, resolution) {
    "use strict";

    if (!(canvas instanceof HTMLCanvasElement)) {
        throw new InvalidArgumentError("canvas", "Invalid canvas object passed: " + canvas);
    }

    this.size = new Vector2(canvas.width, canvas.height);
    this.font = "HelveticaNeue Liberation Roboto Sans";
    this.fontColor = "#FFF";
    this.fontSize = 20;

    if (!(resolution instanceof Vector2)) {
        this.resolution = this.size;
    } else {
        this.resolution = resolution;
    }

    var context = canvas.getContext("2d");

    Log.info("Screen initialized. Canvas Size: " + this.size + " Resolution: " + this.resolution, this);

    this.render = function (image, position, size) {
        context.drawImage(image, position.x, position.y, size.x, size.y);
    };

    this.clear = function () {
        context.clearRect(0, 0, this.size.x, this.size.y);
    };

    this.renderFilledRect = function(position, size, colour) {
        context.fillStyle = colour;
        context.fillRect(position.x, position.y, size.x, size.y);
    };

    this.getTextWidth = function(text, size, font) {
        if (typeof font === 'undefined') {
            font = this.font;
        } else if (typeof font !== 'string') {
            throw new InvalidArgumentError("font", "Fonts have to be strings containing both the font size and one or more font families. Received: " + font);
        }

        if (typeof size === 'undefined') {
            size = this.fontSize;
        } else if (typeof size !== 'number') {
            throw new InvalidArgumentError("size", "size must be an integer. Received: " + size);
        }

        context.font = size + "px " + font;
        return context.measureText(text).width;
    }

    this.getTextHeight = function(text, size, font) {
        if (typeof size === 'undefined') {
            size = this.fontSize;
        } else if (typeof size !== 'number') {
            throw new InvalidArgumentError("size", "size must be an integer. Received: " + size);
        }

        return size;
    }

    this.renderText = function (text, position, size, colour, font, width) {
        if (typeof font === 'undefined') {
            font = this.font;
        } else if (typeof font !== 'string') {
            throw new InvalidArgumentError("font", "Fonts have to be strings containing both the font size and one or more font families. Received: " + font);
        }

        if (typeof size === 'undefined') {
            size = this.fontSize;
        } else if (typeof size !== 'number') {
            throw new InvalidArgumentError("size", "size must be a number. Received: " + size);
        }

        if (typeof colour === 'undefined') {
            colour = this.fontColor;
        } else if (typeof colour !== 'string') {
            throw new InvalidArgumentError("colour", "Colours have to be strings. Received: " + colour);
        }

        if (typeof position === 'undefined') {
            position = new Vector2();
        } else if (!(position instanceof Vector2)) {
            throw new InvalidArgumentError("position", "Position should be a Vector2. Received: " + position);
        }

        if (typeof width === 'undefined') {
            width = this.getTextWidth(text, size, font);
        } else if (typeof width !== 'number') {
            throw new InvalidArgumentError("width", "width must be a number. Received: " + width);
        }

        context.font = size + "px " + font;
        context.fillStyle = colour;
        context.fillText(text, position.x, position.y, width);
    };

    this.addEventListener = function (event, callback) {
        canvas.addEventListener(event, callback);
    };

    this.setOnContextMenu = function (callback) {
        canvas.oncontextmenu = callback;
    };
}

Screen.prototype.toString = function () {
    "use strict";
    return "Screen";
};<|endoftext|>


<commit_before>/**
* @since 0.0.1
* @copyright 2015 Spatial Vision, Inc. http://spatialvision.com.au
* @license The MIT License
* @author Spatial Vision
* @version 0.0.1
*/

'use strict';

/**
 * nutrientCalculator/MilkSold class
 * @module nutrientCalculator/MilkSold
 */
angular.module('farmbuild.nutrientCalculator')

	.factory('MilkSold', function (Validations) {

		var MilkSold = {},
				_isPositiveNumber = Validations.isPositiveNumber;

		/**
		 * Calculates nutrient from milk sold, input values are in percentage
		 * @method calculateByPercent
		 * @param {!number} milkSoldPerYearInLitre - Quantity of milk sold in a year in litre, value must be > 0 and can have up to 2 decimal places
		 * @param {!number} milkProteinPercentage - Percentage of milk protein, value must be > 0
		 * @param {!number} milkFatPercentage - Percentage of milk fat, value must be > 0
		 * @returns {object} milk nutrient data
		 * @public
		 * @static
		 */
		MilkSold.calculateByPercent = function(milkSoldPerYearInLitre, milkProteinPercentage, milkFatPercentage) {
			var milkProteinInKg, milkFatInKg;

			if(!_validateInputs(milkSoldPerYearInLitre, milkProteinPercentage, milkFatPercentage, '%')){
				return undefined;
			}

			milkSoldPerYearInLitre = parseFloat(milkSoldPerYearInLitre);
			milkProteinPercentage = parseFloat(milkProteinPercentage);
			milkFatPercentage = parseFloat(milkFatPercentage);

			milkProteinInKg = _percentageToKg(milkProteinPercentage, milkSoldPerYearInLitre);
			milkFatInKg = _percentageToKg(milkFatPercentage, milkSoldPerYearInLitre);
			return _calculate(milkSoldPerYearInLitre, milkFatInKg, milkProteinInKg, milkProteinPercentage, milkFatPercentage);

		};

		/**
		 * Calculates nutrient from milk sold, input values are in Kg
		 * @method calculateByKg
		 * @param {!number} milkSoldPerYearInLitre - Quantity of milk sold in a year in litre, value must be > 0 and can have up to 2 decimal places
		 * @param {!number} milkFatInKg - Quantity of milk fat in Kg, value must be > 0
		 * @param {!number} milkProteinInKg - Quantity of milk protein in Kg, value must be > 0
		 * @returns {object} milk nutrient data
		 * @public
		 * @static
		 */
		MilkSold.calculateByKg = function(milkSoldPerYearInLitre, milkProteinInKg, milkFatInKg) {
			var milkProteinPercentage, milkFatPercentage;

			if(!_validateInputs(milkSoldPerYearInLitre, milkProteinInKg, milkFatInKg, 'kg')){
				return undefined;
			}

			milkSoldPerYearInLitre = parseFloat(milkSoldPerYearInLitre);
			milkProteinInKg = parseFloat(milkProteinInKg);
			milkFatInKg = parseFloat(milkFatInKg);

			milkFatPercentage = _kgToPercentage(milkFatInKg, milkSoldPerYearInLitre);
			milkProteinPercentage = _kgToPercentage(milkProteinInKg, milkSoldPerYearInLitre);
			return _calculate(milkSoldPerYearInLitre, milkFatInKg, milkProteinInKg, milkProteinPercentage, milkFatPercentage);

		};

		/**
		 * Returns true if input values are valid
		 * @method _validateInputs
		 * @param {!number} milkSoldPerYearInLitre - Quantity of milk sold in a year in litre, value must be > 0 and can have up to 2 decimal places
		 * @param {!number} milkProtein - Quantity of milk fat in Kg/Percentage, value must be > 0
		 * @param {!number} milkFat - Quantity of milk protein in Kg/Percentage, value must be > 0
		 * @param {!string} unit - Percentage or Kg
		 * @returns {boolean} validity of input values
		 * @private
		 */
		function _validateInputs(milkSoldPerYearInLitre, milkProtein, milkFat, unit){

			if (!milkSoldPerYearInLitre || !milkProtein || !milkFat || !unit) {
				return false;
			}

			if(!_isPositiveNumber(milkSoldPerYearInLitre) || !_isPositiveNumber(milkProtein) || !_isPositiveNumber(milkFat)){
				return false;
			}

			if(unit === '%' && milkProtein + milkFat > 100){
				return false;
			}

			if(unit === 'kg' && milkProtein + milkFat > milkSoldPerYearInLitre){
				return false;
			}

			return true;

		}

		/**
		 * Returns nutrient data of milk
		 * @method _calculate
		 * @param {!number} milkSoldPerYearInLitre - Quantity of milk sold in a year in litre, value must be > 0 and can have up to 2 decimal places
		 * @param {!number} milkFatInKg - Quantity of milk fat in Kilograms, value must be > 0
		 * @param {!number} milkProteinInKg - Quantity of milk protein in Kilograms, value must be > 0
		 * @param {!number} milkProteinPercentage - Percentage of milk protein, value must be > 0
		 * @param {!number} milkFatPercentage - Percentage of milk fat, value must be > 0
		 * @returns {object} milk nutrient data
		 * @private
		 */
		function _calculate(milkSoldPerYearInLitre, milkFatInKg, milkProteinInKg, milkProteinPercentage, milkFatPercentage) {

			var nitrogenPercentage = milkProteinPercentage / 6.33,
				phosphorusPercentage = (0.0111 * milkFatPercentage + 0.05255),
				potassiumPercentage = 0.14, sulphurPercentage = 0.06,
				nitrogenInKg = (milkSoldPerYearInLitre * nitrogenPercentage / 100),
				potassiumInKg = (milkSoldPerYearInLitre * potassiumPercentage / 100),
				sulphurInKg = (milkSoldPerYearInLitre * sulphurPercentage / 100),
				phosphorusInKg = (milkSoldPerYearInLitre * phosphorusPercentage / 100);

			return {
				totalPerYearInLitre: milkSoldPerYearInLitre,
				fatInKg: milkFatInKg,
				fatPercentage: milkFatPercentage,
				proteinInKg: milkProteinInKg,
				proteinPercentage: milkProteinPercentage,
				nitrogenInKg: nitrogenInKg,
				nitrogenPercentage: nitrogenPercentage,
				phosphorusInKg: phosphorusInKg,
				phosphorusPercentage: phosphorusPercentage,
				potassiumInKg: potassiumInKg,
				potassiumPercentage: potassiumPercentage,
				sulphurInKg: sulphurInKg,
				sulphurPercentage: sulphurPercentage
			};

		}

		/**
		 * Returns nutrient value in percentage
		 * @method _kgToPercentage
		 * @param {!number} valueInKg - Quantity of milk protein in Kilograms
		 * @param {!number} totalInLitre - Percentage of milk protein
		 * @returns {number} nutrient value in percentage
		 * @private
		 */
		function _kgToPercentage(valueInKg, totalInLitre) {
			return (valueInKg / totalInLitre) * 100;
		}

		/**
		 * Returns nutrient value in Kg
		 * @method _percentageToKg
		 * @param {!number} valuePercentage - Quantity of milk protein in Kilograms
		 * @param {!number} totalInLitre - Percentage of milk protein
		 * @returns {number} nutrient value in Kg
		 * @private
		 */
		function _percentageToKg(valuePercentage, totalInLitre) {
			return (valuePercentage * totalInLitre) / 100;
		}

		return MilkSold;

	});
<commit_msg>updated api docs<commit_after>/**
* @since 0.0.1
* @copyright 2015 Spatial Vision, Inc. http://spatialvision.com.au
* @license The MIT License
* @author Spatial Vision
* @version 0.0.1
*/

'use strict';

/**
 * nutrientCalculator/MilkSold class
 * @module nutrientCalculator/MilkSold
 */
angular.module('farmbuild.nutrientCalculator')

	.factory('MilkSold', function (Validations) {

		var MilkSold = {},
				_isPositiveNumber = Validations.isPositiveNumber;

		/**
		 * Calculates nutrient from milk sold, input values are in percentage
		 * @method calculateByPercent
		 * @param {!number} milkSoldPerYearInLitre - Quantity of milk sold in a year in litre, value must be > 0
		 * @param {!number} milkProteinPercentage - Percentage of milk protein, value must be > 0
		 * @param {!number} milkFatPercentage - Percentage of milk fat, value must be > 0
		 * @returns {object} milk nutrient data
		 * @public
		 * @static
		 */
		MilkSold.calculateByPercent = function(milkSoldPerYearInLitre, milkProteinPercentage, milkFatPercentage) {
			var milkProteinInKg, milkFatInKg;

			if(!_validateInputs(milkSoldPerYearInLitre, milkProteinPercentage, milkFatPercentage, '%')){
				return undefined;
			}

			milkSoldPerYearInLitre = parseFloat(milkSoldPerYearInLitre);
			milkProteinPercentage = parseFloat(milkProteinPercentage);
			milkFatPercentage = parseFloat(milkFatPercentage);

			milkProteinInKg = _percentageToKg(milkProteinPercentage, milkSoldPerYearInLitre);
			milkFatInKg = _percentageToKg(milkFatPercentage, milkSoldPerYearInLitre);
			return _calculate(milkSoldPerYearInLitre, milkFatInKg, milkProteinInKg, milkProteinPercentage, milkFatPercentage);

		};

		/**
		 * Calculates nutrient from milk sold, input values are in Kg
		 * @method calculateByKg
		 * @param {!number} milkSoldPerYearInLitre - Quantity of milk sold in a year in litre, value must be > 0
		 * @param {!number} milkFatInKg - Quantity of milk fat in Kg, value must be > 0
		 * @param {!number} milkProteinInKg - Quantity of milk protein in Kg, value must be > 0
		 * @returns {object} milk nutrient data
		 * @public
		 * @static
		 */
		MilkSold.calculateByKg = function(milkSoldPerYearInLitre, milkProteinInKg, milkFatInKg) {
			var milkProteinPercentage, milkFatPercentage;

			if(!_validateInputs(milkSoldPerYearInLitre, milkProteinInKg, milkFatInKg, 'kg')){
				return undefined;
			}

			milkSoldPerYearInLitre = parseFloat(milkSoldPerYearInLitre);
			milkProteinInKg = parseFloat(milkProteinInKg);
			milkFatInKg = parseFloat(milkFatInKg);

			milkFatPercentage = _kgToPercentage(milkFatInKg, milkSoldPerYearInLitre);
			milkProteinPercentage = _kgToPercentage(milkProteinInKg, milkSoldPerYearInLitre);
			return _calculate(milkSoldPerYearInLitre, milkFatInKg, milkProteinInKg, milkProteinPercentage, milkFatPercentage);

		};

		/**
		 * Returns true if input values are valid
		 * @method _validateInputs
		 * @param {!number} milkSoldPerYearInLitre - Quantity of milk sold in a year in litre, value must be > 0
		 * @param {!number} milkProtein - Quantity of milk fat in Kg/Percentage, value must be > 0
		 * @param {!number} milkFat - Quantity of milk protein in Kg/Percentage, value must be > 0
		 * @param {!string} unit - Percentage or Kg
		 * @returns {boolean} validity of input values
		 * @private
		 */
		function _validateInputs(milkSoldPerYearInLitre, milkProtein, milkFat, unit){

			if (!milkSoldPerYearInLitre || !milkProtein || !milkFat || !unit) {
				return false;
			}

			if(!_isPositiveNumber(milkSoldPerYearInLitre) || !_isPositiveNumber(milkProtein) || !_isPositiveNumber(milkFat)){
				return false;
			}

			if(unit === '%' && milkProtein + milkFat > 100){
				return false;
			}

			if(unit === 'kg' && milkProtein + milkFat > milkSoldPerYearInLitre){
				return false;
			}

			return true;

		}

		/**
		 * Returns nutrient data of milk
		 * @method _calculate
		 * @param {!number} milkSoldPerYearInLitre - Quantity of milk sold in a year in litre, value must be > 0 and can have up to 2 decimal places
		 * @param {!number} milkFatInKg - Quantity of milk fat in Kilograms, value must be > 0
		 * @param {!number} milkProteinInKg - Quantity of milk protein in Kilograms, value must be > 0
		 * @param {!number} milkProteinPercentage - Percentage of milk protein, value must be > 0
		 * @param {!number} milkFatPercentage - Percentage of milk fat, value must be > 0
		 * @returns {object} milk nutrient data
		 * @private
		 */
		function _calculate(milkSoldPerYearInLitre, milkFatInKg, milkProteinInKg, milkProteinPercentage, milkFatPercentage) {

			var nitrogenPercentage = milkProteinPercentage / 6.33,
				phosphorusPercentage = (0.0111 * milkFatPercentage + 0.05255),
				potassiumPercentage = 0.14, sulphurPercentage = 0.06,
				nitrogenInKg = (milkSoldPerYearInLitre * nitrogenPercentage / 100),
				potassiumInKg = (milkSoldPerYearInLitre * potassiumPercentage / 100),
				sulphurInKg = (milkSoldPerYearInLitre * sulphurPercentage / 100),
				phosphorusInKg = (milkSoldPerYearInLitre * phosphorusPercentage / 100);

			return {
				totalPerYearInLitre: milkSoldPerYearInLitre,
				fatInKg: milkFatInKg,
				fatPercentage: milkFatPercentage,
				proteinInKg: milkProteinInKg,
				proteinPercentage: milkProteinPercentage,
				nitrogenInKg: nitrogenInKg,
				nitrogenPercentage: nitrogenPercentage,
				phosphorusInKg: phosphorusInKg,
				phosphorusPercentage: phosphorusPercentage,
				potassiumInKg: potassiumInKg,
				potassiumPercentage: potassiumPercentage,
				sulphurInKg: sulphurInKg,
				sulphurPercentage: sulphurPercentage
			};

		}

		/**
		 * Returns nutrient value in percentage
		 * @method _kgToPercentage
		 * @param {!number} valueInKg - Quantity of milk protein in Kilograms
		 * @param {!number} totalInLitre - Percentage of milk protein
		 * @returns {number} nutrient value in percentage
		 * @private
		 */
		function _kgToPercentage(valueInKg, totalInLitre) {
			return (valueInKg / totalInLitre) * 100;
		}

		/**
		 * Returns nutrient value in Kg
		 * @method _percentageToKg
		 * @param {!number} valuePercentage - Quantity of milk protein in Kilograms
		 * @param {!number} totalInLitre - Percentage of milk protein
		 * @returns {number} nutrient value in Kg
		 * @private
		 */
		function _percentageToKg(valuePercentage, totalInLitre) {
			return (valuePercentage * totalInLitre) / 100;
		}

		return MilkSold;

	});
<|endoftext|>


<commit_before>//Copyright (c) 2015 Jordan Turley, CSGO Win Big. All Rights Reserved.

//The most recent ID for the chat
var localMostRecentID = 0, potCount = 0;

//Whether or not the call of update() is the first call
var firstUpdate = true;

//The most recent ID for the user sending the chat.
//Used if they want to send multiple messages before the chat refreshes.
var localChatIDForColor = 0;

//Whether or not the user is logged in
var loggedIn = false;

//The user's information
var mUserInfo = null;

$(function () {
	$.getJSON('php/login-status.php', function (jsonObj) {
		handleJsonResponse(jsonObj, function (data) {
			var loginStatus = data['loginStatus'];

			mUserInfo = data['userInfo'];

			if (loginStatus === 1) {
				//They are logged in
				$('.logout').css('display', 'inline');
				$('#chat-input').css('display', 'block');

				loggedIn = true;
			} else {
				//They are not logged in
				$('.login').css('display', 'inline');
			}

			$('#loading-menubar').css('display', 'none');

			setTimeout(update, 200);
		});
	});

	$('#chat-input').on('keydown', function (event) {
		if (event.which === 13 || loggedIn === false) {
			var text = this.value;

			if (text.length === 0) {
				return;
			}

			localChatIDForColor++;

			var date = getFormattedDate(), time = getFormattedTime();

			var msgObj = {
				id: localChatIDForColor,
				text: text,
				date: date,
				time: time,
				steamUserInfo: mUserInfo
			};

			var str = generateChatMsgStr(msgObj);

			$('#chatmessages').append(str);
			$('#chatmessages').scrollTop($('#chatmessages')[0].scrollHeight);

			$('#chat-input').val('');

			$.post('php/send-chat-message.php', {text: text});
		}
	});
});

function update () {
	$.getJSON('php/update.php', function (jsonObj) {
		handleJsonResponse(jsonObj, function (data) {
			console.log('Response received.');
			var chat = data['chat'],
				pot = data['pot'],
				potPrice = data['potPrice'],
				mostRecentGame = data['mostRecentGame'];

			var serverMostRecentID = parseInt(chat[chat.length - 1]['id'], 10);

			//Check if this is the first time update has been called
			if (firstUpdate) {
				$('#pot-items-price').css('display', 'block');
			}

			//Check for new messages
			if (serverMostRecentID > localMostRecentID) {
				console.log('New messages!');
				localMostRecentID = serverMostRecentID;
				localChatIDForColor = serverMostRecentID;

				var chatStr = generateChatStr(chat);
				$('#chatmessages').html(chatStr);
				$('#chatmessages').scrollTop($('#chatmessages')[0].scrollHeight);
			}

			//Check for new items in the pot
			if (pot.length > potCount) {
				console.log('New items in pot!');
				potCount = pot.length;

				//Set pot price
				var realPotPrice = potPrice / 100;
				if (realPotPrice % 1 === 0) {
					realPotPrice = realPotPrice + '.00';
				}
				$('#pot-price').text(realPotPrice);

				//Set number of pot items
				$('#pot-items').text(potCount);

				//Set items in pot
				var potStr = generatePotStr(pot);
				$('#pot').html(potStr);
			} else if (pot.length < potCount) {
				//Someone just now won, do some big animation
				//For now, just sweetalert the winner

				potCount = pot.length;

				var prevGameID = mostRecentGame['prevGameID'],
					winnerSteamInfo = mostRecentGame['winnerSteamInfo'],
					userPutInPrice = parseInt(mostRecentGame['userPutInPrice']),
					potPrice = parseInt(mostRecentGame['potPrice']),
					allItems = mostRecentGame['allItems'],
					paid = mostRecentGame['paid'];

				var potPriceReal = '$' + (potPrice / 100) + ((potPrice % 1 === 0) ? '.00' : '');
				var percentageChance = (userPutInPrice / potPrice * 100).toFixed(2);
				var winnerSteamID = winnerSteamInfo['steamid'], winnerProfileName = winnerSteamInfo['personaname'];

				if (winnerSteamID === mUserInfo['steamid']) {
					var msg = 'You have won ' + potPriceReal + ', with a ' + percentageChance + '% chance! Expect a trade request from our bot shortly.';
					swal('You Win!', msg, 'success');
				} else {
					swal('Round ended!', winnerProfileName + ' has won ' + potPriceReal + ', with a ' + percentageChance + ' chance!', 'success');
				}
			}

			if (mostRecentGame !== null) {
				var prevGameID = mostRecentGame['prevGameID'],
					winnerSteamInfo = mostRecentGame['winnerSteamInfo'],
					userPutInPrice = parseInt(mostRecentGame['userPutInPrice']),
					potPrice = parseInt(mostRecentGame['potPrice']),
					allItems = mostRecentGame['allItems'],
					paid = mostRecentGame['paid'];

				var percentageChance = (userPutInPrice / potPrice * 100).toFixed(2);
				var profileName = winnerSteamInfo['personaname'];
				var potPriceReal = '$' + (potPrice / 100) + ((potPrice % 1 === 0) ? '.00' : '');

				var str = 'Previous Winner: ' + profileName + ' won ' + potPriceReal + ' with a ' + percentageChance + '% chance.';
				$('#prev-game-info').html(str);
				$('#prev-game-info').css('display', 'block');
			}

			setTimeout(update, 2000); //Call update again after 2 seconds
		});
	});
}

function generateChatStr (chat) {
	var str = '';
	for (var i1 = 0; i1 < chat.length; i1++) {
		var msg = chat[i1];

		str += generateChatMsgStr(msg);
	}
	return str;
}

function generateChatMsgStr (msg) {
	var id = parseInt(msg['id'], 10),
		text = msg['text'],
		date = msg['date'],
		time = msg['time'],
		userInfo = msg['steamUserInfo'];

	var profileName = userInfo['personaname'],
		profileURL = userInfo['profileurl'],
		steamID = userInfo['steamid'];
		profilePicSmall = userInfo['avatar'];

	var colorClass = id % 2 === 0 ? 'chat-message-even' : 'chat-message-odd';

	var str = '
';
	str += '';
	str += '';
	str += '
' + profileName + '
';
	str += '';
	str += '
' + date + ' at ' + time + '
';
	str += '
' + text + '
';
	str += '
';

	return str;
}

function generatePotStr (pot) {
	var str = '';
	for (var i1 = 0; i1 < pot.length; i1++) {
		var item = pot[i1];

		var itemID = item['id'],
			itemOwnerSteamInfo = item['itemSteamOwnerInfo'],
			itemName = item['itemName'],
			itemPrice = item['itemPrice'],
			itemIcon = item['itemIcon'];

		var profileName = itemOwnerSteamInfo['personaname'],
			profileAvatar = itemOwnerSteamInfo['avatarfull'],
			profileURL = itemOwnerSteamInfo['profileurl'];

		var itemRealPrice = itemPrice / 100;

		if (itemRealPrice % 1 === 0) {
			itemRealPrice = itemRealPrice + '.00';
		}

		str += '
'
		str += '';
		str += '
' + profileName + '' + ': ' + itemName + ' - $' + itemRealPrice + '
';
		str += '';
		str += '
';
	}

	return str;
}

function handleJsonResponse (jsonObj, callback) {
	if (jsonObj['success'] === 1) {
		var data = jsonObj['data'];
		callback(data);
	} else {
		var msg = jsonObj['errMsg'];
		errMsg(msg);
	}
}

function errMsg (message) {
	if (message === null || message === undefined) {
		message = 'An unknown error has occured. Please refresh the page and try again.';
	}
	swal('Hmm, something went wrong', message, 'error');
}

function getFormattedDate() {
	var date = new Date();

	var month = date.getMonth() + 1;
	if (month < 10) {
		month = '0' + month;
	}

	return date.getFullYear() + "-" + month + "-" + date.getDate();
}

function getFormattedTime (argument) {
	var date = new Date();

	return date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds();
}<commit_msg>Add function for formatting price from cents<commit_after>//Copyright (c) 2015 Jordan Turley, CSGO Win Big. All Rights Reserved.

//The most recent ID for the chat
var localMostRecentID = 0, potCount = 0;

//Whether or not the call of update() is the first call
var firstUpdate = true;

//The most recent ID for the user sending the chat.
//Used if they want to send multiple messages before the chat refreshes.
var localChatIDForColor = 0;

//Whether or not the user is logged in
var loggedIn = false;

//The user's information
var mUserInfo = null;

$(function () {
	$.getJSON('php/login-status.php', function (jsonObj) {
		handleJsonResponse(jsonObj, function (data) {
			var loginStatus = data['loginStatus'];

			mUserInfo = data['userInfo'];

			if (loginStatus === 1) {
				//They are logged in
				$('.logout').css('display', 'inline');
				$('#chat-input').css('display', 'block');

				loggedIn = true;
			} else {
				//They are not logged in
				$('.login').css('display', 'inline');
			}

			$('#loading-menubar').css('display', 'none');

			setTimeout(update, 200);
		});
	});

	$('#chat-input').on('keydown', function (event) {
		if (event.which === 13 || loggedIn === false) {
			var text = this.value;

			if (text.length === 0) {
				return;
			}

			localChatIDForColor++;

			var date = getFormattedDate(), time = getFormattedTime();

			var msgObj = {
				id: localChatIDForColor,
				text: text,
				date: date,
				time: time,
				steamUserInfo: mUserInfo
			};

			var str = generateChatMsgStr(msgObj);

			$('#chatmessages').append(str);
			$('#chatmessages').scrollTop($('#chatmessages')[0].scrollHeight);

			$('#chat-input').val('');

			$.post('php/send-chat-message.php', {text: text});
		}
	});
});

function update () {
	$.getJSON('php/update.php', function (jsonObj) {
		handleJsonResponse(jsonObj, function (data) {
			console.log('Response received.');
			var chat = data['chat'],
				pot = data['pot'],
				potPrice = data['potPrice'],
				mostRecentGame = data['mostRecentGame'];

			var serverMostRecentID = parseInt(chat[chat.length - 1]['id'], 10);

			//Check if this is the first time update has been called
			if (firstUpdate) {
				$('#pot-items-price').css('display', 'block');
			}

			//Check for new messages
			if (serverMostRecentID > localMostRecentID) {
				console.log('New messages!');
				localMostRecentID = serverMostRecentID;
				localChatIDForColor = serverMostRecentID;

				var chatStr = generateChatStr(chat);
				$('#chatmessages').html(chatStr);
				$('#chatmessages').scrollTop($('#chatmessages')[0].scrollHeight);
			}

			//Check for new items in the pot
			if (pot.length > potCount) {
				console.log('New items in pot!');
				potCount = pot.length;

				//Set pot price
				var realPotPrice = getFormattedPrice(potPrice);
				$('#pot-price').text(realPotPrice);

				//Set number of pot items
				$('#pot-items').text(potCount);

				//Set items in pot
				var potStr = generatePotStr(pot);
				$('#pot').html(potStr);
			} else if (pot.length < potCount) {
				//Someone just now won, do some big animation
				//For now, just sweetalert the winner

				potCount = pot.length;

				var prevGameID = mostRecentGame['prevGameID'],
					winnerSteamInfo = mostRecentGame['winnerSteamInfo'],
					userPutInPrice = parseInt(mostRecentGame['userPutInPrice']),
					potPrice = parseInt(mostRecentGame['potPrice']),
					allItems = mostRecentGame['allItems'],
					paid = mostRecentGame['paid'];

				var potPriceReal = getFormattedPrice(potPrice);
				var percentageChance = (userPutInPrice / potPrice * 100).toFixed(2);
				var winnerSteamID = winnerSteamInfo['steamid'], winnerProfileName = winnerSteamInfo['personaname'];

				if (winnerSteamID === mUserInfo['steamid']) {
					var msg = 'You have won ' + potPriceReal + ', with a ' + percentageChance + '% chance! Expect a trade request from our bot shortly.';
					swal('You Win!', msg, 'success');
				} else {
					swal('Round ended!', winnerProfileName + ' has won ' + potPriceReal + ', with a ' + percentageChance + ' chance!', 'success');
				}
			}

			if (mostRecentGame !== null) {
				var prevGameID = mostRecentGame['prevGameID'],
					winnerSteamInfo = mostRecentGame['winnerSteamInfo'],
					userPutInPrice = parseInt(mostRecentGame['userPutInPrice']),
					potPrice = parseInt(mostRecentGame['potPrice']),
					allItems = mostRecentGame['allItems'],
					paid = mostRecentGame['paid'];

				var percentageChance = (userPutInPrice / potPrice * 100).toFixed(2);
				var profileName = winnerSteamInfo['personaname'];
				var potPriceReal = getFormattedPrice(potPrice);

				var str = 'Previous Winner: ' + profileName + ' won ' + potPriceReal + ' with a ' + percentageChance + '% chance.';
				$('#prev-game-info').html(str);
				$('#prev-game-info').css('display', 'block');
			}

			setTimeout(update, 2000); //Call update again after 2 seconds
		});
	});
}

function generateChatStr (chat) {
	var str = '';
	for (var i1 = 0; i1 < chat.length; i1++) {
		var msg = chat[i1];

		str += generateChatMsgStr(msg);
	}
	return str;
}

function generateChatMsgStr (msg) {
	var id = parseInt(msg['id'], 10),
		text = msg['text'],
		date = msg['date'],
		time = msg['time'],
		userInfo = msg['steamUserInfo'];

	var profileName = userInfo['personaname'],
		profileURL = userInfo['profileurl'],
		steamID = userInfo['steamid'];
		profilePicSmall = userInfo['avatar'];

	var colorClass = id % 2 === 0 ? 'chat-message-even' : 'chat-message-odd';

	var str = '
';
	str += '';
	str += '';
	str += '
' + profileName + '
';
	str += '';
	str += '
' + date + ' at ' + time + '
';
	str += '
' + text + '
';
	str += '
';

	return str;
}

function generatePotStr (pot) {
	var str = '';
	for (var i1 = 0; i1 < pot.length; i1++) {
		var item = pot[i1];

		var itemID = item['id'],
			itemOwnerSteamInfo = item['itemSteamOwnerInfo'],
			itemName = item['itemName'],
			itemPrice = item['itemPrice'],
			itemIcon = item['itemIcon'];

		var profileName = itemOwnerSteamInfo['personaname'],
			profileAvatar = itemOwnerSteamInfo['avatarfull'],
			profileURL = itemOwnerSteamInfo['profileurl'];

		var itemRealPrice = getFormattedPrice(itemPrice);

		str += '
'
		str += '';
		str += '
' + profileName + '' + ': ' + itemName + ' - ' + itemRealPrice + '
';
		str += '';
		str += '
';
	}

	return str;
}

function handleJsonResponse (jsonObj, callback) {
	if (jsonObj['success'] === 1) {
		var data = jsonObj['data'];
		callback(data);
	} else {
		var msg = jsonObj['errMsg'];
		errMsg(msg);
	}
}

function errMsg (message) {
	if (message === null || message === undefined) {
		message = 'An unknown error has occured. Please refresh the page and try again.';
	}
	swal('Hmm, something went wrong', message, 'error');
}

function getFormattedDate() {
	var date = new Date();

	var month = date.getMonth() + 1;
	if (month < 10) {
		month = '0' + month;
	}

	return date.getFullYear() + "-" + month + "-" + date.getDate();
}

function getFormattedTime (argument) {
	var date = new Date();

	return date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds();
}

function getFormattedPrice (cents) {
	var price = cents / 100;

	if (cents % 100 === 0) { //If it is an even dollar, add the .00
		price = price + '.00';
	} else if (cents % 10 === 0) { //If it is like $3.40, add the trailing 0
		price = price + '0';
	}

	return '$' + price;
}<|endoftext|>