<commit_before>
import {Layer} from './Layer';
import * as Util from '../core/Util';

/*
 * @class LayerGroup
 * @aka L.LayerGroup
 * @inherits Layer
 *
 * Used to group several layers and handle them as one. If you add it to the map,
 * any layers added or removed from the group will be added/removed on the map as
 * well. Extends `Layer`.
 *
 * @example
 *
 * ```js
 * L.layerGroup([marker1, marker2])
 * 	.addLayer(polyline)
 * 	.addTo(map);
 * ```
 */

export var LayerGroup = Layer.extend({

	initialize: function (layers) {
		this._layers = {};

		var i, len;

		if (layers) {
			for (i = 0, len = layers.length; i < len; i++) {
				this.addLayer(layers[i]);
			}
		}
	},

	// @method addLayer(layer: Layer): this
	// Adds the given layer to the group.
	addLayer: function (layer) {
		var id = this.getLayerId(layer);

		this._layers[id] = layer;

		if (this._map) {
			this._map.addLayer(layer);
		}

		return this;
	},

	// @method removeLayer(layer: Layer): this
	// Removes the given layer from the group.
	// @alternative
	// @method removeLayer(id: Number): this
	// Removes the layer with the given internal ID from the group.
	removeLayer: function (layer) {
		var id = layer in this._layers ? layer : this.getLayerId(layer);

		if (this._map && this._layers[id]) {
			this._map.removeLayer(this._layers[id]);
		}

		delete this._layers[id];

		return this;
	},

	// @method hasLayer(layer: Layer): Boolean
	// Returns `true` if the given layer is currently added to the group.
	// @alternative
	// @method hasLayer(id: Number): Boolean
	// Returns `true` if the given internal ID is currently added to the group.
	hasLayer: function (layer) {
		return !!layer && (layer in this._layers || this.getLayerId(layer) in this._layers);
	},

	// @method clearLayers(): this
	// Removes all the layers from the group.
	clearLayers: function () {
		for (var i in this._layers) {
			this.removeLayer(this._layers[i]);
		}
		return this;
	},

	// @method invoke(methodName: String, …): this
	// Calls `methodName` on every layer contained in this group, passing any
	// additional parameters. Has no effect if the layers contained do not
	// implement `methodName`.
	invoke: function (methodName) {
		var args = Array.prototype.slice.call(arguments, 1),
		    i, layer;

		for (i in this._layers) {
			layer = this._layers[i];

			if (layer[methodName]) {
				layer[methodName].apply(layer, args);
			}
		}

		return this;
	},

	onAdd: function (map) {
		for (var i in this._layers) {
			map.addLayer(this._layers[i]);
		}
	},

	onRemove: function (map) {
		for (var i in this._layers) {
			map.removeLayer(this._layers[i]);
		}
	},

	// @method eachLayer(fn: Function, context?: Object): this
	// Iterates over the layers of the group, optionally specifying context of the iterator function.
	// ```js
	// group.eachLayer(function (layer) {
	// 	layer.bindPopup('Hello');
	// });
	// ```
	eachLayer: function (method, context) {
		for (var i in this._layers) {
			method.call(context, this._layers[i]);
		}
		return this;
	},

	// @method getLayer(id: Number): Layer
	// Returns the layer with the given internal ID.
	getLayer: function (id) {
		return this._layers[id];
	},

	// @method getLayers(): Layer[]
	// Returns an array of all the layers added to the group.
	getLayers: function () {
		var layers = [];

		for (var i in this._layers) {
			layers.push(this._layers[i]);
		}
		return layers;
	},

	// @method setZIndex(zIndex: Number): this
	// Calls `setZIndex` on every layer contained in this group, passing the z-index.
	setZIndex: function (zIndex) {
		return this.invoke('setZIndex', zIndex);
	},

	// @method getLayerId(layer: Layer): Number
	// Returns the internal ID for a layer
	getLayerId: function (layer) {
		return Util.stamp(layer);
	}
});

// @factory L.layerGroup(layers: Layer[])
// Create a layer group, optionally given an initial set of layers.
export var layerGroup = function (layers) {
	return new LayerGroup(layers);
};
<commit_msg>LayerGroup parameter is optional (#5599)<commit_after>
import {Layer} from './Layer';
import * as Util from '../core/Util';

/*
 * @class LayerGroup
 * @aka L.LayerGroup
 * @inherits Layer
 *
 * Used to group several layers and handle them as one. If you add it to the map,
 * any layers added or removed from the group will be added/removed on the map as
 * well. Extends `Layer`.
 *
 * @example
 *
 * ```js
 * L.layerGroup([marker1, marker2])
 * 	.addLayer(polyline)
 * 	.addTo(map);
 * ```
 */

export var LayerGroup = Layer.extend({

	initialize: function (layers) {
		this._layers = {};

		var i, len;

		if (layers) {
			for (i = 0, len = layers.length; i < len; i++) {
				this.addLayer(layers[i]);
			}
		}
	},

	// @method addLayer(layer: Layer): this
	// Adds the given layer to the group.
	addLayer: function (layer) {
		var id = this.getLayerId(layer);

		this._layers[id] = layer;

		if (this._map) {
			this._map.addLayer(layer);
		}

		return this;
	},

	// @method removeLayer(layer: Layer): this
	// Removes the given layer from the group.
	// @alternative
	// @method removeLayer(id: Number): this
	// Removes the layer with the given internal ID from the group.
	removeLayer: function (layer) {
		var id = layer in this._layers ? layer : this.getLayerId(layer);

		if (this._map && this._layers[id]) {
			this._map.removeLayer(this._layers[id]);
		}

		delete this._layers[id];

		return this;
	},

	// @method hasLayer(layer: Layer): Boolean
	// Returns `true` if the given layer is currently added to the group.
	// @alternative
	// @method hasLayer(id: Number): Boolean
	// Returns `true` if the given internal ID is currently added to the group.
	hasLayer: function (layer) {
		return !!layer && (layer in this._layers || this.getLayerId(layer) in this._layers);
	},

	// @method clearLayers(): this
	// Removes all the layers from the group.
	clearLayers: function () {
		for (var i in this._layers) {
			this.removeLayer(this._layers[i]);
		}
		return this;
	},

	// @method invoke(methodName: String, …): this
	// Calls `methodName` on every layer contained in this group, passing any
	// additional parameters. Has no effect if the layers contained do not
	// implement `methodName`.
	invoke: function (methodName) {
		var args = Array.prototype.slice.call(arguments, 1),
		    i, layer;

		for (i in this._layers) {
			layer = this._layers[i];

			if (layer[methodName]) {
				layer[methodName].apply(layer, args);
			}
		}

		return this;
	},

	onAdd: function (map) {
		for (var i in this._layers) {
			map.addLayer(this._layers[i]);
		}
	},

	onRemove: function (map) {
		for (var i in this._layers) {
			map.removeLayer(this._layers[i]);
		}
	},

	// @method eachLayer(fn: Function, context?: Object): this
	// Iterates over the layers of the group, optionally specifying context of the iterator function.
	// ```js
	// group.eachLayer(function (layer) {
	// 	layer.bindPopup('Hello');
	// });
	// ```
	eachLayer: function (method, context) {
		for (var i in this._layers) {
			method.call(context, this._layers[i]);
		}
		return this;
	},

	// @method getLayer(id: Number): Layer
	// Returns the layer with the given internal ID.
	getLayer: function (id) {
		return this._layers[id];
	},

	// @method getLayers(): Layer[]
	// Returns an array of all the layers added to the group.
	getLayers: function () {
		var layers = [];

		for (var i in this._layers) {
			layers.push(this._layers[i]);
		}
		return layers;
	},

	// @method setZIndex(zIndex: Number): this
	// Calls `setZIndex` on every layer contained in this group, passing the z-index.
	setZIndex: function (zIndex) {
		return this.invoke('setZIndex', zIndex);
	},

	// @method getLayerId(layer: Layer): Number
	// Returns the internal ID for a layer
	getLayerId: function (layer) {
		return Util.stamp(layer);
	}
});

// @factory L.layerGroup(layers?: Layer[])
// Create a layer group, optionally given an initial set of layers.
export var layerGroup = function (layers) {
	return new LayerGroup(layers);
};
<|endoftext|>


<commit_before>import * as todoApi from '../generated/todo/';
const usedSagas = [].concat(
  todoApi.sagas.getTodosSaga.takeEverySaga,
  todoApi.sagas.postTodoSaga.takeLatestSaga
  // others ...
);
export default usedSagas;

<commit_msg>shorten sagas in usedsagas<commit_after>import { sagas } from '../generated/todo/';
const usedSagas = [].concat(
  sagas.getTodosSaga.takeEverySaga,
  sagas.postTodoSaga.takeLatestSaga
  // others ...
);
export default usedSagas;

<|endoftext|>


<commit_before>import { types, getEnv, getRoot, getType, resolveIdentifier, process } from "mobx-state-tree";
import { isObservableMap } from "mobx";
import { curry, ary } from "lodash";

const optionalString = types.optional(types.string, "");
const optionalMap = type => types.optional(types.map(type), {});

export const reserved = "􂳰";
export const linkKey = "􂳰L";
export const opKey = "􂳰O";
export const valKey = "􂳰V";
export const inputKey = "􂳰I";
export const linkRefKey = "􂳰R";
export const packageKey = "􂳰P";

export const lodash = "_";

export const global = "g";

export const access = ".";

export const array = "[";
export const object = "{";

export const add = "+";
export const subtract = "-";
export const multiply = "*";
export const divide = "/";
export const mod = "%";

export const ifOp = "?";
export const switchOp = "s";
export const forOp = "f";
export const importOp = "m";
export const newOp = "n";
export const typeofOp = "t";
export const instanceOfOp = "i";
export const classOp = "c";
export const thisOp = "h";

export const lessThan = "<";
export const greaterThan = ">";
export const lessThanOrEqual = "<=";
export const greaterThanOrEqual = ">=";
export const equal = "==";
export const strictEqual = "===";
export const notEqual = "!=";
export const notStrictEqual = "!==";

export const swap = "@";

const opFuncs = {
  [global](val) {
    return window[val];
    // return eval(val);
  },
  [access](obj, key) {
    return obj[key];
  },
  [add](...nums) {
    let sum = 0;
    for (const num of nums) {
      sum += num;
    }
    return sum;
  },
  [array](...items) {
    return items;
  },
  [lodash]() {
    // TODO: remove
    return _;
  },
  ifOp(condition, trueVal, falseVal) {
    return condition ? trueVal : falseVal;
  },
  switchOp(context, switcher, ...casePairs) {
    for (let i = 0; i < casePairs.length; i += 2) {
      if (switcher === casePairs[i]) {
        return casePairs[i + 1](context);
      }
    }
  }
};

export const Val = types
  .model("Val", {
    val: types.union(types.string, types.number, types.boolean, types.null)
  })
  .views(self => ({
    with() {
      return self.val;
    }
  }));

export const Op = types
  .model("Op", {
    op: types.enumeration("OpEnum", [
      lodash,
      global,
      access,
      array,
      object,
      add,
      subtract,
      multiply,
      divide,
      mod,
      ifOp,
      switchOp,
      forOp,
      importOp,
      newOp,
      typeofOp,
      instanceOfOp,
      classOp,
      thisOp,
      lessThan,
      greaterThan,
      lessThanOrEqual,
      greaterThanOrEqual,
      equal,
      strictEqual,
      notEqual,
      notStrictEqual,
      swap
    ])
  })
  .views(self => ({
    get val() {
      return opFuncs[self.op];
    },
    with() {
      return self.val;
    }
  }));

export const Package = types
  .model("Package", {
    id: types.identifier(types.number),
    path: types.string,
    resolved: false
  })
  .actions(self => {
    const { system } = getEnv(self);

    return {
      afterCreate: process(function*() {
        yield system.import(self.path);
        // TODO: error handling (retry?)
        self.resolved = true;
      })
    };
  })
  .views(self => {
    const { system } = getEnv(self);

    return {
      get val() {
        if (self.resolved) {
          return system.get(self.path);
        }
        return Package;
      },
      with() {
        return self.val;
      }
    };
  });

export const PackageRef = types
  .model("PackageRef", {
    pkg: types.reference(Package)
  })
  .views(self => ({
    get val() {
      return self.pkg.val;
    },
    with() {
      return self.val;
    }
  }));

// TYPE-CEPTION
export const stringType = "s";
export const numType = "n";
export const boolType = "b";
export const anyType = "a";
export const InputType = types.enumeration("InputType", [stringType, numType, boolType, anyType]);

// is there a better way of doing this?
class Hole {
  constructor(...inputSets) {
    this.inputs = {};

    for (const inputSet of inputSets) {
      for (const input in inputSet) {
        this.inputs[input] = true;
      }
    }
  }
}

export const Input = types
  .model("Input", {
    input: types.identifier(types.string),
    type: types.maybe(InputType, anyType)
  })
  .views(self => ({
    get val() {
      return Input;
    },
    with(inputs) {
      const { input } = self;
      if (inputs && inputs.has(input)) {
        const mapValue = inputs.get(input);
        if (isObservableMap(inputs)) {
          return mapValue.val;
        } else {
          return mapValue;
        }
      } else {
        return new Hole({ [input]: true });
      }
    }
  }));

curry.placeholder = Input;

export const Node = types.union(Val, Op, Input, types.late(() => LinkRef), types.late(() => SubRef), PackageRef);

const identity = x => x;

const baseColor = ",66%,55%)";
const opColor = `hsl(150${baseColor}`;
const valColor = `hsl(210${baseColor}`;
const inputColor = `hsl(25${baseColor}`;
const packageColor = `hsl(315${baseColor}`;
const pendingColor = `hsl(270${baseColor}`;
const unknownColor = `hsl(0${baseColor}`;

export const Link = types
  .model("Link", {
    linkId: types.identifier(types.string),
    nodes: types.array(Node)
  })
  .views(self => ({
    derive(nodeVals) {
      // NOTE: this is a pure function, would it be better to pull this out of the model?
      if (nodeVals.indexOf(Package) !== -1) {
        return Package;
      }

      const [head, ...nodeInputs] = nodeVals;

      if (typeof head === "function") {
        const inputs = nodeInputs.filter(input => input === Input);
        if (inputs.length) {
          const curried = curry(head, nodeInputs.length);
          return ary(curried(...nodeInputs), inputs.length);
        }
        return head(...nodeInputs);
      } else {
        return head;
      }
    },
    get val() {
      const nodeVals = self.nodes.map(node => node.val);
      return self.derive(nodeVals);
    },
    with(inputs) {
      const nodeVals = self.nodes.map(node => node.with(inputs));

      const holes = nodeVals.filter(val => val instanceof Hole);

      if (holes.length) {
        return new Hole(...holes.map(hole => hole.inputs));
      }

      return self.derive(nodeVals);
    }
  }));

export const LinkRef = types
  .model("LinkRef", {
    ref: types.reference(Link)
  })
  .views(self => ({
    get val() {
      return self.ref.val;
    },
    with() {
      return self.val;
    }
  }));

export const Call = types
  .model("Call", {
    callId: types.identifier(types.string),
    link: types.reference(Link),
    inputs: optionalMap(Node)
  })
  .views(self => ({
    get val() {
      const linkVal = self.link.with(self.inputs);
      if (linkVal instanceof Hole) {
        const inputEntries = self.inputs.entries().slice();
        const holeInputIds = Object.keys(linkVal.inputs);

        return (...newInputs) => {
          const newInputEntries = newInputs.map((input, i) => [holeInputIds[i], input]);
          const allInputEntries = [...inputEntries, ...newInputEntries];
          const allInputs = new Map(allInputEntries);
          return self.nodes.with(allInputs);
        };
      }

      return linkVal;
    },
    with() {
      return self.val;
    }
  }));

export const SubParam = types
  .model("SubParam", {
    param: types.number
  })
  .views(self => ({
    get val() {
      return self.param;
    },
    with() {
      return self.val;
    }
  }));

export const SubLink = types
  .model("SubLink", {
    subLink: types.number
  })
  .views(self => ({
    get val() {
      return self.subLink;
    },
    with() {
      return self.val;
    }
  }));

export const SubNode = types.union(Val, Op, Input, LinkRef, SubParam, SubLink, types.late(() => SubRef));

export const Sub = types
  .model("Sub", {
    subId: types.identifier(types.string),
    nodes: types.map(types.array(SubNode))
  })
  .views(self => ({
    get val() {
      return self;
    },
    with() {
      return self.val;
    }
  }));

export const SubRef = types
  .model("SubRef", {
    subRef: types.reference(Sub)
  })
  .views(self => ({
    get val() {
      return self.subRef;
    },
    with() {
      return self.val;
    }
  }));

export const Label = types.model("Label", {
  labelId: types.identifier(types.string), // TODO: labels should have own id, not that of link!
  text: optionalString,
  targetId: optionalString,
  groupId: optionalString,
  locale: optionalString
});

export const Comment = types.model("Post", {
  postId: types.identifier(types.string),
  text: optionalString,
  targetId: optionalString
});

const dirUp = "UP";
const dirDown = "DOWN";
const dirLeft = "LEFT";
const dirRight = "RIGHT";

export const RepoView = types
  .model("RepoView", {
    rootLink: types.string,
    selectedLink: types.maybe(types.string),
    selectedNode: types.maybe(types.number, 0),
    expandedLinks: optionalMap(types.boolean),
    labelGroup: types.optional(types.string, "standard")
  })
  .views(self => ({
    get isPending() {
      for (const node of self.nodes) {
        const nodeType = getType(node);
        if (nodeType === Input) {
          return true;
        }
        if (nodeType === LinkRef && node.ref.isPending) {
          return true;
        }
      }
      return false;
    },
    display(
      repo,
      link = repo.links.get(self.rootLink),
      base = {
        x: 0,
        y: 10,
        nextIsRef: false,
        isLast: true,
        root: true
      }
    ) {
      const { selectedLink, selectedNode } = self;
      const { linkId, nodes } = link;
      let { x, y, nextIsRef, isLast, path = [linkId], root } = base;

      let allNodes = [];
      for (let i = 0; i < nodes.length; i++) {
        const node = nodes[i];
        const nodeType = getType(node);
        const base = {
          path: [...path, `I${i}`],
          x,
          y: y - 1,
          size: 1,
          root: false,
          selected: linkId == selectedLink && i !== null && i === selectedNode
        };

        switch (nodeType) {
          case Op:
            allNodes.push({
              ...base,
              color: opColor,
              text: node.op
            });
            x++;
            break;
          case Val:
            const { val } = node;
            allNodes.push({
              ...base,
              color: valColor,
              text: typeof val === "string" ? `"${val}"` : val
            });
            x++;
            break;
          case Input:
            allNodes.push({
              ...base,
              color: inputColor,
              text: node.input
            });
            x++;
            break;
          case PackageRef:
            allNodes.push({
              ...base,
              color: packageColor,
              text: node.path
            });
            x++;
            break;
          case LinkRef:
            const isLast = i === nodes.length - 1;
            const innerPath = [...path, node.ref.linkId];
            const refChildNodes = self.display(repo, node.ref, {
              path: innerPath,
              x,
              y: y - 1,
              nextIsRef: !isLast && getType(nodes[i + 1]) === LinkRef,
              isLast
            });
            allNodes.push(...refChildNodes);

            const { size } = refChildNodes[refChildNodes.length - 1];
            x += size;
            break;
          default:
            allNodes.push({ ...base, color: unknownColor });
            x++;
        }
      }

      const label = resolveIdentifier(Label, repo, link.linkId);
      const thisSize = nextIsRef
        ? Math.max(...allNodes.map(n => n.x)) - base.x + 2
        : isLast ? Math.max(...allNodes.map(n => n.x + n.size)) - base.x : 1;

      const thisNode = {
        path,
        x: base.x,
        y,
        size: thisSize,
        color: pendingColor, //self.isPending ? pendingColor : valColor,
        text: (label && label.text) || `(${self.linkId})`,
        link: true
      };
      allNodes.push(thisNode);

      if (root) {
        const existingKeys = {};
        let i = allNodes.length;
        while (i--) {
          const node = allNodes[i];
          const { path } = node;
          let j = path.length - 1;
          let currentKey = "" + (j in path ? path[j] : "");
          while (existingKeys[currentKey]) {
            j--;
            currentKey += "/" + (j in path ? path[j] : "");
          }
          existingKeys[currentKey] = true;
          node.key = currentKey;
        }
      }

      return allNodes;
    }
  }))
  .actions(self => ({
    move(dir) {}
  }));

export const Repo = types
  .model("Repo", {
    packages: optionalMap(Package),
    links: optionalMap(types.union(Link, Call)),
    subs: optionalMap(Sub),
    linkLabelSets: optionalMap(optionalMap(Label)),
    linkComments: optionalMap(Comment),
    subLabels: optionalMap(Label),
    subComments: optionalMap(Comment),
    branchLabels: optionalMap(Label),
    branchComments: optionalMap(Comment)
  })
  .actions(self => ({
    expandSub(subId, baseId, ...params) {
      const { nodes } = self.subs.get(subId);

      let inputCounter = 0;
      nodes.forEach((subLink, i) => {
        const linkNodes = subLink.map(node => {
          const nodeType = getType(node);
          const { val } = node;
          switch (nodeType) {
            case SubParam:
              return params[val];
            case SubLink:
              return { ref: `${baseId}-${val}` };
            case LinkRef:
              const retVal = { ref: node.ref.linkId };
              return retVal;
            default:
              return val;
          }
        });

        self.links.put({ linkId: `${baseId}-${i}`, nodes: linkNodes });
      });
    }
  }));
<commit_msg>chore: movement actions boilerplate<commit_after>import { types, getEnv, getRoot, getType, resolveIdentifier, process } from "mobx-state-tree";
import { isObservableMap } from "mobx";
import { curry, ary } from "lodash";

const optionalString = types.optional(types.string, "");
const optionalMap = type => types.optional(types.map(type), {});

export const reserved = "􂳰";
export const linkKey = "􂳰L";
export const opKey = "􂳰O";
export const valKey = "􂳰V";
export const inputKey = "􂳰I";
export const linkRefKey = "􂳰R";
export const packageKey = "􂳰P";

export const lodash = "_";

export const global = "g";

export const access = ".";

export const array = "[";
export const object = "{";

export const add = "+";
export const subtract = "-";
export const multiply = "*";
export const divide = "/";
export const mod = "%";

export const ifOp = "?";
export const switchOp = "s";
export const forOp = "f";
export const importOp = "m";
export const newOp = "n";
export const typeofOp = "t";
export const instanceOfOp = "i";
export const classOp = "c";
export const thisOp = "h";

export const lessThan = "<";
export const greaterThan = ">";
export const lessThanOrEqual = "<=";
export const greaterThanOrEqual = ">=";
export const equal = "==";
export const strictEqual = "===";
export const notEqual = "!=";
export const notStrictEqual = "!==";

export const swap = "@";

const opFuncs = {
  [global](val) {
    return window[val];
    // return eval(val);
  },
  [access](obj, key) {
    return obj[key];
  },
  [add](...nums) {
    let sum = 0;
    for (const num of nums) {
      sum += num;
    }
    return sum;
  },
  [array](...items) {
    return items;
  },
  [lodash]() {
    // TODO: remove
    return _;
  },
  ifOp(condition, trueVal, falseVal) {
    return condition ? trueVal : falseVal;
  },
  switchOp(context, switcher, ...casePairs) {
    for (let i = 0; i < casePairs.length; i += 2) {
      if (switcher === casePairs[i]) {
        return casePairs[i + 1](context);
      }
    }
  }
};

export const Val = types
  .model("Val", {
    val: types.union(types.string, types.number, types.boolean, types.null)
  })
  .views(self => ({
    with() {
      return self.val;
    }
  }));

export const Op = types
  .model("Op", {
    op: types.enumeration("OpEnum", [
      lodash,
      global,
      access,
      array,
      object,
      add,
      subtract,
      multiply,
      divide,
      mod,
      ifOp,
      switchOp,
      forOp,
      importOp,
      newOp,
      typeofOp,
      instanceOfOp,
      classOp,
      thisOp,
      lessThan,
      greaterThan,
      lessThanOrEqual,
      greaterThanOrEqual,
      equal,
      strictEqual,
      notEqual,
      notStrictEqual,
      swap
    ])
  })
  .views(self => ({
    get val() {
      return opFuncs[self.op];
    },
    with() {
      return self.val;
    }
  }));

export const Package = types
  .model("Package", {
    id: types.identifier(types.number),
    path: types.string,
    resolved: false
  })
  .actions(self => {
    const { system } = getEnv(self);

    return {
      afterCreate: process(function*() {
        yield system.import(self.path);
        // TODO: error handling (retry?)
        self.resolved = true;
      })
    };
  })
  .views(self => {
    const { system } = getEnv(self);

    return {
      get val() {
        if (self.resolved) {
          return system.get(self.path);
        }
        return Package;
      },
      with() {
        return self.val;
      }
    };
  });

export const PackageRef = types
  .model("PackageRef", {
    pkg: types.reference(Package)
  })
  .views(self => ({
    get val() {
      return self.pkg.val;
    },
    with() {
      return self.val;
    }
  }));

// TYPE-CEPTION
export const stringType = "s";
export const numType = "n";
export const boolType = "b";
export const anyType = "a";
export const InputType = types.enumeration("InputType", [stringType, numType, boolType, anyType]);

// is there a better way of doing this?
class Hole {
  constructor(...inputSets) {
    this.inputs = {};

    for (const inputSet of inputSets) {
      for (const input in inputSet) {
        this.inputs[input] = true;
      }
    }
  }
}

export const Input = types
  .model("Input", {
    input: types.identifier(types.string),
    type: types.maybe(InputType, anyType)
  })
  .views(self => ({
    get val() {
      return Input;
    },
    with(inputs) {
      const { input } = self;
      if (inputs && inputs.has(input)) {
        const mapValue = inputs.get(input);
        if (isObservableMap(inputs)) {
          return mapValue.val;
        } else {
          return mapValue;
        }
      } else {
        return new Hole({ [input]: true });
      }
    }
  }));

curry.placeholder = Input;

export const Node = types.union(Val, Op, Input, types.late(() => LinkRef), types.late(() => SubRef), PackageRef);

const identity = x => x;

const baseColor = ",66%,55%)";
const opColor = `hsl(150${baseColor}`;
const valColor = `hsl(210${baseColor}`;
const inputColor = `hsl(25${baseColor}`;
const packageColor = `hsl(315${baseColor}`;
const pendingColor = `hsl(270${baseColor}`;
const unknownColor = `hsl(0${baseColor}`;

export const Link = types
  .model("Link", {
    linkId: types.identifier(types.string),
    nodes: types.array(Node)
  })
  .views(self => ({
    derive(nodeVals) {
      // NOTE: this is a pure function, would it be better to pull this out of the model?
      if (nodeVals.indexOf(Package) !== -1) {
        return Package;
      }

      const [head, ...nodeInputs] = nodeVals;

      if (typeof head === "function") {
        const inputs = nodeInputs.filter(input => input === Input);
        if (inputs.length) {
          const curried = curry(head, nodeInputs.length);
          return ary(curried(...nodeInputs), inputs.length);
        }
        return head(...nodeInputs);
      } else {
        return head;
      }
    },
    get val() {
      const nodeVals = self.nodes.map(node => node.val);
      return self.derive(nodeVals);
    },
    with(inputs) {
      const nodeVals = self.nodes.map(node => node.with(inputs));

      const holes = nodeVals.filter(val => val instanceof Hole);

      if (holes.length) {
        return new Hole(...holes.map(hole => hole.inputs));
      }

      return self.derive(nodeVals);
    }
  }));

export const LinkRef = types
  .model("LinkRef", {
    ref: types.reference(Link)
  })
  .views(self => ({
    get val() {
      return self.ref.val;
    },
    with() {
      return self.val;
    }
  }));

export const Call = types
  .model("Call", {
    callId: types.identifier(types.string),
    link: types.reference(Link),
    inputs: optionalMap(Node)
  })
  .views(self => ({
    get val() {
      const linkVal = self.link.with(self.inputs);
      if (linkVal instanceof Hole) {
        const inputEntries = self.inputs.entries().slice();
        const holeInputIds = Object.keys(linkVal.inputs);

        return (...newInputs) => {
          const newInputEntries = newInputs.map((input, i) => [holeInputIds[i], input]);
          const allInputEntries = [...inputEntries, ...newInputEntries];
          const allInputs = new Map(allInputEntries);
          return self.nodes.with(allInputs);
        };
      }

      return linkVal;
    },
    with() {
      return self.val;
    }
  }));

export const SubParam = types
  .model("SubParam", {
    param: types.number
  })
  .views(self => ({
    get val() {
      return self.param;
    },
    with() {
      return self.val;
    }
  }));

export const SubLink = types
  .model("SubLink", {
    subLink: types.number
  })
  .views(self => ({
    get val() {
      return self.subLink;
    },
    with() {
      return self.val;
    }
  }));

export const SubNode = types.union(Val, Op, Input, LinkRef, SubParam, SubLink, types.late(() => SubRef));

export const Sub = types
  .model("Sub", {
    subId: types.identifier(types.string),
    nodes: types.map(types.array(SubNode))
  })
  .views(self => ({
    get val() {
      return self;
    },
    with() {
      return self.val;
    }
  }));

export const SubRef = types
  .model("SubRef", {
    subRef: types.reference(Sub)
  })
  .views(self => ({
    get val() {
      return self.subRef;
    },
    with() {
      return self.val;
    }
  }));

export const Label = types.model("Label", {
  labelId: types.identifier(types.string), // TODO: labels should have own id, not that of link!
  text: optionalString,
  targetId: optionalString,
  groupId: optionalString,
  locale: optionalString
});

export const Comment = types.model("Post", {
  postId: types.identifier(types.string),
  text: optionalString,
  targetId: optionalString
});

const dirUp = "UP";
const dirDown = "DOWN";
const dirLeft = "LEFT";
const dirRight = "RIGHT";

export const RepoView = types
  .model("RepoView", {
    rootLink: types.string,
    selectedLink: types.maybe(types.string),
    selectedNode: types.maybe(types.number, 0),
    expandedLinks: optionalMap(types.boolean),
    labelGroup: types.optional(types.string, "standard")
  })
  .views(self => ({
    get isPending() {
      for (const node of self.nodes) {
        const nodeType = getType(node);
        if (nodeType === Input) {
          return true;
        }
        if (nodeType === LinkRef && node.ref.isPending) {
          return true;
        }
      }
      return false;
    },
    display(
      repo,
      link = repo.links.get(self.rootLink),
      base = {
        x: 0,
        y: 10,
        nextIsRef: false,
        isLast: true,
        root: true
      }
    ) {
      const { selectedLink, selectedNode } = self;
      const { linkId, nodes } = link;
      let { x, y, nextIsRef, isLast, path = [linkId], root } = base;

      let allNodes = [];
      for (let i = 0; i < nodes.length; i++) {
        const node = nodes[i];
        const nodeType = getType(node);
        const base = {
          path: [...path, `I${i}`],
          x,
          y: y - 1,
          size: 1,
          root: false,
          selected: linkId == selectedLink && i !== null && i === selectedNode
        };

        switch (nodeType) {
          case Op:
            allNodes.push({
              ...base,
              color: opColor,
              text: node.op
            });
            x++;
            break;
          case Val:
            const { val } = node;
            allNodes.push({
              ...base,
              color: valColor,
              text: typeof val === "string" ? `"${val}"` : val
            });
            x++;
            break;
          case Input:
            allNodes.push({
              ...base,
              color: inputColor,
              text: node.input
            });
            x++;
            break;
          case PackageRef:
            allNodes.push({
              ...base,
              color: packageColor,
              text: node.path
            });
            x++;
            break;
          case LinkRef:
            const isLast = i === nodes.length - 1;
            const innerPath = [...path, node.ref.linkId];
            const refChildNodes = self.display(repo, node.ref, {
              path: innerPath,
              x,
              y: y - 1,
              nextIsRef: !isLast && getType(nodes[i + 1]) === LinkRef,
              isLast
            });
            allNodes.push(...refChildNodes);

            const { size } = refChildNodes[refChildNodes.length - 1];
            x += size;
            break;
          default:
            allNodes.push({ ...base, color: unknownColor });
            x++;
        }
      }

      const label = resolveIdentifier(Label, repo, link.linkId);
      const thisSize = nextIsRef
        ? Math.max(...allNodes.map(n => n.x)) - base.x + 2
        : isLast ? Math.max(...allNodes.map(n => n.x + n.size)) - base.x : 1;

      const thisNode = {
        path,
        x: base.x,
        y,
        size: thisSize,
        color: pendingColor, //self.isPending ? pendingColor : valColor,
        text: (label && label.text) || `(${self.linkId})`,
        link: true
      };
      allNodes.push(thisNode);

      if (root) {
        const existingKeys = {};
        let i = allNodes.length;
        while (i--) {
          const node = allNodes[i];
          const { path } = node;
          let j = path.length - 1;
          let currentKey = "" + (j in path ? path[j] : "");
          while (existingKeys[currentKey]) {
            j--;
            currentKey += "/" + (j in path ? path[j] : "");
          }
          existingKeys[currentKey] = true;
          node.key = currentKey;
        }
      }

      return allNodes;
    }
  }))
  .actions(self => ({
    move(dir) {},
    up() {},
    down() {}
  }))
  .actions(self => {
    const handleKeyUp = e => {
      const { keyCode } = e;
      switch (keyCode) {
        case 37: // LEFT
          e.preventDefault();
          self.move(-1);
          break;
        case 39: // RIGHT
          e.preventDefault();
          self.move(+1);
          break;
        case 38: // UP
          e.preventDefault();
          self.up();
          break;
        case 40: // DOWN
          e.preventDefault();
          self.down();
      }
    };

    return {
      afterCreate() {
        document.addEventListener("keyup", handleKeyUp);
      },
      beforeDestroy() {
        document.removeEventListener("keyup", handleKeyUp);
      }
    };
  });

export const Repo = types
  .model("Repo", {
    packages: optionalMap(Package),
    links: optionalMap(types.union(Link, Call)),
    subs: optionalMap(Sub),
    linkLabelSets: optionalMap(optionalMap(Label)),
    linkComments: optionalMap(Comment),
    subLabels: optionalMap(Label),
    subComments: optionalMap(Comment),
    branchLabels: optionalMap(Label),
    branchComments: optionalMap(Comment)
  })
  .actions(self => ({
    expandSub(subId, baseId, ...params) {
      const { nodes } = self.subs.get(subId);

      let inputCounter = 0;
      nodes.forEach((subLink, i) => {
        const linkNodes = subLink.map(node => {
          const nodeType = getType(node);
          const { val } = node;
          switch (nodeType) {
            case SubParam:
              return params[val];
            case SubLink:
              return { ref: `${baseId}-${val}` };
            case LinkRef:
              const retVal = { ref: node.ref.linkId };
              return retVal;
            default:
              return val;
          }
        });

        self.links.put({ linkId: `${baseId}-${i}`, nodes: linkNodes });
      });
    }
  }));
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

foam.CLASS({
  refines: 'foam.core.Property',
  properties: [
    {
      name: 'tableFormatter',
      value: function(obj) {
        return obj[this.name];
      }
    }
  ]
});

foam.CLASS({
  package: 'foam.u2',
  name: 'TableBody',
  extends: 'foam.u2.Element',

  properties: [
    [ 'nodeName', 'tbody' ],
    [ 'properties_' ]
  ],

  methods: [
    function addObj(obj) {
      var e = this.start('tr')
      for ( var j = 0 ; j < this.properties_.length ; j++ ) {
        var prop = this.properties_[j];
        e = e.start('td').add(prop.tableFormatter(obj, e)).end();
      }
      e.end();
    }
  ]
});

foam.CLASS({
  package: 'foam.u2',
  name: 'TableBodySink',
  implements: ['foam.dao.Sink'],
  requires: [
    'foam.u2.TableBody'
  ],
  properties: [
    'properties_',
    {
      name: 'body',
      factory: function() { return this.TableBody.create({ properties_: this.properties_ }); }
    }
  ],
  methods: [
    function put(obj) {
      this.body.addObj(obj);
    }
  ]
});

foam.CLASS({
  package: 'foam.u2',
  name: 'TableView',
  extends: 'foam.u2.Element',

  properties: [
    {
      class: 'Class2',
      name: 'of'
    },
    [ 'nodeName', 'table' ],
    {
      name: 'properties_',
      expression: function(properties, of) {
        var cls = this.of$cls;
        return properties.map(function(p) { return cls.getAxiomByName(p); });
      }
    },
    {
      name: 'properties',
      expression: function(of) {
        if ( ! this.of$cls ) return undefined;

        var tableProperties = this.of$cls.getAxiomByName('tableProperties');

        if ( tableProperties ) return tableProperties.properties;

        return this.of$cls.getAxiomsByClass(foam.core.Property)
            .filter(function(p) { return ! p.hidden; })
            .map(foam.core.Property.NAME.f)
      }
    },
    {
      name: 'data',
      postSet: function(old, nu) {
        old && old.on.unsub(this.onDAOUpdate);
        nu && nu.on.sub(this.onDAOUpdate);
        this.onDAOUpdate();
      }
    },
    {
      name: 'header',
      expression: function(properties_) {
        var E = this.E('thead');
        var e = E;

        if ( ! properties_ ) {
          return e.add("'of' or 'properties' is required for table view configuration.");
        }

        e = e.start('tr');
        for ( var i = 0 ; i < properties_.length ; i++ ) {
          e = e.start('td').add(properties_[i].label).end();
        }
        e = e.end();

        return E;
      }
    },
    {
      name: 'body',
      factory: function() { return this.E('tbody'); }
    }
  ],

  methods: [
    function initE() {
      this.onDAOUpdate();
      return this.add(this.header$, this.body$);
    }
  ],

  listeners: [
    {
      name: 'onDAOUpdate',
      isFramed: true,
      code: function() {
        this.data.select(foam.u2.TableBodySink.create({ properties_: this.properties_ }, this)).then(
          function(a) { this.body = a.body; }.bind(this));
      }
    }
  ]
});
<commit_msg>TableView: Rename tableFormatter to tableCellView<commit_after>/**
 * @license
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

foam.CLASS({
  package: 'foam.u2',
  name: 'TableCellRefinement',
  refines: 'foam.core.Property',
  properties: [
    {
      name: 'tableCellView',
      value: function(obj) {
        return obj[this.name];
      }
    }
  ]
});

foam.CLASS({
  package: 'foam.u2',
  name: 'TableBody',
  extends: 'foam.u2.Element',

  requires: [
    'foam.u2.TableCellRefinement'
  ],

  properties: [
    [ 'nodeName', 'tbody' ],
    [ 'properties_' ]
  ],

  methods: [
    function addObj(obj) {
      var e = this.start('tr')
      for ( var j = 0 ; j < this.properties_.length ; j++ ) {
        var prop = this.properties_[j];
        e = e.start('td').add(prop.tableCellView(obj, e)).end();
      }
      e.end();
    }
  ]
});

foam.CLASS({
  package: 'foam.u2',
  name: 'TableBodySink',
  implements: ['foam.dao.Sink'],
  requires: [
    'foam.u2.TableBody'
  ],
  properties: [
    'properties_',
    {
      name: 'body',
      factory: function() { return this.TableBody.create({ properties_: this.properties_ }); }
    }
  ],
  methods: [
    function put(obj) {
      this.body.addObj(obj);
    }
  ]
});

foam.CLASS({
  package: 'foam.u2',
  name: 'TableView',
  extends: 'foam.u2.Element',

  properties: [
    {
      class: 'Class2',
      name: 'of'
    },
    [ 'nodeName', 'table' ],
    {
      name: 'properties_',
      expression: function(properties, of) {
        var cls = this.of$cls;
        return properties.map(function(p) { return cls.getAxiomByName(p); });
      }
    },
    {
      name: 'properties',
      expression: function(of) {
        if ( ! this.of$cls ) return undefined;

        var tableProperties = this.of$cls.getAxiomByName('tableProperties');

        if ( tableProperties ) return tableProperties.properties;

        return this.of$cls.getAxiomsByClass(foam.core.Property)
            .filter(function(p) { return ! p.hidden; })
            .map(foam.core.Property.NAME.f)
      }
    },
    {
      name: 'data',
      postSet: function(old, nu) {
        old && old.on.unsub(this.onDAOUpdate);
        nu && nu.on.sub(this.onDAOUpdate);
        this.onDAOUpdate();
      }
    },
    {
      name: 'header',
      expression: function(properties_) {
        var E = this.E('thead');
        var e = E;

        if ( ! properties_ ) {
          return e.add("'of' or 'properties' is required for table view configuration.");
        }

        e = e.start('tr');
        for ( var i = 0 ; i < properties_.length ; i++ ) {
          e = e.start('td').add(properties_[i].label).end();
        }
        e = e.end();

        return E;
      }
    },
    {
      name: 'body',
      factory: function() { return this.E('tbody'); }
    }
  ],

  methods: [
    function initE() {
      this.onDAOUpdate();
      return this.add(this.header$, this.body$);
    }
  ],

  listeners: [
    {
      name: 'onDAOUpdate',
      isFramed: true,
      code: function() {
        this.data.select(foam.u2.TableBodySink.create({ properties_: this.properties_ }, this)).then(
          function(a) { this.body = a.body; }.bind(this));
      }
    }
  ]
});
<|endoftext|>


<commit_before>!( function( factory ) {
  if ( typeof define === "function" && define.amd ) {
    define(factory );
  } else {
    factory( );
  }
}(function( ){

  // Code form Zepto.js
  // @see https://github.com/madrobby/zepto/blob/master/src/form.js#files
  var serializeArray = function() {
    var name, type, result = [],
        add = function(value) {
          if (value.forEach) return value.forEach(add)
          result.push({ name: name, value: value })
        };

    [].slice.apply(this.elements).forEach(function(field) {

      type = field.type, name = field.name
      if (name && field.nodeName.toLowerCase() !== 'fieldset' &&
        !field.disabled && type !== 'submit' && type !== 'reset' && type !== 'button' && type !== 'file' &&
        ((type !== 'radio' && type !== 'checkbox') || field.checked))
          add(field.value)
    })
    return result
  }

  var serialize = function(){
    var result = []
    serializeArray.call(this).forEach(function(elm){
      result.push(encodeURIComponent(elm.name) + '=' + encodeURIComponent(elm.value))
    })
    return result.join('&')
  }

  // keys: ["a", ""]
  // ["a", "b", "c"], ["a", "b", "d"]
  // types: "string", "array", "number", "bool", "object"
  //
  // TEST
  // form.json
  // input(name='a')
  // input(name='images.')
  // input(name='images.')
  // input(name='b.b')
  // input(name='c.c.:number')
  // input(name='c.c.')
  // input(type='submit')
  //
  var submitHandler = function(e, options, action) {
    e.preventDefault();

    var self = this;
    var method = self.getAttribute('method') || 'POST';
    var res;

    if (method === "GET") {
      res = serialize.call(self);
    } else {

      res = {};
      serializeArray.call(self).forEach(function(t){
        var keys  = t.name.split('.');
        var len   = keys.length - 1;
        var index = keys[len].indexOf(':');
        var value = t.value;
        var type;
        if (index !== -1) {
          type    = keys[len].substr(index + 1);
          keys[len] = keys[len].substr(0, index);
        } else {
          type = 'string';
        }

        if (type === 'array' || type === 'object') {

          value  = JSON.parse(value);

        } else if (type === 'number') {

          value = +value;

        } else if (type === 'time') {
          value = new Date(value).getTime();

        } else if (type === 'bool') {
          if (value === 'false')
            value = false
          else
            value = !!value;

        }

        deepSet(res, keys, value);
      });

      res = options.data.call(self, res);
      res = JSON.stringify(res);
    }

    /**
     * If there are no data should be sent, just return.
     */
    if (res === 'null') {
      return;
    }

    /**
     *
     * AJAX request
     *
     */
    var xmlHttp = new XMLHttpRequest();
    /**
     * Add session header for cross-domain request.
     * You can't set cookies for ajax
     * and you have to response #options request# like:
     * "Access-Control-Allow-Headers: X-AVOSCloud-Session-Token"
     * before you send it.
     * */
    var session = document.cookie.match(/sessionToken=([^;]*)(;|$)/);
    action = (action === undefined ? self.getAttribute('action') : action);

    if (method === 'GET')
      action += '?' + res;

    xmlHttp.open(method, action, true);
    xmlHttp.setRequestHeader('Content-Type', 'application/json');
    if (session) {
      xmlHttp.setRequestHeader('X-AVOSCloud-Session-Token', session[1])
    }
    xmlHttp.responseType = 'json';
    xmlHttp.onreadystatechange = function() {
      if (xmlHttp.readyState === 4) {
        if (xmlHttp.status >= 200 && xmlHttp.status < 300) {
          options.ended.call(self, xmlHttp.response, xmlHttp)
        } else {
          options.error.call(self, xmlHttp);
        }
      }
    }

    if (method === 'GET')
      xmlHttp.send();
    else
      xmlHttp.send(res);
  }

  /**
   * Set obj's value by keys
   * @param  {[object]}           obj   The target you want to set.
   * @param  {[array]}            keys  The value's path.
   * @param  {[string, array...]} value Target's value.
   * @return {[object]}                 The target after setting value.
   *
   * Example: obj = {'a':'a'}, keys = ['b','bb'], value = 'b-value'
   * return {
   *         'a': 'a',
   *         'b': {
   *           'bb': 'b-value'
   *          }
   *        }
   */
  var deepSet = function(obj, keys, value) {

    var curKey = keys[0];
    if(keys.length === 1) {

      curKey === '' ? obj.push(value) : obj[curKey] = value;

      return;
    }
    if (keys.length > 1) {
      if (typeof obj[curKey] === 'undefined')
        obj[curKey] = keys[1] === '' ? [] : {};
    }

    var o = obj[curKey];
    keys.shift();
    return deepSet(o, keys, value);
  }

  /**
   * Example:
   * <form action='/action/a'>
   * <input type='submit'>
   * <input type='submit' formAction='/action/b'>
   * </form>
   */
  var formAction;
  document.addEventListener('click', function(e) {
    var target = e.target;

    if (target.type === 'submit' && target.formAction) {
      formAction = target.formAction;
    }

    setTimeout(function() {
      formAction = undefined;
    }, 1000);

  })

  /**
   * Submit form's handler.
   * Example:
   * <form data-role='formJSON'>
   * </form>
   */
  document.addEventListener('submit', function(e) {

    var target = e.target;
    if (target.getAttribute('data-role') === 'formJSON') {

      var temp = (temp = target.getAttribute('data-target')) && document.querySelector(temp);

      var options = {
        ended: target.onended || ( temp && temp.onended ) || function(){},
        // to change data
        data: target._data || ( temp && temp._data ) || function(d){return d},
        error: target.onerror || ( temp && temp.onerror ) || function(){}
      };

      submitHandler.call(target, e, options, formAction);
    }

  })

  // Fix.
  // Submit a form by javascript won't fire submit event.
  // @see http://stackoverflow.com/questions/12819357/form-submitted-using-submit-from-a-link-cannot-be-caught-by-onsubmit-handler

  var _submit = HTMLFormElement.prototype.submit;
  HTMLFormElement.prototype.submit = function() {

    if (this.getAttribute('data-role') === 'formJSON') {
      this.dispatchEvent(new Event('submit', {bubbles: true}));
    } else {
      _submit.call(this);
    }
  }

  return null;

}));
<commit_msg>fix get method's bug<commit_after>!( function( factory ) {
  if ( typeof define === "function" && define.amd ) {
    define(factory );
  } else {
    factory( );
  }
}(function( ){

  // Code form Zepto.js
  // @see https://github.com/madrobby/zepto/blob/master/src/form.js#files
  var serializeArray = function() {
    var name, type, result = [],
        add = function(value) {
          if (value.forEach) return value.forEach(add)
          result.push({ name: name, value: value })
        };

    [].slice.apply(this.elements).forEach(function(field) {

      type = field.type, name = field.name
      if (name && field.nodeName.toLowerCase() !== 'fieldset' &&
        !field.disabled && type !== 'submit' && type !== 'reset' && type !== 'button' && type !== 'file' &&
        ((type !== 'radio' && type !== 'checkbox') || field.checked))
          add(field.value)
    })
    return result
  }

  var serialize = function(){
    var result = []
    serializeArray.call(this).forEach(function(elm){
      result.push(encodeURIComponent(elm.name) + '=' + encodeURIComponent(elm.value))
    })
    return result.join('&')
  }

  // keys: ["a", ""]
  // ["a", "b", "c"], ["a", "b", "d"]
  // types: "string", "array", "number", "bool", "object"
  //
  // TEST
  // form.json
  // input(name='a')
  // input(name='images.')
  // input(name='images.')
  // input(name='b.b')
  // input(name='c.c.:number')
  // input(name='c.c.')
  // input(type='submit')
  //
  var submitHandler = function(e, options, action) {
    e.preventDefault();

    var self = this;
    var method = self.getAttribute('method') || 'POST';
    var res;

    if (method === "GET") {
      res = serialize.call(self);
    } else {

      res = {};
      serializeArray.call(self).forEach(function(t){
        var keys  = t.name.split('.');
        var len   = keys.length - 1;
        var index = keys[len].indexOf(':');
        var value = t.value;
        var type;
        if (index !== -1) {
          type    = keys[len].substr(index + 1);
          keys[len] = keys[len].substr(0, index);
        } else {
          type = 'string';
        }

        if (type === 'array' || type === 'object') {

          value  = JSON.parse(value);

        } else if (type === 'number') {

          value = +value;

        } else if (type === 'time') {
          value = new Date(value).getTime();

        } else if (type === 'bool') {
          if (value === 'false')
            value = false
          else
            value = !!value;

        }

        deepSet(res, keys, value);
      });

      res = options.data.call(self, res);
      res = JSON.stringify(res);
    }

    /**
     * If there are no data should be sent, just return.
     */
    if (res === 'null') {
      return;
    }

    /**
     *
     * AJAX request
     *
     */
    var xmlHttp = new XMLHttpRequest();
    /**
     * Add session header for cross-domain request.
     * You can't set cookies for ajax
     * and you have to response #options request# like:
     * "Access-Control-Allow-Headers: X-AVOSCloud-Session-Token"
     * before you send it.
     * */
    var session = document.cookie.match(/sessionToken=([^;]*)(;|$)/);
    action = (action === undefined ? self.getAttribute('action') : action);

    if (method === 'GET') {
      action += action.indexOf('?') === -1 ? ('?' + res) : ( '&' + res);
    }

    xmlHttp.open(method, action, true);
    xmlHttp.setRequestHeader('Content-Type', 'application/json');
    if (session) {
      xmlHttp.setRequestHeader('X-AVOSCloud-Session-Token', session[1])
    }
    xmlHttp.responseType = 'json';
    xmlHttp.onreadystatechange = function() {
      if (xmlHttp.readyState === 4) {
        if (xmlHttp.status >= 200 && xmlHttp.status < 300) {
          options.ended.call(self, xmlHttp.response, xmlHttp)
        } else {
          options.error.call(self, xmlHttp);
        }
      }
    }

    if (method === 'GET')
      xmlHttp.send();
    else
      xmlHttp.send(res);
  }

  /**
   * Set obj's value by keys
   * @param  {[object]}           obj   The target you want to set.
   * @param  {[array]}            keys  The value's path.
   * @param  {[string, array...]} value Target's value.
   * @return {[object]}                 The target after setting value.
   *
   * Example: obj = {'a':'a'}, keys = ['b','bb'], value = 'b-value'
   * return {
   *         'a': 'a',
   *         'b': {
   *           'bb': 'b-value'
   *          }
   *        }
   */
  var deepSet = function(obj, keys, value) {

    var curKey = keys[0];
    if(keys.length === 1) {

      curKey === '' ? obj.push(value) : obj[curKey] = value;

      return;
    }
    if (keys.length > 1) {
      if (typeof obj[curKey] === 'undefined')
        obj[curKey] = keys[1] === '' ? [] : {};
    }

    var o = obj[curKey];
    keys.shift();
    return deepSet(o, keys, value);
  }

  /**
   * Example:
   * <form action='/action/a'>
   * <input type='submit'>
   * <input type='submit' formAction='/action/b'>
   * </form>
   */
  var formAction;
  document.addEventListener('click', function(e) {
    var target = e.target;

    if (target.type === 'submit' && target.formAction) {
      formAction = target.formAction;
    }

    setTimeout(function() {
      formAction = undefined;
    }, 1000);

  })

  /**
   * Submit form's handler.
   * Example:
   * <form data-role='formJSON'>
   * </form>
   */
  document.addEventListener('submit', function(e) {

    var target = e.target;
    if (target.getAttribute('data-role') === 'formJSON') {

      var temp = (temp = target.getAttribute('data-target')) && document.querySelector(temp);

      var options = {
        ended: target.onended || ( temp && temp.onended ) || function(){},
        // to change data
        data: target._data || ( temp && temp._data ) || function(d){return d},
        error: target.onerror || ( temp && temp.onerror ) || function(){}
      };

      submitHandler.call(target, e, options, formAction);
    }

  })

  // Fix.
  // Submit a form by javascript won't fire submit event.
  // @see http://stackoverflow.com/questions/12819357/form-submitted-using-submit-from-a-link-cannot-be-caught-by-onsubmit-handler

  var _submit = HTMLFormElement.prototype.submit;
  HTMLFormElement.prototype.submit = function() {

    if (this.getAttribute('data-role') === 'formJSON') {
      this.dispatchEvent(new Event('submit', {bubbles: true}));
    } else {
      _submit.call(this);
    }
  }

  return null;

}));
<|endoftext|>


<commit_before>!( function( factory ) {
  if ( typeof define === "function" && define.amd ) {
    define(factory );
  } else {
    factory( );
  }
}(function( ){

  // Code form Zepto.js
  // @see https://github.com/madrobby/zepto/blob/master/src/form.js#files
  var serializeArray = function() {
    var name, type, result = [],
        add = function(value) {
          if (value.forEach) return value.forEach(add)
          result.push({ name: name, value: value })
        };

    [].slice.apply(this.elements).forEach(function(field) {

      type = field.type, name = field.name
      if (name && field.nodeName.toLowerCase() !== 'fieldset' &&
        !field.disabled && type !== 'submit' && type !== 'reset' && type !== 'button' && type !== 'file' &&
        ((type !== 'radio' && type !== 'checkbox') || field.checked))
          add(field.value)
    })
    return result
  }

  var serialize = function(){
    var result = []
    serializeArray.call(this).forEach(function(elm){
      result.push(encodeURIComponent(elm.name) + '=' + encodeURIComponent(elm.value))
    })
    return result.join('&')
  }
    /**
   * Set obj's value by keys
   * @param  {[object]}           obj   The target you want to set.
   * @param  {[array]}            keys  The value's path.
   * @param  {[string, array...]} value Target's value.
   * @return {[object]}                 The target after setting value.
   *
   * Example: obj = {'a':'a'}, keys = ['b','bb'], value = 'b-value'
   * return {
   *         'a': 'a',
   *         'b': {
   *           'bb': 'b-value'
   *          }
   *        }
   */
  var deepSet = function(obj, keys, value) {

    var curKey = keys[0];
    if(keys.length === 1) {

      curKey === '' ? obj.push(value) : obj[curKey] = value;

      return;
    }
    if (keys.length > 1) {
      if (typeof obj[curKey] === 'undefined')
        obj[curKey] = keys[1] === '' ? [] : {};
    }

    var o = obj[curKey];
    keys.shift();
    return deepSet(o, keys, value);
  }

  var integerKeysAsArrayIndexes = function(obj, keys, value) {

    var allKeysIsInteger = true;
    var arr = [];
    var temp;
    keys = keys || [];
    value = value || obj;

    for (var key in value) {

      temp = keys.concat();

      if (isNaN(+key)) {
        allKeysIsInteger = false;
      } else {
        arr.push(value[key]);
      }
      temp.push(key);

      if ((typeof value[key] === 'object') && !Array.isArray(value[key])) {
        integerKeysAsArrayIndexes(obj, temp, value[key]);
      }
    }

    if (allKeysIsInteger) {

      if (keys.length === 0) {
        obj = arr;
      } else {
        deepSet(obj, keys, arr)
      }
    }
    return obj;
  }
  // TEST: integerKeysAsArrayIndexes
  // var json = integerKeysAsArrayIndexes({
  //   a: {
  //     0: {
  //       aa: "aa",
  //       bb: {
  //         0: "bb0",
  //         1: "bb1",
  //         3: "bb3"
  //       }
  //     },
  //     1: "a"
  //   },
  //   b: "b"
  // })
  // console.log(JSON.stringify(json));
  // var json = integerKeysAsArrayIndexes({
  //   0: "a",
  //   1: {
  //     "a": "b"
  //   }
  // })
  // console.log(JSON.stringify(json));

  // keys: ["a", ""]
  // ["a", "b", "c"], ["a", "b", "d"]
  // types: "string", "array", "number", "bool", "object"
  //
  // TEST
  // form.json
  // input(name='a')
  // input(name='images.')
  // input(name='images.')
  // input(name='b.b')
  // input(name='c.c.:number')
  // input(name='c.c.')
  // input(type='submit')
  //
  var submitHandler = function(e, options, action) {

    var self = this;
    var method = self.getAttribute('method') || 'POST';
    var res;

    if (method === "GET") {
      res = serialize.call(self);
    } else {

      res = {};
      serializeArray.call(self).forEach(function(t){
        var keys  = t.name.split('.');
        var len   = keys.length - 1;
        var index = keys[len].indexOf(':');
        var value = t.value;
        var type;
        if (index !== -1) {
          type    = keys[len].substr(index + 1);
          keys[len] = keys[len].substr(0, index);
        } else {
          type = 'string';
        }

        if (type === 'array' || type === 'object') {

          value  = JSON.parse(value);

        } else if (type === 'number') {

          value = +value;

        } else if (type === 'time') {
          value = new Date(value).getTime();

        } else if (type === 'bool' || type === 'boolean') {
          if (value === 'false')
            value = false
          else
            value = !!value;

        }

        deepSet(res, keys, value);
      });

      if (options.parseInteger)
        res = integerKeysAsArrayIndexes(res);
      res = options.data.call(self, res);
      res = JSON.stringify(res);
    }

    /**
     * If there are no data should be sent, just return.
     */
    if (res === 'null') {
      return;
    }

    /**
     *
     * AJAX request
     *
     */
    var xmlHttp = new XMLHttpRequest();
    /**
     * Add session header for cross-domain request.
     * You can't set cookies for ajax
     * and you have to response #options request# like:
     * "Access-Control-Allow-Headers: X-AVOSCloud-Session-Token"
     * before you send it.
     * */
    var session = document.cookie.match(/sessionToken=([^;]*)(;|$)/);
    action = (action === undefined ? self.getAttribute('action') : action);

    if (method === 'GET') {
      action += action.indexOf('?') === -1 ? ('?' + res) : ( '&' + res);
    }

    xmlHttp.open(method, action, true);
    xmlHttp.setRequestHeader('Content-Type', 'application/json');
    if (session) {
      xmlHttp.setRequestHeader('X-AVOSCloud-Session-Token', session[1])
    }

    xmlHttp.responseType = 'json';

    xmlHttp.onreadystatechange = function() {
      if (xmlHttp.readyState === 4) {
        if (xmlHttp.status >= 200 && xmlHttp.status < 300) {

          if (typeof xmlHttp.response === 'string')
            options.ended.call(self, JSON.parse(xmlHttp.response), xmlHttp);
          else
            options.ended.call(self, xmlHttp.response, xmlHttp);

        } else {
          options.error.call(self, xmlHttp);
        }
      }
    }

    if (method === 'GET')
      xmlHttp.send();
    else
      xmlHttp.send(res);
  }

  /**
   * Example:
   * <form action='/action/a'>
   * <input type='submit'>
   * <input type='submit' formAction='/action/b'>
   * </form>
   */
  var formAction;
  document.addEventListener('click', function(e) {
    var target = e.target;

    if (target.type === 'submit' && target.formAction) {
      formAction = target.formAction;
    }

    setTimeout(function() {
      formAction = undefined;
    }, 1000);

  })

  /**
   * Submit form's handler.
   * Example:
   * <form data-role='formJSON'>
   * </form>
   */
  document.addEventListener('submit', function(e) {

    var target = e.target;
    if (target.getAttribute('data-role') === 'formJSON') {

      e.preventDefault();

      var temp = (temp = target.getAttribute('data-target')) && document.querySelector(temp);
      var parseInteger = target.getAttribute('data-parseInteger') === 'false' ? false : true;

      var options = {
        parseInteger: parseInteger,
        ended: target.onended || ( temp && temp.onended ) || function(){},
        // to change data
        data: target._data || ( temp && temp._data ) || function(d){return d},
        error: target.onerror || ( temp && temp.onerror ) || function(){}
      };

      submitHandler.call(target, e, options, formAction);

    }

  })

  // Fix.
  // Submit a form by javascript won't fire submit event.
  // @see http://stackoverflow.com/questions/12819357/form-submitted-using-submit-from-a-link-cannot-be-caught-by-onsubmit-handler

  var _submit = HTMLFormElement.prototype.submit;
  HTMLFormElement.prototype.submit = function() {

    if (this.getAttribute('data-role') === 'formJSON') {
      this.dispatchEvent(new Event('submit', {bubbles: true}));
    } else {
      _submit.call(this);
    }
  }

  return null;

}));
<commit_msg>Support json for GET method.<commit_after>!( function( factory ) {
  if ( typeof define === "function" && define.amd ) {
    define(factory );
  } else {
    factory( );
  }
}(function( ){

  // Code form Zepto.js
  // @see https://github.com/madrobby/zepto/blob/master/src/form.js#files
  var serializeArray = function() {
    var name, type, result = [],
        add = function(value) {
          if (value.forEach) return value.forEach(add)
          result.push({ name: name, value: value })
        };

    [].slice.apply(this.elements).forEach(function(field) {

      type = field.type, name = field.name
      if (name && field.nodeName.toLowerCase() !== 'fieldset' &&
        !field.disabled && type !== 'submit' && type !== 'reset' && type !== 'button' && type !== 'file' &&
        ((type !== 'radio' && type !== 'checkbox') || field.checked))
          add(field.value)
    })
    return result
  }

  var serialize = function(){
    var result = []
    serializeArray.call(this).forEach(function(elm){
      result.push(encodeURIComponent(elm.name) + '=' + encodeURIComponent(elm.value))
    })
    return result.join('&')
  }

  var serializeJSONForGET = function(){
    var result = []
    serializeArray.call(this).forEach(function(elm){
      result.push(encodeURIComponent(elm.name) + '=' + encodeURIComponent(elm.value))
    })
    return result.join('&')
  }

    /**
   * Set obj's value by keys
   * @param  {[object]}           obj   The target you want to set.
   * @param  {[array]}            keys  The value's path.
   * @param  {[string, array...]} value Target's value.
   * @return {[object]}                 The target after setting value.
   *
   * Example: obj = {'a':'a'}, keys = ['b','bb'], value = 'b-value'
   * return {
   *         'a': 'a',
   *         'b': {
   *           'bb': 'b-value'
   *          }
   *        }
   */
  var deepSet = function(obj, keys, value) {

    var curKey = keys[0];
    if(keys.length === 1) {

      curKey === '' ? obj.push(value) : obj[curKey] = value;

      return;
    }
    if (keys.length > 1) {
      if (typeof obj[curKey] === 'undefined')
        obj[curKey] = keys[1] === '' ? [] : {};
    }

    var o = obj[curKey];
    keys.shift();
    return deepSet(o, keys, value);
  }

  var integerKeysAsArrayIndexes = function(obj, keys, value) {

    var allKeysIsInteger = true;
    var arr = [];
    var temp;
    keys = keys || [];
    value = value || obj;

    for (var key in value) {

      temp = keys.concat();

      if (isNaN(+key)) {
        allKeysIsInteger = false;
      } else {
        arr.push(value[key]);
      }
      temp.push(key);

      if ((typeof value[key] === 'object') && !Array.isArray(value[key])) {
        integerKeysAsArrayIndexes(obj, temp, value[key]);
      }
    }

    if (allKeysIsInteger) {

      if (keys.length === 0) {
        obj = arr;
      } else {
        deepSet(obj, keys, arr)
      }
    }
    return obj;
  }
  // TEST: integerKeysAsArrayIndexes
  // var json = integerKeysAsArrayIndexes({
  //   a: {
  //     0: {
  //       aa: "aa",
  //       bb: {
  //         0: "bb0",
  //         1: "bb1",
  //         3: "bb3"
  //       }
  //     },
  //     1: "a"
  //   },
  //   b: "b"
  // })
  // console.log(JSON.stringify(json));
  // var json = integerKeysAsArrayIndexes({
  //   0: "a",
  //   1: {
  //     "a": "b"
  //   }
  // })
  // console.log(JSON.stringify(json));

  // keys: ["a", ""]
  // ["a", "b", "c"], ["a", "b", "d"]
  // types: "string", "array", "number", "bool", "object"
  //
  // TEST
  // form.json
  // input(name='a')
  // input(name='images.')
  // input(name='images.')
  // input(name='b.b')
  // input(name='c.c.:number')
  // input(name='c.c.')
  // input(type='submit')
  //
  var submitHandler = function(e, options, action) {

    var self = this;
    var method = self.getAttribute('method') || 'POST';
    var res;

    res = {};
    serializeArray.call(self).forEach(function(t){
      var keys  = t.name.split('.');
      var len   = keys.length - 1;
      var index = keys[len].indexOf(':');
      var value = t.value;
      var type;
      if (index !== -1) {
        type    = keys[len].substr(index + 1);
        keys[len] = keys[len].substr(0, index);
      } else {
        type = 'string';
      }

      if (type === 'array' || type === 'object') {

        value  = JSON.parse(value);

      } else if (type === 'number') {

        value = +value;

      } else if (type === 'time') {

        value = new Date(value).getTime();
        Number.isNaN(value) && (value = '')

      } else if (type === 'bool' || type === 'boolean') {
        if (value === 'false')
          value = false
        else
          value = !!value;

      }

      deepSet(res, keys, value);
    });

    if (options.parseInteger)
      res = integerKeysAsArrayIndexes(res);
    res = options.data.call(self, res);

    // Stringify result object.
    if (method === "GET") {

      var keys = Object.keys(res);
      var arr = []
      for (var i = 0, max = keys.length; i < max; i ++) {
        if (typeof res[keys[i]] === 'string') {

          arr.push(encodeURIComponent(keys[i]) + '=' + encodeURIComponent( res[keys[i]]) )
        } else {
          arr.push(encodeURIComponent(keys[i]) + '=' + encodeURIComponent( JSON.stringify(res[keys[i]])) );
        }
      }
      res = arr.join('&')

    } else {
      res = JSON.stringify(res);
    }

    /**
     * If there are no data should be sent, just return.
     */
    if (res === 'null') {
      return;
    }

    /**
     *
     * AJAX request
     *
     */
    var xmlHttp = new XMLHttpRequest();
    /**
     * Add session header for cross-domain request.
     * You can't set cookies for ajax
     * and you have to response #options request# like:
     * "Access-Control-Allow-Headers: X-AVOSCloud-Session-Token"
     * before you send it.
     * */
    var session = document.cookie.match(/sessionToken=([^;]*)(;|$)/);
    action = (action === undefined ? self.getAttribute('action') : action);

    if (method === 'GET') {
      action += action.indexOf('?') === -1 ? ('?' + res) : ( '&' + res);
    }

    xmlHttp.open(method, action, true);
    xmlHttp.setRequestHeader('Content-Type', 'application/json');
    if (session) {
      xmlHttp.setRequestHeader('X-AVOSCloud-Session-Token', session[1])
    }

    xmlHttp.responseType = 'json';

    xmlHttp.onreadystatechange = function() {
      if (xmlHttp.readyState === 4) {
        if (xmlHttp.status >= 200 && xmlHttp.status < 300) {

          if (typeof xmlHttp.response === 'string')
            options.ended.call(self, JSON.parse(xmlHttp.response), xmlHttp);
          else
            options.ended.call(self, xmlHttp.response, xmlHttp);

        } else {
          options.error.call(self, xmlHttp);
        }
      }
    }

    if (method === 'GET')
      xmlHttp.send();
    else
      xmlHttp.send(res);
  }

  /**
   * Example:
   * <form action='/action/a'>
   * <input type='submit'>
   * <input type='submit' formAction='/action/b'>
   * </form>
   */
  var formAction;
  document.addEventListener('click', function(e) {
    var target = e.target;

    if (target.type === 'submit' && target.formAction) {
      formAction = target.formAction;
    }

    setTimeout(function() {
      formAction = undefined;
    }, 1000);

  })

  /**
   * Submit form's handler.
   * Example:
   * <form data-role='formJSON'>
   * </form>
   */
  document.addEventListener('submit', function(e) {

    var target = e.target;
    if (target.getAttribute('data-role') === 'formJSON') {

      e.preventDefault();

      var temp = (temp = target.getAttribute('data-target')) && document.querySelector(temp);
      var parseInteger = target.getAttribute('data-parseInteger') === 'false' ? false : true;

      var options = {
        parseInteger: parseInteger,
        ended: target.onended || ( temp && temp.onended ) || function(){},
        // to change data
        data: target._data || ( temp && temp._data ) || function(d){return d},
        error: target.onerror || ( temp && temp.onerror ) || function(){}
      };

      submitHandler.call(target, e, options, formAction);

    }

  })

  // Fix.
  // Submit a form by javascript won't fire submit event.
  // @see http://stackoverflow.com/questions/12819357/form-submitted-using-submit-from-a-link-cannot-be-caught-by-onsubmit-handler

  var _submit = HTMLFormElement.prototype.submit;
  HTMLFormElement.prototype.submit = function() {

    if (this.getAttribute('data-role') === 'formJSON') {
      this.dispatchEvent(new Event('submit', {bubbles: true}));
    } else {
      _submit.call(this);
    }
  }

  return null;

}));
<|endoftext|>


<commit_before>var FFA = require('./FFA'); // Base gamemode
var Food = require('../entity/Food');

function Rainbow() {
    FFA.apply(this, Array.prototype.slice.call(arguments));

    this.ID = 20;
    this.name = "Rainbow FFA";
    this.specByLeaderboard = true;

    this.colors = [{
            'r': 255,
            'g': 0,
            'b': 0
        }, // Red
        {
            'r': 255,
            'g': 32,
            'b': 0
        }, {
            'r': 255,
            'g': 64,
            'b': 0
        }, {
            'r': 255,
            'g': 96,
            'b': 0
        }, {
            'r': 255,
            'g': 128,
            'b': 0
        }, // Orange
        {
            'r': 255,
            'g': 160,
            'b': 0
        }, {
            'r': 255,
            'g': 192,
            'b': 0
        }, {
            'r': 255,
            'g': 224,
            'b': 0
        }, {
            'r': 255,
            'g': 255,
            'b': 0
        }, // Yellow
        {
            'r': 192,
            'g': 255,
            'b': 0
        }, {
            'r': 128,
            'g': 255,
            'b': 0
        }, {
            'r': 64,
            'g': 255,
            'b': 0
        }, {
            'r': 0,
            'g': 255,
            'b': 0
        }, // Green
        {
            'r': 0,
            'g': 192,
            'b': 64
        }, {
            'r': 0,
            'g': 128,
            'b': 128
        }, {
            'r': 0,
            'g': 64,
            'b': 192
        }, {
            'r': 0,
            'g': 0,
            'b': 255
        }, // Blue
        {
            'r': 18,
            'g': 0,
            'b': 192
        }, {
            'r': 37,
            'g': 0,
            'b': 128
        }, {
            'r': 56,
            'g': 0,
            'b': 64
        }, {
            'r': 75,
            'g': 0,
            'b': 130
        }, // Indigo
        {
            'r': 92,
            'g': 0,
            'b': 161
        }, {
            'r': 109,
            'g': 0,
            'b': 192
        }, {
            'r': 126,
            'g': 0,
            'b': 223
        }, {
            'r': 143,
            'g': 0,
            'b': 255
        }, // Purple
        {
            'r': 171,
            'g': 0,
            'b': 192
        }, {
            'r': 199,
            'g': 0,
            'b': 128
        }, {
            'r': 227,
            'g': 0,
            'b': 64
        },
    ];
    this.colorsLength = this.colors.length - 1;
    this.speed = 1; // Speed of color change
}

module.exports = Rainbow;
Rainbow.prototype = new FFA();

// Gamemode Specific Functions

Rainbow.prototype.changeColor = function (node) {
    if (typeof node.rainbow == 'undefined') {
        node.rainbow = Math.floor(Math.random() * this.colors.length);
    }

    if (node.rainbow >= this.colorsLength) {
        node.rainbow = 0;
    }

    node.setColor(this.colors[node.rainbow]);
    node.rainbow += this.speed;
};

// Override

Rainbow.prototype.onServerInit = function () {
};

Rainbow.prototype.onTick = function (gameServer) {
    var color, node;
    // Change color
    for (var i in gameServer.nodes) {
        node = gameServer.nodes[i];

        if (!node) {
            continue;
        }

        this.changeColor(node);
    }
};
<commit_msg>Update Rainbow.js<commit_after>var FFA = require('./FFA'); // Base gamemode
var Food = require('../entity/Food');

function Rainbow() {
    FFA.apply(this, Array.prototype.slice.call(arguments));

    this.ID = 20;
    this.name = "Rainbow FFA";
    this.specByLeaderboard = true;

    this.colors = [{
            'r': 255,
            'g': 0,
            'b': 0
        }, // Red
        {
            'r': 255,
            'g': 32,
            'b': 0
        }, {
            'r': 255,
            'g': 64,
            'b': 0
        }, {
            'r': 255,
            'g': 96,
            'b': 0
        }, {
            'r': 255,
            'g': 128,
            'b': 0
        }, // Orange
        {
            'r': 255,
            'g': 160,
            'b': 0
        }, {
            'r': 255,
            'g': 192,
            'b': 0
        }, {
            'r': 255,
            'g': 224,
            'b': 0
        }, {
            'r': 255,
            'g': 255,
            'b': 0
        }, // Yellow
        {
            'r': 192,
            'g': 255,
            'b': 0
        }, {
            'r': 128,
            'g': 255,
            'b': 0
        }, {
            'r': 64,
            'g': 255,
            'b': 0
        }, {
            'r': 0,
            'g': 255,
            'b': 0
        }, // Green
        {
            'r': 0,
            'g': 192,
            'b': 64
        }, {
            'r': 0,
            'g': 128,
            'b': 128
        }, {
            'r': 0,
            'g': 64,
            'b': 192
        }, {
            'r': 0,
            'g': 0,
            'b': 255
        }, // Blue
        {
            'r': 18,
            'g': 0,
            'b': 192
        }, {
            'r': 37,
            'g': 0,
            'b': 128
        }, {
            'r': 56,
            'g': 0,
            'b': 64
        }, {
            'r': 75,
            'g': 0,
            'b': 130
        }, // Indigo
        {
            'r': 92,
            'g': 0,
            'b': 161
        }, {
            'r': 109,
            'g': 0,
            'b': 192
        }, {
            'r': 126,
            'g': 0,
            'b': 223
        }, {
            'r': 143,
            'g': 0,
            'b': 255
        }, // Purple
        {
            'r': 171,
            'g': 0,
            'b': 192
        }, {
            'r': 199,
            'g': 0,
            'b': 128
        }, {
            'r': 227,
            'g': 0,
            'b': 64
        },
    ];
    this.colorsLength = this.colors.length - 1;
    this.speed = 1; // Speed of color change
}

module.exports = Rainbow;
Rainbow.prototype = new FFA();

// Gamemode Specific Functions

Rainbow.prototype.changeColor = function (node) {
    if (typeof node.rainbow == 'undefined') {
        node.rainbow = Math.floor(Math.random() * this.colors.length);
    }
    if (node.rainbow >= this.colorsLength) {
        node.rainbow = 0;
    }
    node.setColor(this.colors[node.rainbow]);
    node.rainbow += this.speed;
};

// Override

Rainbow.prototype.onServerInit = function () {
};

Rainbow.prototype.onTick = function (gameServer) {
    // Change color
    for (var i in gameServer.nodes) {
        var node = gameServer.nodes[i];
        if (!node) continue;
        this.changeColor(node);
    }
};
<|endoftext|>


<commit_before>/** Usage:
*
* Add Infowindow model:
*
* var infowindowModel = new cdb.geo.ui.InfowindowModel({
*   template_name: 'templates/map/infowindow',
*   latlng: [72, -45],
*   offset: [100, 10]
* });
*
* var infowindow = new cdb.geo.ui.Infowindow({
*   model: infowindowModel,
*   mapView: mapView
* });
*
* Show the infowindow:
* infowindow.showInfowindow();
*
*/

cdb.geo.ui.InfowindowModel = Backbone.Model.extend({

  defaults: {
    template_name: 'geo/infowindow',
    latlng: [0, 0],
    offset: [28, 0], // offset of the tip calculated from the bottom left corner
    autoPan: true,
    content: "",
    visibility: false,
    fields: null // contains the fields displayed in the infowindow
  },

  clearFields: function() {
    this.set({fields: []});
  },

  _cloneFields: function() {
    return _(this.get('fields')).map(function(v) {
      return _.clone(v);
    });
  },

  _setFields: function(f) {
    f.sort(function(a, b) { return a.position -  b.position; });
    this.set({'fields': f});
  },

  addField: function(fieldName, at) {
    if(!this.containsField(fieldName)) {
      var fields = this._cloneFields() || [];
      at = at === undefined ? fields.length: at;
      fields.push({name: fieldName, title: true, position: at});
      //sort fields
      this._setFields(fields);
    }
    return this;
  },

  getFieldProperty: function(fieldName, k) {
    if(this.containsField(fieldName)) {
      var fields = this.get('fields') || [];
      var idx = _.indexOf(_(fields).pluck('name'), fieldName);
      return fields[idx][k];
    }
    return null;
  },

  setFieldProperty: function(fieldName, k, v) {
    if(this.containsField(fieldName)) {
      var fields = this._cloneFields() || [];
      var idx = _.indexOf(_(fields).pluck('name'), fieldName);
      fields[idx][k] = v;
      this._setFields(fields);
    }
    return this;
  },

  getFieldPos: function(fieldName) {
    var p = this.getFieldProperty(fieldName, 'position');
    if(p == undefined) {
      return Number.MAX_VALUE;
    }
    return p;
  },

  containsField: function(fieldName) {
    var fields = this.get('fields') || [];
    return _.contains(_(fields).pluck('name'), fieldName);
  },

  removeField: function(fieldName) {
    if(this.containsField(fieldName)) {
      var fields = this._cloneFields() || [];
      var idx = _.indexOf(_(fields).pluck('name'), fieldName);
      if(idx >= 0) {
        fields.splice(idx, 1);
      }
      this._setFields(fields);
    }
    return this;
  }

});

cdb.geo.ui.Infowindow = cdb.core.View.extend({
  className: "infowindow",

  events: {
    "click .close":   "_closeInfowindow",
    "mousedown":      "_stopPropagation",
    "mouseup":        "_stopPropagation",
    "mousewheel":     "_stopPropagation",
    "DOMMouseScroll": "_stopPropagation",
    "dbclick":        "_stopPropagation",
    "click":          "_stopPropagation"
  },

  initialize: function(){

    _.bindAll(this, "render", "setLatLng", "changeTemplate", "_updatePosition", "_update", "toggle", "show", "hide");

    this.mapView = this.options.mapView;

    this.template = this.options.template ? this.options.template : cdb.templates.getTemplate(this.model.get("template_name"));

    this.add_related_model(this.model);

    this.model.bind('change:content', this.render, this);
    this.model.bind('change:template_name', this.changeTemplate, this);
    this.model.bind('change:latlng', this.render, this);
    this.model.bind('change:visibility', this.toggle, this);

    this.mapView.map.bind('change', this._updatePosition, this);
    //this.map.on('viewreset', this._updatePosition, this);
    this.mapView.bind('drag', this._updatePosition, this);
    this.mapView.bind('zoomstart', this.hide, this);
    this.mapView.bind('zoomend', this.show, this);

    this.render();
    this.$el.hide();

  },

  changeTemplate: function(template_name) {
    this.template = cdb.templates.getTemplate(this.model.get("template_name"));
    this.render();
  },

  render: function() {
    if(this.template) {
      this.$el.html($(this.template(_.clone(this.model.attributes))));
      this._update();
    }
    return this;
  },

  toggle: function() {
    this.model.get("visibility") ? this.show() : this.hide();
  },

  _stopPropagation: function(ev) {
    ev.stopPropagation();
  },

  _closeInfowindow: function(ev) {
    if (ev) {
      ev.preventDefault()
      ev.stopPropagation();
    }

    this.model.set("visibility",false);
  },

  /**
  * Set the correct position for the popup
  * @params {latlng} A new Leaflet LatLng object
  */
  setLatLng: function (latlng) {
    this.model.set("latlng", latlng);
    return this;
  },

  showInfowindow: function() {
    this.model.set("visibility", true);
  },

  show: function () {
    var that = this;

    if (this.model.get("visibility")) {
      that.$el.css({ left: -5000 });
      that.$el.fadeIn(250, function() {
        that._update();
      });
    }

  },

  isHidden: function () {
    return !this.model.get("visibility");
  },

  hide: function (force) {
    if (force || !this.model.get("visibility")) this.$el.fadeOut(250);
  },

  _update: function () {
    if(!this.isHidden()) {
      this._adjustPan();
      this._updatePosition();
    }
  },

  /**
  * Update the position (private)
  */
  _updatePosition: function () {

    var offset = this.model.get("offset");

    var
    pos             = this.mapView.latLonToPixel(this.model.get("latlng")),
    x               = this.$el.position().left,
    y               = this.$el.position().top,
    containerHeight = this.$el.outerHeight(true),
    containerWidth  = this.$el.width(),
    left            = pos.x - offset[0],
    size            = this.mapView.getSize(),
    bottom          = -1*(pos.y - offset[1] - size.y);

    this.$el.css({ bottom: bottom, left: left });
  },

  _adjustPan: function () {

    var offset = this.model.get("offset");

    if (!this.model.get("autoPan")) { return; }

    var
      x               = this.$el.position().left,
      y               = this.$el.position().top,
      containerHeight = this.$el.outerHeight(true),
      containerWidth  = this.$el.width(),
      pos             = this.mapView.latLonToPixel(this.model.get("latlng")),
      adjustOffset    = {x: 0, y: 0};
      size            = this.mapView.getSize();

    if (pos.x - offset[0] < 0) {
      adjustOffset.x = pos.x - offset[0] - 10;
    }

    if (pos.x - offset[0] + containerWidth > size.x) {
      adjustOffset.x = pos.x + containerWidth - size.x - offset[0] + 10;
    }

    if (pos.y - containerHeight < 0) {
      adjustOffset.y = pos.y - containerHeight - 10;
    }

    if (pos.y - containerHeight > size.y) {
      adjustOffset.y = pos.y + containerHeight - size.y;
    }

    if (adjustOffset.x || adjustOffset.y) {
      this.mapView.panBy(adjustOffset);
    }
  }

});
<commit_msg>new animation + pan actions<commit_after>/** Usage:
*
* Add Infowindow model:
*
* var infowindowModel = new cdb.geo.ui.InfowindowModel({
*   template_name: 'templates/map/infowindow',
*   latlng: [72, -45],
*   offset: [100, 10]
* });
*
* var infowindow = new cdb.geo.ui.Infowindow({
*   model: infowindowModel,
*   mapView: mapView
* });
*
* Show the infowindow:
* infowindow.showInfowindow();
*
*/

cdb.geo.ui.InfowindowModel = Backbone.Model.extend({

  defaults: {
    template_name: 'geo/infowindow',
    latlng: [0, 0],
    offset: [28, 0], // offset of the tip calculated from the bottom left corner
    autoPan: true,
    content: "",
    visibility: false,
    fields: null // contains the fields displayed in the infowindow
  },

  clearFields: function() {
    this.set({fields: []});
  },

  _cloneFields: function() {
    return _(this.get('fields')).map(function(v) {
      return _.clone(v);
    });
  },

  _setFields: function(f) {
    f.sort(function(a, b) { return a.position -  b.position; });
    this.set({'fields': f});
  },

  addField: function(fieldName, at) {
    if(!this.containsField(fieldName)) {
      var fields = this._cloneFields() || [];
      at = at === undefined ? fields.length: at;
      fields.push({name: fieldName, title: true, position: at});
      //sort fields
      this._setFields(fields);
    }
    return this;
  },

  getFieldProperty: function(fieldName, k) {
    if(this.containsField(fieldName)) {
      var fields = this.get('fields') || [];
      var idx = _.indexOf(_(fields).pluck('name'), fieldName);
      return fields[idx][k];
    }
    return null;
  },

  setFieldProperty: function(fieldName, k, v) {
    if(this.containsField(fieldName)) {
      var fields = this._cloneFields() || [];
      var idx = _.indexOf(_(fields).pluck('name'), fieldName);
      fields[idx][k] = v;
      this._setFields(fields);
    }
    return this;
  },

  getFieldPos: function(fieldName) {
    var p = this.getFieldProperty(fieldName, 'position');
    if(p == undefined) {
      return Number.MAX_VALUE;
    }
    return p;
  },

  containsField: function(fieldName) {
    var fields = this.get('fields') || [];
    return _.contains(_(fields).pluck('name'), fieldName);
  },

  removeField: function(fieldName) {
    if(this.containsField(fieldName)) {
      var fields = this._cloneFields() || [];
      var idx = _.indexOf(_(fields).pluck('name'), fieldName);
      if(idx >= 0) {
        fields.splice(idx, 1);
      }
      this._setFields(fields);
    }
    return this;
  }

});

cdb.geo.ui.Infowindow = cdb.core.View.extend({
  className: "infowindow",

  events: {
    "click .close":   "_closeInfowindow",
    "mousedown":      "_stopPropagation",
    "mouseup":        "_stopPropagation",
    "mousewheel":     "_stopPropagation",
    "DOMMouseScroll": "_stopPropagation",
    "dbclick":        "_stopPropagation",
    "click":          "_stopPropagation"
  },

  initialize: function(){

    _.bindAll(this, "render", "setLatLng", "changeTemplate", "_updatePosition", "_update", "toggle", "show", "hide");

    this.mapView = this.options.mapView;

    this.template = this.options.template ? this.options.template : cdb.templates.getTemplate(this.model.get("template_name"));

    this.add_related_model(this.model);

    this.model.bind('change:content',       this.render, this);
    this.model.bind('change:template_name', this.changeTemplate, this);
    this.model.bind('change:latlng',        this._update, this);
    this.model.bind('change:visibility',    this.toggle, this);

    this.mapView.map.bind('change',         this._updatePosition, this);
    //this.map.on('viewreset', this._updatePosition, this);
    this.mapView.bind('drag',               this._updatePosition, this);

    var that = this;
    this.mapView.bind('zoomstart', function(){
      that.hide(true);
    });
    this.mapView.bind('zoomend', function() {
      that.show(true);
    });

    this.render();
    this.$el.hide();

  },

  changeTemplate: function(template_name) {
    this.template = cdb.templates.getTemplate(this.model.get("template_name"));
    this.render();
  },

  render: function() {
    if(this.template) {
      this.$el.html($(this.template(_.clone(this.model.attributes))));
      //this._update();
    }
    return this;
  },

  toggle: function() {
    this.model.get("visibility") ? this.show() : this.hide();
  },

  _stopPropagation: function(ev) {
    ev.stopPropagation();
  },

  _closeInfowindow: function(ev) {
    if (ev) {
      ev.preventDefault()
      ev.stopPropagation();
    }

    this.model.set("visibility",false);
  },

  /**
  * Set the correct position for the popup
  * @params {latlng} A new Leaflet LatLng object
  */
  setLatLng: function (latlng) {
    this.model.set("latlng", latlng);
    return this;
  },

  showInfowindow: function() {
    this.model.set("visibility", true);
  },

  show: function (no_pan) {
    var that = this;

    if (this.model.get("visibility")) {
      that.$el.css({ left: -5000 });
      that._update(no_pan);
    }
  },

  isHidden: function () {
    return !this.model.get("visibility");
  },

  hide: function (force) {
    if (force || !this.model.get("visibility")) this._animateOut();
  },

  _update: function (no_pan) {

    if(!this.isHidden()) {
      var delay = 0;

      if (!no_pan) {
        var delay = this._adjustPan();
      }

      this._updatePosition();
      this._animateIn(delay);
    }
  },

  _animateIn: function(delay) {
    this.$el.css({
      'marginBottom':'-10px',
      'display':'block',
      opacity:0
    });

    this.$el
      .delay(delay)
      .animate({
        opacity: 1,
        marginBottom: 0
      },300);
  },

  _animateOut: function() {
    var that = this;

    this.$el.animate({
      marginBottom: "-10px",
      opacity:      "0",
      display:      "block"
    }, 180, function() {
      that.$el.css({display: "none"});
    });
  },

  /**
  * Update the position (private)
  */
  _updatePosition: function () {

    var
    offset          = this.model.get("offset")
    pos             = this.mapView.latLonToPixel(this.model.get("latlng")),
    x               = this.$el.position().left,
    y               = this.$el.position().top,
    containerHeight = this.$el.outerHeight(true),
    containerWidth  = this.$el.width(),
    left            = pos.x - offset[0],
    size            = this.mapView.getSize(),
    bottom          = -1*(pos.y - offset[1] - size.y);

    this.$el.css({ bottom: bottom, left: left });
  },

  _adjustPan: function (callback) {

    var offset = this.model.get("offset");

    if (!this.model.get("autoPan")) { return; }

    var
      x               = this.$el.position().left,
      y               = this.$el.position().top,
      containerHeight = 280, //this.$el.outerHeight(true),
      containerWidth  = this.$el.width(),
      pos             = this.mapView.latLonToPixel(this.model.get("latlng")),
      adjustOffset    = {x: 0, y: 0};
      size            = this.mapView.getSize()
      wait_callback   = 0;

    if (pos.x - offset[0] < 0) {
      adjustOffset.x = pos.x - offset[0] - 10;
    }

    if (pos.x - offset[0] + containerWidth > size.x) {
      adjustOffset.x = pos.x + containerWidth - size.x - offset[0] + 10;
    }

    if (pos.y - containerHeight < 0) {
      adjustOffset.y = pos.y - containerHeight - 10;
    }

    if (pos.y - containerHeight > size.y) {
      adjustOffset.y = pos.y + containerHeight - size.y;
    }

    if (adjustOffset.x || adjustOffset.y) {
      this.mapView.panBy(adjustOffset);
      wait_callback = 300;
    }

    return wait_callback;
  }

});
<|endoftext|>