<commit_before>all();
function all() {
   /**
    * Function is alias to {@link WAMS.init}
    * @param {string} [host] Host socket.io is connecting to
    * @param {object} clientDescription User specified description of client
    * @returns {WAMS.init} Instance of session
    *
    * @alias WAMS
    * @constructor
    */
   var WAMS = function(host, clientDescription) {
      return new WAMS.init(host, clientDescription);
   };

   /**
    * Check if uuid is valid
    * @param {string} uuid uuid to check
    * @returns {boolean}
    */
   var isUUID = function(uuid) {
      var uuidRegexp = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
      return uuidRegexp.test(uuid);
   };

//   var //Returns true if object is a DOM node
//      isNode = function(o) {
//         return (typeof Node === "object" ? o instanceof Node :
//            o && typeof o === "object" && typeof o.nodeType === "number"
//               && typeof o.nodeName === "string");
//      }
//      , //Returns true if object is a DOM element
//      isElement = function(o) {
//         return (typeof HTMLElement === "object" ? o instanceof HTMLElement : //DOM2
//            o && typeof o === "object" && o !== null && o.nodeType === 1
//               && typeof o.nodeName === "string");
//      }
//      , //Returns true if object is jQuery element
//      isJQueryElement = function(o) {
//         return (o instanceof WAMS.modules.$);
//      }
//      , //Check if object is empty
//      isEmpty = function(obj) {
//         for (var key in obj) {
//            if (obj.hasOwnProperty(key))
//               return false;
//         }
//         return true;
//      }
//      , //default drag callback
//      defaultDragCallback = function(ev) {
//         var $ = WAMS.modules.$;
//
//      };

   /**
    * Is true when {@link WAMS.init#socket socket} is connected and
    * {@link WAMS.init#MTObjects MT objects} initialized
    * @type {boolean}
    */
   WAMS.READY = false;

   /**
    * All events that sent to server
    * @type {{}}
    */
   var io_send_calls = {
      new_connection:       "CONN"
      , subscribe_mt_event: "MT_EVENT_SUBSCRIBE"
      , message_sent:       "SEND_MSG"
      , broadcast_sent:     "SEND_BROADCAST"
   };
   /**
    * All events that received from server
    * @type {{}}
    */
   var io_recv_calls = WAMS.when = {
      connection_ok:        "CONN_OK"
      , user_connected:     "CONN_USER"
      , user_disconnected:  "DEL_USER"
      , message_received:   "RECV_MSG"
      , broadcast_received: "RECV_BROADCAST"
   };
   io_recv_calls.has = function(target) {
      for (var i in this) {
         if (this[i] === target) {
            return true;
         }
      }
      return false;
   };
   //   WAMS.events = new WAMS.modules.ev();

   /**
    * Function initializes new session instance
    * @param {string} [host] Host socket.io is connecting to
    * @param {object} clientDescription User specified description of client
    * @returns {WAMS.init} Instance of session
    *
    * @constructor
    */
   WAMS.init = function(host, clientDescription) {
      if (typeof host !== "string") {
         clientDescription = host;
         host = undefined;
      }
      var self = this;

      /**
       * Description of client for current session
       * @type {Object}
       */
      this.description = clientDescription;
      /**
       * Objects that has multi-touch properties
       * @type {Array}
       */
      this.MTObjects = [];
      this.MTSelector = "";

      /**
       * Array with all clients connected to server except this
       * @type {Array}
       */
      this.otherClients = [];

      /**
       * Socket to the host for the current session
       * @type {*|io.Socket}
       */
      this.socket = WAMS.modules.io.connect(host);

      this.socket.emit(io_send_calls.new_connection, {
         description: clientDescription
      });
      this.socket.on(io_recv_calls.connection_ok, function(data) {
         self.uuid = data.data.uuid;
         self.otherClients = data.data.otherClients;

         //TODO fire event or something similar when connection happened
      });
      this.socket.on(io_recv_calls.user_connected, function(data) {
         self.otherClients.push(data.data.client);

         //TODO fire event
      });
      this.socket.on(io_recv_calls.user_disconnected, function(data) {
         if (self.otherClients.length > 0) {
            var toDelete = -1, i;
            for (i = 0; i < self.otherClients.length && toDelete === -1; i++) {
               if (self.otherClients[i].uuid === data.data.client.uuid) {toDelete = i;}
            }
            if (toDelete != -1) {
               self.otherClients.splice(toDelete, 1);
            }

            //TODO fire event
         }
      });
      this.socket.on(io_recv_calls.message_received, function(data) {
//         console.log(data);
         //TODO fire event
      });
      this.socket.on(io_recv_calls.broadcast_received, function(data) {
//         console.log(data);
         //TODO fire event
      });

      WAMS.READY = true;
      return this;
   };

   WAMS.init.prototype = {
      /**
       * All multitouch events from Hammer
       * @type {string[]}
       */
      MTEvents: [
         "hold", "tap", "doubletap", "drag", "dragstart", "dragend", "dragup",
         "dragdown", "dragleft", "dragright", "swipe", "swipeup", "swipedown",
         "swipeleft", "swiperight", "transform", "transformstart", "transformend",
         "rotate", "pinch", "pinchin", "pinchout", "touch", "release"
      ],

      /**
       * Specify on which element multitouch is started
       * @param {jQuery} elem Jquery array of elements
       */
      addMT: function(elem) {
         //TODO make hammer start on body and move items only with certain classes
         //FIXME --bug 1--
         // when we pass clean js array of html elements (not $),
         // and we push each element into MTObjects array, inside "on" function
         // callback on elements is not called.
         // Also. When in MTObjects was pushed instance of Hammer, "on" function
         // was not calling callback on elements. (On github wiki it is working)
         for (var i = 0, len = elem.length; i < len; i++) {
            var newMTObj = new WAMS.modules.Hammer(elem[i], {
               prevent_default: true,
               no_mouseevents: true
            });
//            this.MTObjects.push(newMTObj);
         }
         this.MTObjects.push(elem);
      },

      // TODO check on idea of starting MT on body and only allowing
      // to interact with elements with certain selector
//      startMT: function (selector) {
//         new WAMS.modules.Hammer(document.body, {
//            prevent_default: true,
//            no_mouseevents: true
//         });
//         this.MTSelector = selector;
//      },

      /**
       * Send data to server through {@link WAMS.init#socket|socket}
       * @param {string} type Type of event created on server
       * @param {string|object} data Object to send
       */
      emit: function(type, data) {
         var self = this;
         this.socket.emit(type, {
            source: self.uuid,
            data: data
         });
      },

      /**
       * Register callback on specified event
       * @param {string|string[]} types On which types fire callback
       * @param {function} callback Function to execute
       */
      on: function(types, callback) {
         var self = this;
         types.split(' ').forEach(function(type) { // in case types is given as string of few events
            if (type === "shake") {
               window.addEventListener(type, callback, false);
            } else if (io_recv_calls.has(type)) { // one of internal events
               self.socket.on(type, function(data) {
                  callback(data.data);
               });
            } else if (self.MTEvents.indexOf(type) != -1) { // if this event is from hammer
               self.MTObjects.forEach(function (MTObj) { // to all mt objects we attach listener
                  MTObj.on(type, function (ev) { //listener callback
                     var touches = ev.originalEvent.gesture.touches;
                     var event = {
                           type: type,
                           element: []
                        };
                     for (var i = 0; i < touches.length; i++) {
                        var touch = touches[i];
                        var elementMetadata = {
                           tag: touch.target.tagName,
                           attributes: {},
                           innerHTML: touch.target.innerHTML,
                           x: touch.pageX,
                           y: touch.pageY
                        };
                        for (var j = 0, attrs = touch.target.attributes; j < attrs.length; j++) {
                           elementMetadata.attributes[attrs.item(j).nodeName] = attrs.item(j).nodeValue;
                        }
                        event.element.push(elementMetadata);
                     }
                     self.emit(type, event);

                     //FIXME --bug 1-- continued
                     // cont from higher - this callback is not called when event is
                     // generated. Right before callback any console.log is called,
                     // but right inside this callback none of console.log are called
                     callback(ev);
                  });
               });
            } else {
               self.socket.on(type, function (data) {
                  callback(data);
               });
            }
         });
      },

      /**
       * Stop listening for events of these types
       * @param {string|string[]} types
       * @param {function} callback specify which function should be unsubscribed
       */
      off: function(types, callback) {
         var self = this;
         types.split(' ').forEach(function(type) { // in case types is given as string of few events
            if (type === "shake") {
               window.removeEventListener(type, callback, false);
            } else if (self.MTEvents.indexOf(type) != -1) {
               self.MTObjects.off(type, callback);
               self.socket.removeListener(type, callback);
            }
            else {
               self.socket.removeListener(type, callback);
            }
         });
      },

      /**
       * Register callback on event type from remote server
       * @param {string|string[]} types On which types fire callback
       * @param {function} callback Function to execute
       */
      onRemote: function(types, callback) {
         var self = this;
         self.emit(io_send_calls.subscribe_mt_event, {
            eventType: types
         });
         types.split(' ').forEach(function(type) {
            self.socket.on(type, function(data) {
               data.data.source = data.source;
               callback(data.data);
            });
         });
      },

      /**
       * Send message to specified clients through server
       * @param {string[]} targets Array of target uuids
       * @param {String|object} msg message
       */
      sendMSG: function(targets, msg) {
         var self = this;
         self.emit(io_send_calls.message_sent, {
            targets: targets,
            msg: msg
         });
      },

      /**
       * Send message to all clients through server
       * @param {String|object} msg message
       */
      broadcastMSG: function(msg) {
         var self = this;
         self.emit(io_send_calls.broadcast_sent, {
            msg: msg
         });
      },

      //FIXME rewrite better without return in the middle of for
      getDescription: function(uuid) {
         if (!isUUID(uuid)) {
//            console.error("Provide correct uuid");
            return undefined;
         }
         for (var i = 0; i < this.otherClients.length; i++) {
            if (this.otherClients[i].uuid === uuid) {
               return this.otherClients[i].description;
            }
         }
         return undefined;
      }
   };

   /*
    //Shared dic
    var dic = {};
    this.socket.on("DIC_SNAPSHOT", function(data) {
    dic = data;
    });
    this.socket.on("DIC_UPDATE", function(data) {
    dic[data.attr] = data.value;
    console.log(dic);
    });
    console.log(dic);
    this.socket.emit("PUSH_TO_DIC", {
    attr: "uuid", value: this.uuid
    });
    dic["uuid"] = this.uuid;
    console.log(dic);
    //Shared dic end
    */

   // Taken from Hammer.js and modified
   // Based off Lo-Dash's excellent UMD wrapper (slightly modified) - https://github.com/bestiejs/lodash/blob/master/lodash.js#L5515-L5543
   // some AMD build optimizers, like r.js, check for specific condition patterns like the following:
   if(typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
      // define as module
      define(["jquery", "hammer", "socket.io"],
         function ($, Hammer, io) {
            if (!WAMS.modules) {
               WAMS.modules = {};
            }
            WAMS.modules.$ = $;
            WAMS.modules.Hammer = Hammer;
            WAMS.modules.io = io;

            return WAMS;
         });
   }
   // Browserify support
   else if(typeof module === 'object' && typeof module.exports === 'object') {
      var $ = require('');
      var Hammer = require('hammerjs');
      var io = require('socket.io-client');

      WAMS.modules.$ = $;
      WAMS.modules.Hammer = Hammer;
      WAMS.modules.io = io;

      module.exports = WAMS;
   }
   // If we have no plugins
   else {
      WAMS.modules.$ = window.jQuery;
      WAMS.modules.Hammer = window.Hammer;
      WAMS.modules.io = window.io;

      window.WAMS = WAMS;
   }
}<commit_msg>feat(wams): decrease data sent over network<commit_after>all();
function all() {
   /**
    * Function is alias to {@link WAMS.init}
    * @param {string} [host] Host socket.io is connecting to
    * @param {object} clientDescription User specified description of client
    * @returns {WAMS.init} Instance of session
    *
    * @alias WAMS
    * @constructor
    */
   var WAMS = function(host, clientDescription) {
      return new WAMS.init(host, clientDescription);
   };

   /**
    * Check if uuid is valid
    * @param {string} uuid uuid to check
    * @returns {boolean}
    */
   var isUUID = function(uuid) {
      var uuidRegexp = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
      return uuidRegexp.test(uuid);
   };

//   var //Returns true if object is a DOM node
//      isNode = function(o) {
//         return (typeof Node === "object" ? o instanceof Node :
//            o && typeof o === "object" && typeof o.nodeType === "number"
//               && typeof o.nodeName === "string");
//      }
//      , //Returns true if object is a DOM element
//      isElement = function(o) {
//         return (typeof HTMLElement === "object" ? o instanceof HTMLElement : //DOM2
//            o && typeof o === "object" && o !== null && o.nodeType === 1
//               && typeof o.nodeName === "string");
//      }
//      , //Returns true if object is jQuery element
//      isJQueryElement = function(o) {
//         return (o instanceof WAMS.modules.$);
//      }
//      , //Check if object is empty
//      isEmpty = function(obj) {
//         for (var key in obj) {
//            if (obj.hasOwnProperty(key))
//               return false;
//         }
//         return true;
//      }
//      , //default drag callback
//      defaultDragCallback = function(ev) {
//         var $ = WAMS.modules.$;
//
//      };

   /**
    * Is true when {@link WAMS.init#socket socket} is connected and
    * {@link WAMS.init#MTObjects MT objects} initialized
    * @type {boolean}
    */
   WAMS.READY = false;

   /**
    * All events that sent to server
    * @type {{}}
    */
   var io_send_calls = {
      new_connection:       "CONN"
      , subscribe_mt_event: "MT_EVENT_SUBSCRIBE"
      , message_sent:       "SEND_MSG"
      , broadcast_sent:     "SEND_BROADCAST"
   };
   /**
    * All events that received from server
    * @type {{}}
    */
   var io_recv_calls = WAMS.when = {
      connection_ok:        "CONN_OK"
      , user_connected:     "CONN_USER"
      , user_disconnected:  "DEL_USER"
      , message_received:   "RECV_MSG"
      , broadcast_received: "RECV_BROADCAST"
   };
   io_recv_calls.has = function(target) {
      for (var i in this) {
         if (this[i] === target) {
            return true;
         }
      }
      return false;
   };
   //   WAMS.events = new WAMS.modules.ev();

   /**
    * Function initializes new session instance
    * @param {string} [host] Host socket.io is connecting to
    * @param {object} clientDescription User specified description of client
    * @returns {WAMS.init} Instance of session
    *
    * @constructor
    */
   WAMS.init = function(host, clientDescription) {
      if (typeof host !== "string") {
         clientDescription = host;
         host = undefined;
      }
      var self = this;

      /**
       * Description of client for current session
       * @type {Object}
       */
      this.description = clientDescription;
      /**
       * Objects that has multi-touch properties
       * @type {Array}
       */
      this.MTObjects = [];
      this.MTSelector = "";

      /**
       * Array with all clients connected to server except this
       * @type {Array}
       */
      this.otherClients = [];

      /**
       * Socket to the host for the current session
       * @type {*|io.Socket}
       */
      this.socket = WAMS.modules.io.connect(host);

      this.socket.emit(io_send_calls.new_connection, {
         description: clientDescription
      });
      this.socket.on(io_recv_calls.connection_ok, function(data) {
         self.uuid = data.data.uuid;
         self.otherClients = data.data.otherClients;

         //TODO fire event or something similar when connection happened
      });
      this.socket.on(io_recv_calls.user_connected, function(data) {
         self.otherClients.push(data.data.client);

         //TODO fire event
      });
      this.socket.on(io_recv_calls.user_disconnected, function(data) {
         if (self.otherClients.length > 0) {
            var toDelete = -1, i;
            for (i = 0; i < self.otherClients.length && toDelete === -1; i++) {
               if (self.otherClients[i].uuid === data.data.client) {toDelete = i;}
            }
            if (toDelete != -1) {
               self.otherClients.splice(toDelete, 1);
            }

            //TODO fire event
         }
      });
      this.socket.on(io_recv_calls.message_received, function(data) {
//         console.log(data);
         //TODO fire event
      });
      this.socket.on(io_recv_calls.broadcast_received, function(data) {
//         console.log(data);
         //TODO fire event
      });

      WAMS.READY = true;
      return this;
   };

   WAMS.init.prototype = {
      /**
       * All multitouch events from Hammer
       * @type {string[]}
       */
      MTEvents: [
         "hold", "tap", "doubletap", "drag", "dragstart", "dragend", "dragup",
         "dragdown", "dragleft", "dragright", "swipe", "swipeup", "swipedown",
         "swipeleft", "swiperight", "transform", "transformstart", "transformend",
         "rotate", "pinch", "pinchin", "pinchout", "touch", "release"
      ],

      /**
       * Specify on which element multitouch is started
       * @param {jQuery} elem Jquery array of elements
       */
      addMT: function(elem) {
         //TODO make hammer start on body and move items only with certain classes
         //FIXME --bug 1--
         // when we pass clean js array of html elements (not $),
         // and we push each element into MTObjects array, inside "on" function
         // callback on elements is not called.
         // Also. When in MTObjects was pushed instance of Hammer, "on" function
         // was not calling callback on elements. (On github wiki it is working)
         for (var i = 0, len = elem.length; i < len; i++) {
            var newMTObj = new WAMS.modules.Hammer(elem[i], {
               prevent_default: true,
               no_mouseevents: true
            });
//            this.MTObjects.push(newMTObj);
         }
         this.MTObjects.push(elem);
      },

      // TODO check on idea of starting MT on body and only allowing
      // to interact with elements with certain selector
//      startMT: function (selector) {
//         new WAMS.modules.Hammer(document.body, {
//            prevent_default: true,
//            no_mouseevents: true
//         });
//         this.MTSelector = selector;
//      },

      /**
       * Send data to server through {@link WAMS.init#socket|socket}
       * @param {string} type Type of event created on server
       * @param {string|object} data Object to send
       */
      emit: function(type, data) {
         var self = this;
         this.socket.emit(type, {
            source: self.uuid,
            data: data
         });
      },

      /**
       * Register callback on specified event
       * @param {string|string[]} types On which types fire callback
       * @param {function} callback Function to execute
       */
      on: function(types, callback) {
         var self = this;
         types.split(' ').forEach(function(type) { // in case types is given as string of few events
            if (type === "shake") {
               window.addEventListener(type, callback, false);
            } else if (io_recv_calls.has(type)) { // one of internal events
               self.socket.on(type, function(data) {
                  callback(data.data);
               });
            } else if (self.MTEvents.indexOf(type) != -1) { // if this event is from hammer
               self.MTObjects.forEach(function (MTObj) { // to all mt objects we attach listener
                  MTObj.on(type, function (ev) { //listener callback
                     var touches = ev.originalEvent.gesture.touches;
                     var event = {
                           type: type,
                           element: []
                        };
                     for (var i = 0; i < touches.length; i++) {
                        var touch = touches[i];
                        var elementMetadata = {
                           tag: touch.target.tagName,
                           attributes: {},
                           innerHTML: touch.target.innerHTML,
                           x: touch.pageX,
                           y: touch.pageY
                        };
                        for (var j = 0, attrs = touch.target.attributes; j < attrs.length; j++) {
                           elementMetadata.attributes[attrs.item(j).nodeName] = attrs.item(j).nodeValue;
                        }
                        event.element.push(elementMetadata);
                     }
                     self.emit(type, event);

                     //FIXME --bug 1-- continued
                     // cont from higher - this callback is not called when event is
                     // generated. Right before callback any console.log is called,
                     // but right inside this callback none of console.log are called
                     callback(ev);
                  });
               });
            } else {
               self.socket.on(type, function (data) {
                  callback(data);
               });
            }
         });
      },

      /**
       * Stop listening for events of these types
       * @param {string|string[]} types
       * @param {function} callback specify which function should be unsubscribed
       */
      off: function(types, callback) {
         var self = this;
         types.split(' ').forEach(function(type) { // in case types is given as string of few events
            if (type === "shake") {
               window.removeEventListener(type, callback, false);
            } else if (self.MTEvents.indexOf(type) != -1) {
               self.MTObjects.off(type, callback);
               self.socket.removeListener(type, callback);
            }
            else {
               self.socket.removeListener(type, callback);
            }
         });
      },

      /**
       * Register callback on event type from remote server
       * @param {string|string[]} types On which types fire callback
       * @param {function} callback Function to execute
       */
      onRemote: function(types, callback) {
         var self = this;
         self.emit(io_send_calls.subscribe_mt_event, {
            eventType: types
         });
         types.split(' ').forEach(function(type) {
            self.socket.on(type, function(data) {
               data.data.source = data.source;
               callback(data.data);
            });
         });
      },

      /**
       * Send message to specified clients through server
       * @param {string[]} targets Array of target uuids
       * @param {String|object} msg message
       */
      sendMSG: function(targets, msg) {
         var self = this;
         self.emit(io_send_calls.message_sent, {
            targets: targets,
            msg: msg
         });
      },

      /**
       * Send message to all clients through server
       * @param {String|object} msg message
       */
      broadcastMSG: function(msg) {
         var self = this;
         self.emit(io_send_calls.broadcast_sent, {
            msg: msg
         });
      },

      //FIXME rewrite better without return in the middle of for
      getDescription: function(uuid) {
         if (!isUUID(uuid)) {
//            console.error("Provide correct uuid");
            return undefined;
         }
         for (var i = 0; i < this.otherClients.length; i++) {
            if (this.otherClients[i].uuid === uuid) {
               return this.otherClients[i].description;
            }
         }
         return undefined;
      }
   };

   /*
    //Shared dic
    var dic = {};
    this.socket.on("DIC_SNAPSHOT", function(data) {
    dic = data;
    });
    this.socket.on("DIC_UPDATE", function(data) {
    dic[data.attr] = data.value;
    console.log(dic);
    });
    console.log(dic);
    this.socket.emit("PUSH_TO_DIC", {
    attr: "uuid", value: this.uuid
    });
    dic["uuid"] = this.uuid;
    console.log(dic);
    //Shared dic end
    */

   // Taken from Hammer.js and modified
   // Based off Lo-Dash's excellent UMD wrapper (slightly modified) - https://github.com/bestiejs/lodash/blob/master/lodash.js#L5515-L5543
   // some AMD build optimizers, like r.js, check for specific condition patterns like the following:
   if(typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
      // define as module
      define(["jquery", "hammer", "socket.io"],
         function ($, Hammer, io) {
            if (!WAMS.modules) {
               WAMS.modules = {};
            }
            WAMS.modules.$ = $;
            WAMS.modules.Hammer = Hammer;
            WAMS.modules.io = io;

            return WAMS;
         });
   }
   // Browserify support
   else if(typeof module === 'object' && typeof module.exports === 'object') {
      var $ = require('');
      var Hammer = require('hammerjs');
      var io = require('socket.io-client');

      WAMS.modules.$ = $;
      WAMS.modules.Hammer = Hammer;
      WAMS.modules.io = io;

      module.exports = WAMS;
   }
   // If we have no plugins
   else {
      WAMS.modules.$ = window.jQuery;
      WAMS.modules.Hammer = window.Hammer;
      WAMS.modules.io = window.io;

      window.WAMS = WAMS;
   }
}<|endoftext|>


<commit_before>
/**
  Dependencies
*/

var Cast = require('./cast');
var Rules = require('./rules');
var Compute = require('./compute');

/**
  Export this module
*/

module.exports = exports;

/**
  Apply compute facilities
*/

exports.compute = Compute.computeAll;

/**
  Accessor mechanism to load a 'schema' by a String reference

  Method MUST either throw an Error or return a valid **Schema**.

  Used by `.deepcast()` and `.validate()` when these are presented with
  subschema that are not resolved, but referenced by a string. These methods
  delegate to `exports.accessor(ref)` to attempt to load the schema.

  This method is designed to be overwritten by a wrapper library that stores
  schema by 'string' reference.

  @param {String} ref Unique key reference to schema

  @throws {Error} Thrown when no accessor method has been provided
  @returns {Schema} schema object
*/

exports.accessor = function (ref) {
  throw new Error('No accessor method found. Cannot load reference: '+ref);
};

/**
  Sets a default value if specified on empty fields

  Supports passing an object and complex schema.

  @param {Mixed} v The value or object to default
  @param {Schema} schema The associated schema to check the default value on

  @return Value or the default value
*/

exports.default = function (v, schema) {

  if (!schema) return v;

  var def = function (v, s) {
    // No default, return the value as is
    if (s.default === undefined) return v;

    // Return the default if `v` is empty (ie. undefined or '')
    return Rules.empty(v) ? s.default : v;
  };

  // Parse objects
  if (typeof v === 'object') {
    for (var k in schema) {
      if (schema[k].default) v[k] = def( v[k], schema[k] );
    }

    return v;
  }
  // Or simply return defaulted scalars
  else return def(v, schema);
};

/**
  Returns an object built on ALL values present in the schema, set to defaults

  @param {Schema} schema To initialise object

  @return {Object}
*/

exports.createFrom = function (schema) {
  var o = {};

  if (!schema) return o;

  for (var k in schema) {
    if (!schema.hasOwnProperty(k)) continue;
    o[k] = exports.default( undefined, schema[k] );
  }

  return o;
};

/**
  Available filter functions (modifiers for value)
*/

var _filters = {
  trim: function(v) { return v.trim(); },
  nowhite: function (v) { return v.replace( / /g, ''); },
  uppercase: function (v) { return v.toUpperCase(); },
  lowercase: function (v) { return v.toLowerCase(); }
};

// Add 'to$CAST' casters to filters
for (var cast in Cast) if (cast.substr(0,2)==='to') _filters[cast] = Cast[cast];

/**
  Applies a list of filter functions

  @param {Mixed} val The value to filter
  @param {String[]} filters Array of named filters to apply

  @throws {Error} if filter cannot be applied
*/

exports.filter = function (val, filters) {
  // No-op if no filters
  if (!filters) return val;

  // Do not attempt to filter 'undefined' values
  if (val === undefined) return val;

  // Ensure filters are provided as an array
  if (typeof filters === 'string') filters = [filters];

  filters.forEach( function (key) {
    // Try-catch is to make it CLEAR that this can throw
    // May be useful in future to do more than propagate throw
    try {
      if ( _filters[key] ) val = _filters[key]( val );
    }
    catch( e ) { throw e; }
  });

  return val;
};

/**
  Exposes the available filters as an array

  @return {Array}
*/

exports.filter.available = function () {
  return Object.keys(_filters);
};

/**
  Adds a named `key` filter `fn`

  @param {String} key The identifier for the filter
  @param {Function} fn The filter function (passed `v` and returns modified `v`)
*/

exports.filter.add = function (key, fn) {
  _filters[ key ] = fn;
};

/**
  Cross browser object 'type' checker
  Returns the [[Class]] subjugate

  @param {Mixed} obj The entity to type check

  @return {String} type
*/

var toType = exports.toType = function(obj) {
  return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase();
};

/**
  Type check

  Explicit tests on `{type:$TypeFn}` declarations. Same as 'Rules'
*/

var is = {
  string: function (v) { return typeof v === 'string'; },
  integer: function (v) { return typeof v === 'number' && v%1 === 0 && !isNaN(v);},
  number: function (v) { return toType(v) === 'number' && !isNaN(v); },
  array: function (v) { return toType(v) === 'array'; },
  boolean: function (v) { return toType(v) === 'boolean'; },
  object: function (v) { return toType(v) === 'object'; }
};

/**
  Checks that a `val` is of `type`

  Runs `val` against a 'type' function that returns boolean if the
  value meets its criteria.

  Does **NOT** type check undefined values.

  @param {Mixed} val The value to test
  @param {String} type The name of the type check to run

  @return {Array} errors
*/

exports.typeCheck = function ( val, type ) {
  if (!is[ type ]) return ['Unknown type to check: '+type];

  return val === undefined || is[ type ](val)
    ? []
    : ['Not of type: '+type];
};

/**
  Helper method: Applies a default and runs filters on a `val`

  @param {Mixed} val The value to cast
  @param {Schema} schema The schema to apply to the value

  @throws {Error} on failed filter
  @return the cast value
*/

var _cast = exports.cast = function (val, schema) {

  try {
    // Cast objects
    if (is.object(val) ) {
      // First check that we're not at a ROOT level schema (which is a
      // request to deepcast an object, NOT step through keys)
      if (schema.schema) return _deepcast( val, schema );

      for (var key in schema) {
        if (val.hasOwnProperty(key))
          val[key] = _cast( val[key], schema[key] );
      }
      return val;
    }
    // Cast everything else
    else {
      return schema.schema
        ? _deepcast( val, schema )
        : exports.filter( exports.default( val, schema ), schema.filters );
    }
  }
  catch(e) { throw e; }
};

/**
  Casts (default+filter) arrays and objects that are described by sub-schema
  Destructively operates on the data provided (ie. overwrites provided values)
  (Useful when being passed custom Class objects and not simple primitives)

  @param {Object|Array} data
  @param {Schema} schema containing sub-schema declarations

  @return cast values
*/

var _deepcast = function (data, schema) {
  // No sub-schema to deepcast, just do a normal cast
  if (!schema.schema) return _cast(data, schema);

  // Load a string referenced schema from an accessor (expects a SCHEMA)
  if ('string' === typeof schema.schema)
    schema.schema = exports.accessor( schema.schema );

  var setO = function ( obj, scm, ret ) {
    for (var key in scm) {
      var cast = _deepcast( obj[key], scm[key] );
      if (typeof cast !== 'undefined') ret[key] = cast;
    }
    return ret;
  };

  switch (toType(data)) {
    case 'array':
      // Step through each element
      for (var i=0; i<data.length; i++) {

        // Array 'data' is actually a Collection.
        if (is.object(data[i]))
          data[i] = setO( data[i], schema.schema, data[i] );

        // Treat the contents as scalar values
        else data[i] = _cast( data[i], schema.schema );

      }

      break;

    case 'object':
      data = setO( data, schema.schema, data );
      break;
  }

  return data;
};

/**
  The schema for a valid schema (used to validate schema objects)
*/

var validSchema = exports.validSchema = {
  type: {type:'string', rules:{in:Object.keys(is)}},
  required: {type:'boolean'},
  rules: {type:'object'},
  filters: {schema:{type:'string'}},
  array: {type:'boolean'},
  default: {},
  allowNull: {type:'boolean'}
};

// The default "failed validation" message. Appended with ' $key' where
// `$key` is the key of the validation rule that failed.
var defaultError = 'Failed:';

function errMsg (key) {
  return defaultError + ' ' + key;
}

/**
  Checks a value against the rules defined in `schema`

  Does **NOT** apply rules to undefined values that are not `required`

  @param {Mixed} val The value to test
  @param {Object} schema The schema to apply the tests against

  @return {Array} errors
*/

exports.checkValue = function (val, schema) {
  var errs = [];

  if (!schema) return errs;

  // Check required...
  if (schema.required) {
    if (!Rules.required( val )) return ['Required to be set'];
  }

  // Not required and unset returns WITHOUT check
  if (val === undefined) return errs;

  // 2. Check type match
  // The value type matches its declaration (if any)
  if (schema.type) {
    var res = exports.typeCheck(val, schema.type);
    if (res.length) return res;
  }

  // 3. Validate rules
  for (var key in schema.rules) {
    // Build parameters to pass to rule
    var params = schema.rules[key];
    if ( !(params instanceof Array) ) params = [params];
    params.unshift( val );

    // Check that the rule exists to run against
    if (!Rules[key]) {
      errs.push('Unknown rule: '+key);
      continue;
    }

    // Run validation
    var isValid = Rules[key].apply( this, params );
    if (!isValid) {
      // Failed validation adds error to stack
      if (schema.errors) {
        if (typeof schema.errors === 'string') errs.push( schema.errors );
        else if (schema.errors[key]) errs.push( schema.errors[key] );
        else if (schema.errors.default) errs.push( schema.errors.default );
        else errs.push( errMsg(key) );
      }
      else errs.push( errMsg(key) );
    }
  }

  // Return errors
  return errs;
};

/**
  Validates `data` against a schema's rules. Does not pre-cast data.

  Returns:

  {
    valid: {Boolean},
    errors: {Object|Array} // Error object if passed object, array if scalar
  }

  Example:

  ```
  schema.validate( '1', {type:'string'} );
  // -> {valid:true, errors:[]}

  schema.validate( {name:'Zim'}, {name:{type:'string'}});
  // -> {valid: true, errors:{}}
  ```

  @return {Object} Validation object `{valid:$bool, errors:$Object|Array}`
*/

exports.validate = function (data, schema, _noCheck) {
  var errs = {};
  var isValid = true;

  // Validate scalars
  if (!is.object(data)) {
    var res = exports.checkValue( data, schema );
    return res.length
      ? {valid:false, errors:res}
      : {valid:true, errors:[]};
  }

  // Step through ONLY our schema keys
  for (var key in schema) {
    // Only handle own properties
    if (!schema.hasOwnProperty(key)) continue;

    // Shorthand
    var scm = schema[key];
    var v = data[key];

    // Self validate schema
    if (!_noCheck) {
      var chk = exports.validate( scm, validSchema, true );
      if (!chk.valid)
        throw new Error('Invalid schema: ' + JSON.stringify(chk.errors));
    }

    // If it's not required and the default value is 'empty', skip it
    if (!scm.required && Rules.empty( exports.default(v,scm) )) continue;

    // Recursively Validate sub-schema
    if (scm.schema) {

      // Load a string referenced schema from an accessor (expects a SCHEMA)
      if ('string' === typeof scm.schema)
        scm.schema = exports.accessor( scm.schema );

      // Arrays can be either raw 'values' or complex 'objects'
      if (scm.type === 'array' || v instanceof Array) {

        // Step through the values in the array
        v.forEach(function(val,idx) {

          // Array of complex objects
          if (toType(val) === 'object') {
            var arsub = exports.validate( val, scm.schema );
            if (!arsub.valid) {
              isValid = false;
              if (!errs[key]) errs[key] = {};
              errs[key][idx] = arsub.errors;
            }
          }

          // Array of simple types
          else {
            var er = exports.checkValue( val, scm.schema );
            if (er.length) {
              isValid = false;
              if (!errs[key]) errs[key] = {};
              errs[key][idx] = er;
            }
          }
        });
      }

      // Otherwise just assume it's an object
      else {
        var sub = exports.validate( v, scm.schema );
        if (!sub.valid) {
          isValid = false;
          errs[key] = sub.errors;
        }
      }
    }

    // Otherwise NO sub-schema: test the value directly
    else {
      var errors = exports.checkValue( v, scm );
      if (errors.length) {
        isValid = false;
        errs[key] = errors;
      }
    }
  }

  return {
    valid: isValid,
    errors: errs
  };
};

<commit_msg>Copy schema on validate(schema) and expand error<commit_after>
/**
  Dependencies
*/

var Cast = require('./cast');
var Rules = require('./rules');
var Compute = require('./compute');

/**
  Export this module
*/

module.exports = exports;

/**
  Apply compute facilities
*/

exports.compute = Compute.computeAll;

/**
  Accessor mechanism to load a 'schema' by a String reference

  Method MUST either throw an Error or return a valid **Schema**.

  Used by `.deepcast()` and `.validate()` when these are presented with
  subschema that are not resolved, but referenced by a string. These methods
  delegate to `exports.accessor(ref)` to attempt to load the schema.

  This method is designed to be overwritten by a wrapper library that stores
  schema by 'string' reference.

  @param {String} ref Unique key reference to schema

  @throws {Error} Thrown when no accessor method has been provided
  @returns {Schema} schema object
*/

exports.accessor = function (ref) {
  throw new Error('No accessor method found. Cannot load reference: '+ref);
};

/**
  Sets a default value if specified on empty fields

  Supports passing an object and complex schema.

  @param {Mixed} v The value or object to default
  @param {Schema} schema The associated schema to check the default value on

  @return Value or the default value
*/

exports.default = function (v, schema) {

  if (!schema) return v;

  var def = function (v, s) {
    // No default, return the value as is
    if (s.default === undefined) return v;

    // Return the default if `v` is empty (ie. undefined or '')
    return Rules.empty(v) ? s.default : v;
  };

  // Parse objects
  if (typeof v === 'object') {
    for (var k in schema) {
      if (schema[k].default) v[k] = def( v[k], schema[k] );
    }

    return v;
  }
  // Or simply return defaulted scalars
  else return def(v, schema);
};

/**
  Returns an object built on ALL values present in the schema, set to defaults

  @param {Schema} schema To initialise object

  @return {Object}
*/

exports.createFrom = function (schema) {
  var o = {};

  if (!schema) return o;

  for (var k in schema) {
    if (!schema.hasOwnProperty(k)) continue;
    o[k] = exports.default( undefined, schema[k] );
  }

  return o;
};

/**
  Available filter functions (modifiers for value)
*/

var _filters = {
  trim: function(v) { return v.trim(); },
  nowhite: function (v) { return v.replace( / /g, ''); },
  uppercase: function (v) { return v.toUpperCase(); },
  lowercase: function (v) { return v.toLowerCase(); }
};

// Add 'to$CAST' casters to filters
for (var cast in Cast) if (cast.substr(0,2)==='to') _filters[cast] = Cast[cast];

/**
  Applies a list of filter functions

  @param {Mixed} val The value to filter
  @param {String[]} filters Array of named filters to apply

  @throws {Error} if filter cannot be applied
*/

exports.filter = function (val, filters) {
  // No-op if no filters
  if (!filters) return val;

  // Do not attempt to filter 'undefined' values
  if (val === undefined) return val;

  // Ensure filters are provided as an array
  if (typeof filters === 'string') filters = [filters];

  filters.forEach( function (key) {
    // Try-catch is to make it CLEAR that this can throw
    // May be useful in future to do more than propagate throw
    try {
      if ( _filters[key] ) val = _filters[key]( val );
    }
    catch( e ) { throw e; }
  });

  return val;
};

/**
  Exposes the available filters as an array

  @return {Array}
*/

exports.filter.available = function () {
  return Object.keys(_filters);
};

/**
  Adds a named `key` filter `fn`

  @param {String} key The identifier for the filter
  @param {Function} fn The filter function (passed `v` and returns modified `v`)
*/

exports.filter.add = function (key, fn) {
  _filters[ key ] = fn;
};

/**
  Cross browser object 'type' checker
  Returns the [[Class]] subjugate

  @param {Mixed} obj The entity to type check

  @return {String} type
*/

var toType = exports.toType = function(obj) {
  return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase();
};

/**
  Type check

  Explicit tests on `{type:$TypeFn}` declarations. Same as 'Rules'
*/

var is = {
  string: function (v) { return typeof v === 'string'; },
  integer: function (v) { return typeof v === 'number' && v%1 === 0 && !isNaN(v);},
  number: function (v) { return toType(v) === 'number' && !isNaN(v); },
  array: function (v) { return toType(v) === 'array'; },
  boolean: function (v) { return toType(v) === 'boolean'; },
  object: function (v) { return toType(v) === 'object'; }
};

/**
  Checks that a `val` is of `type`

  Runs `val` against a 'type' function that returns boolean if the
  value meets its criteria.

  Does **NOT** type check undefined values.

  @param {Mixed} val The value to test
  @param {String} type The name of the type check to run

  @return {Array} errors
*/

exports.typeCheck = function ( val, type ) {
  if (!is[ type ]) return ['Unknown type to check: '+type];

  return val === undefined || is[ type ](val)
    ? []
    : ['Not of type: '+type];
};

/**
  Helper method: Applies a default and runs filters on a `val`

  @param {Mixed} val The value to cast
  @param {Schema} schema The schema to apply to the value

  @throws {Error} on failed filter
  @return the cast value
*/

var _cast = exports.cast = function (val, schema) {

  try {
    // Cast objects
    if (is.object(val) ) {
      // First check that we're not at a ROOT level schema (which is a
      // request to deepcast an object, NOT step through keys)
      if (schema.schema) return _deepcast( val, schema );

      for (var key in schema) {
        if (val.hasOwnProperty(key))
          val[key] = _cast( val[key], schema[key] );
      }
      return val;
    }
    // Cast everything else
    else {
      return schema.schema
        ? _deepcast( val, schema )
        : exports.filter( exports.default( val, schema ), schema.filters );
    }
  }
  catch(e) { throw e; }
};

/**
  Casts (default+filter) arrays and objects that are described by sub-schema
  Destructively operates on the data provided (ie. overwrites provided values)
  (Useful when being passed custom Class objects and not simple primitives)

  @param {Object|Array} data
  @param {Schema} schema containing sub-schema declarations

  @return cast values
*/

var _deepcast = function (data, schema) {
  // No sub-schema to deepcast, just do a normal cast
  if (!schema.schema) return _cast(data, schema);

  // Load a string referenced schema from an accessor (expects a SCHEMA)
  if ('string' === typeof schema.schema)
    schema.schema = exports.accessor( schema.schema );

  var setO = function ( obj, scm, ret ) {
    for (var key in scm) {
      var cast = _deepcast( obj[key], scm[key] );
      if (typeof cast !== 'undefined') ret[key] = cast;
    }
    return ret;
  };

  switch (toType(data)) {
    case 'array':
      // Step through each element
      for (var i=0; i<data.length; i++) {

        // Array 'data' is actually a Collection.
        if (is.object(data[i]))
          data[i] = setO( data[i], schema.schema, data[i] );

        // Treat the contents as scalar values
        else data[i] = _cast( data[i], schema.schema );

      }

      break;

    case 'object':
      data = setO( data, schema.schema, data );
      break;
  }

  return data;
};

/**
  The schema for a valid schema (used to validate schema objects)
*/

var validSchema = exports.validSchema = {
  type: {type:'string', rules:{in:Object.keys(is)}},
  required: {type:'boolean'},
  rules: {type:'object'},
  filters: {schema:{type:'string'}},
  array: {type:'boolean'},
  default: {},
  allowNull: {type:'boolean'}
};

// The default "failed validation" message. Appended with ' $key' where
// `$key` is the key of the validation rule that failed.
var defaultError = 'Failed:';

function errMsg (key) {
  return defaultError + ' ' + key;
}

/**
  Checks a value against the rules defined in `schema`

  Does **NOT** apply rules to undefined values that are not `required`

  @param {Mixed} val The value to test
  @param {Object} schema The schema to apply the tests against

  @return {Array} errors
*/

exports.checkValue = function (val, schema) {
  var errs = [];

  if (!schema) return errs;

  // Check required...
  if (schema.required) {
    if (!Rules.required( val )) return ['Required to be set'];
  }

  // Not required and unset returns WITHOUT check
  if (val === undefined) return errs;

  // 2. Check type match
  // The value type matches its declaration (if any)
  if (schema.type) {
    var res = exports.typeCheck(val, schema.type);
    if (res.length) return res;
  }

  // 3. Validate rules
  for (var key in schema.rules) {
    // Build parameters to pass to rule
    var params = schema.rules[key];
    if ( !(params instanceof Array) ) params = [params];
    params.unshift( val );

    // Check that the rule exists to run against
    if (!Rules[key]) {
      errs.push('Unknown rule: '+key);
      continue;
    }

    // Run validation
    var isValid = Rules[key].apply( this, params );
    if (!isValid) {
      // Failed validation adds error to stack
      if (schema.errors) {
        if (typeof schema.errors === 'string') errs.push( schema.errors );
        else if (schema.errors[key]) errs.push( schema.errors[key] );
        else if (schema.errors.default) errs.push( schema.errors.default );
        else errs.push( errMsg(key) );
      }
      else errs.push( errMsg(key) );
    }
  }

  // Return errors
  return errs;
};

/**
  Validates `data` against a schema's rules. Does not pre-cast data.

  Returns:

  {
    valid: {Boolean},
    errors: {Object|Array} // Error object if passed object, array if scalar
  }

  Example:

  ```
  schema.validate( '1', {type:'string'} );
  // -> {valid:true, errors:[]}

  schema.validate( {name:'Zim'}, {name:{type:'string'}});
  // -> {valid: true, errors:{}}
  ```

  @return {Object} Validation object `{valid:$bool, errors:$Object|Array}`
*/

exports.validate = function (data, schema, _noCheck) {
  var errs = {};
  var isValid = true;

  // Validate scalars
  if (!is.object(data)) {
    var res = exports.checkValue( data, schema );
    return res.length
      ? {valid:false, errors:res}
      : {valid:true, errors:[]};
  }

  // Step through ONLY our schema keys
  for (var key in schema) {
    // Only handle own properties
    if (!schema.hasOwnProperty(key)) continue;

    // Shorthand
    var scm = schema[key];
    var v = data[key];

    // Self validate schema
    if (!_noCheck) {
      var chk = exports.validate( JSON.parse(JSON.stringify(scm)), validSchema, true );
      if (!chk.valid)
        throw new Error('Invalid schema: ' +
          JSON.stringify(chk.errors) +
          ' - {"' + key +'":'+ JSON.stringify(scm) + '}' );
    }

    // If it's not required and the default value is 'empty', skip it
    if (!scm.required && Rules.empty( exports.default(v,scm) )) continue;

    // Recursively Validate sub-schema
    if (scm.schema) {

      // Load a string referenced schema from an accessor (expects a SCHEMA)
      if ('string' === typeof scm.schema)
        scm.schema = exports.accessor( scm.schema );

      // Arrays can be either raw 'values' or complex 'objects'
      if (scm.type === 'array' || v instanceof Array) {

        // Step through the values in the array
        v.forEach(function(val,idx) {

          // Array of complex objects
          if (toType(val) === 'object') {
            var arsub = exports.validate( val, scm.schema );
            if (!arsub.valid) {
              isValid = false;
              if (!errs[key]) errs[key] = {};
              errs[key][idx] = arsub.errors;
            }
          }

          // Array of simple types
          else {
            var er = exports.checkValue( val, scm.schema );
            if (er.length) {
              isValid = false;
              if (!errs[key]) errs[key] = {};
              errs[key][idx] = er;
            }
          }
        });
      }

      // Otherwise just assume it's an object
      else {
        var sub = exports.validate( v, scm.schema );
        if (!sub.valid) {
          isValid = false;
          errs[key] = sub.errors;
        }
      }
    }

    // Otherwise NO sub-schema: test the value directly
    else {
      var errors = exports.checkValue( v, scm );
      if (errors.length) {
        isValid = false;
        errs[key] = errors;
      }
    }
  }

  return {
    valid: isValid,
    errors: errs
  };
};

<|endoftext|>


<commit_before>//@flow
const graphqlTools = require('graphql-tools')
const isGitUrl     = require('is-git-url')

const {actions, store} = require('./actions')

import type {RepoStatus} from './reducers'

const schema = `
   type UserError {
       message : String
   }

    type Repo {
        status   : String
    }

    union Result = Repo | UserError

    type Query {
        repo(url : String) : Result
        sessionId : String!
    }

    type Mutation {
        addRepo(url : String) : Result
    }
`

type Repo = {
   status: RepoStatus
}

type UserError = {
   message: string
}

const resolverMap = {
   Query: {
       repo({session}, {url}): Repo | UserError {
           if (! isGitUrl(url)) {
               return {message: 'Invalid git URL'}
           }
           const state = store.getState().get('sessions').get(session.id)
           if (state == null) {
              return {message: 'Invalid session'}
           }
           const status = state.repos.get(url)
           return {status}
       },
       sessionId({session}) {
           return session.id
       }
   },
   Mutation: {
       addRepo({session}, {url}): Repo | UserError {
           if (! isGitUrl(url)) {
               return {message: 'Invalid git URL'}
           }
           actions.startClone(session.id, url)
           return {status: 'start'}
       },
   },
   Result: {
      __resolveType(root, context, info){
          if (root.status != null) {
              return 'Repo'
          } else if (root.message != null) {
              return 'UserError'
          }
          return null;
      },
   },
}

function repoToFolder(repoURL)  {
    let folder = repoURL.replace(/^http:\/\//,'')
    folder = folder.replace(/^https:\/\//,'')
    folder = folder.replace(/^git:\/\//,'')
    folder = folder.replace(/^.+?@/,'')
    return folder.replace(/:/,'/')
}

module.exports = graphqlTools.makeExecutableSchema({
    typeDefs: schema,
    resolvers: resolverMap,
})
<commit_msg>Play with repo status state<commit_after>//@flow
const graphqlTools = require('graphql-tools')
const isGitUrl     = require('is-git-url')

const {actions, store} = require('./actions')

import type {RepoStatus} from './reducers'

const schema = `
   type UserError {
       message : String
   }

    type Repo {
        status   : String
    }

    union Result = Repo | UserError

    type Query {
        repo(url : String) : Result
        sessionId : String!
    }

    type Mutation {
        addRepo(url : String) : Result
    }
`

type Repo = {
   status: RepoStatus
}

type UserError = {
   message: string
}

function getStatus(session_id, url) {
     const state = store.getState().get('sessions').get(session_id)
     if (state == null) {
         return null
     }
     return state.repos.get(url)
}

const resolverMap = {
   Query: {
       repo({session}, {url}): Repo | UserError {
           if (! isGitUrl(url)) {
               return {message: 'Invalid git URL'}
           }
           const status = getStatus(session.id, url)
           if (status == null) {
               return {message: 'Invalid session'}
           }
           return {status}
       },
       sessionId({session}) {
           return session.id
       },
   },
   Mutation: {
       addRepo({session}, {url}): Repo | UserError {
           if (! isGitUrl(url)) {
               return {message: 'Invalid git URL'}
           }
           actions.startClone(session.id, url)
           const status = getStatus(session.id, url) || 'start'
           return {status}
       },
   },
   Result: {
      __resolveType(root, context, info){
          if (root.status != null) {
              return 'Repo'
          } else if (root.message != null) {
              return 'UserError'
          }
          return null;
      },
   },
}

function repoToFolder(repoURL)  {
    let folder = repoURL.replace(/^http:\/\//,'')
    folder = folder.replace(/^https:\/\//,'')
    folder = folder.replace(/^git:\/\//,'')
    folder = folder.replace(/^.+?@/,'')
    return folder.replace(/:/,'/')
}

module.exports = graphqlTools.makeExecutableSchema({
    typeDefs: schema,
    resolvers: resolverMap,
})
<|endoftext|>


<commit_before>function gallery (pictures){
  var index= 0;
  //cache DOM
  var left = document.getElementById("left");
  var right = document.getElementById("right");
  var slider = document.getElementById("slider");
  var img = document.querySelector("#slider .slide img");
  var description = document.getElementById("description");
  //bind events
  left.addEventListener("click", slide);
  right.addEventListener("click", slide);
  document.addEventListener("keydown", keyPressed);
  document.addEventListener("mousemove", toggleButtons);
  render();
  function render(){
    var pic = pictures[index];
    img.src = pic.src;
    if(pic.description){
      description.style.display = "block";
      description.innerHTML = "
" + pic.description + "
";
    }else{
      description.style.display = "none";
    }
  }
  function slide(e){
    if(e.target.id =="left" && index>0){
      index--;
    }else if (e.target.id =="right" && index+1<pictures.length) {
      index++;
    }
    render();
  }
  function keyPressed(e){
    if(e.key =="ArrowLeft" && index>0){
      index--;
      render();
    }else if(e.key =="ArrowRight" && index+1<pictures.length){
      index++;
      render();
    }
  }
  function toggleButtons(){
    right.style.display = "block";
    left.style.display = "block";
    document.removeEventListener("mousemove", toggleButtons);
    window.setTimeout(function(){
      right.style.display = "none";
      left.style.display = "none";
      document.addEventListener("mousemove", toggleButtons);
    }, 3000);
  }
}

var pictures = [
  {
    src: "pics/1.jpeg",
    description: "Hello world!"
  },
  {
    src: "pics/2.jpeg",
    description: "snow!!!"
  },
  {
    src: "pics/3.jpeg",
    description: "city"
  },
  {
    src: "pics/4.jpeg"
  }
];
gallery(pictures);
<commit_msg>fixed slide Bug<commit_after>function gallery (pictures){
  var index= 0;
  //cache DOM
  var left = document.getElementById("left");
  var right = document.getElementById("right");
  var slider = document.getElementById("slider");
  var slideEl = document.getElementsByClassName('slide');
  var img = document.querySelector("#slider .slide img");
  var description = document.getElementById("description");
  //bind events
  left.addEventListener("click", slide);
  right.addEventListener("click", slide);
  document.addEventListener("keydown", keyPressed);
  document.addEventListener("mousemove", toggleButtons);
  render();
  function render(){
    var pic = pictures[index];
    img.src = pic.src;
    if(pic.description){
      description.style.display = "block";
      description.innerHTML = "
" + pic.description + "
";
    }else{
      description.style.display = "none";
    }
  }
  function slide(e){
    console.log("x");
    if(e.target.id =="left" && index>0){
      index--;
    }else if (e.target.id =="right" && index+1<pictures.length) {
      index++;
    }
    render();
  }
  function keyPressed(e){
    if(e.key =="ArrowLeft" && index>0){
      index--;
      render();
    }else if(e.key =="ArrowRight" && index+1<pictures.length){
      index++;
      render();
    }
  }
  function toggleButtons(){
    right.style.display = "block";
    left.style.display = "block";
    document.removeEventListener("mousemove", toggleButtons);
    window.setTimeout(function(){
      right.style.display = "block";
      left.style.display = "block";
      document.addEventListener("mousemove", toggleButtons);
    }, 3000);
  }
}

var pictures = [
  {
    src: "pics/1.jpeg",
    description: "Hello world!"
  },
  {
    src: "pics/2.jpeg",
    description: "snow!!!"
  },
  {
    src: "pics/3.jpeg",
    description: "city"
  },
  {
    src: "pics/4.jpeg"
  }
];
gallery(pictures);
<|endoftext|>


<commit_before>/*jslint browser:true */
var message = document.getElementById("message");
var messages = document.getElementById("messages");
var formid = document.getElementById("formid");
var textarea = document.getElementById("textarea");

function getResponse(query) {
    $.ajax({
        dataType: "jsonp",
        type: "GET",
        url: "https://api.susi.ai/susi/chat.json?timezoneOffset=-300&q=" + query,
        error: function(xhr,textStatus,errorThrown) {
            var newP = document.createElement("p");
            var newDiv = messages.childNodes[messages.childElementCount];
            loading(false);
            newDiv.setAttribute("class", "susinewmessage");
            var myTextNode = document.createTextNode("Sorry! request could not be made.");
            newP.appendChild(myTextNode);
            newDiv.appendChild(newP);
            messages.appendChild(newDiv);
        },
        success: function (data) {
            var recQuery = data["answers"][0]["data"][0]["query"];
            if (query !== recQuery) {
                return getResponse(query);
            }
            var link = data["answers"][0]["data"][0]["link"];
            var image1 = data["answers"][0]["data"][0]["answer"];
            var image2 = data["answers"][0]["data"][0]["webformatURL"];
            var image3 = data["answers"][0]["data"][0]["image"];
            var answer = data["answers"][0]["data"][0]["answer"];
            console.log(image1);
            console.log(image2);
    		console.log(image3);
            try {
            if (image2.startsWith("https"))
            {
                var image=image2;
                answer="";
            }
            } catch(err)
            {}
            try{

            if (image3.startsWith("https"))
            {
            	var image=image3;
        	}
            }
            catch(err)
            {}
            try {
            if (image1.startsWith("https"))
            {
                var image=image1;
                answer="";
            }
            }
            catch(err)
            {}
            loading(false);
        	console.log(image);
            var newDiv = messages.childNodes[messages.childElementCount];
            var newP = document.createElement("p");
            newP.appendChild(document.createTextNode(answer));
            newDiv.appendChild(newP);
            if (link) {
                var newA = document.createElement("a");
                newA.appendChild(document.createTextNode(link));
                newA.setAttribute("href", link);
                newA.setAttribute("target", "_blank");
                newDiv.appendChild(document.createElement("br"));
                newDiv.appendChild(newA);
            }
            if (image) {
                var newImg = document.createElement("img");
                newDiv.appendChild(document.createElement("br"));
                newImg.setAttribute("src", image);
                newImg.setAttribute("class", "susi-img");
                newDiv.appendChild(newImg);
            }
            newDiv.setAttribute("class", "susinewmessage");
            messages.appendChild(newDiv);
            messages.scrollTop = messages.scrollHeight;
        }
    });
}

function loading(condition=true){
    if(condition == true){
        var newDiv = document.createElement('div');
        var newImg = document.createElement('img');
        newImg.setAttribute("src","loading.gif");
        newImg.setAttribute("style","height:10px;width:auto");
        newDiv.appendChild(newImg);
        newDiv.setAttribute("class","susinewmessage");
        messages.appendChild(newDiv);
        messages.scrollTop = messages.scrollHeight;
    }
    else{
        messages.childNodes[messages.childElementCount].innerHTML = "";
    }
}

function submitForm() {
    var text = textarea.value;
    text = text.trim();
    if (text === "") {
        return console.log("Empty Query!");
    }
    var newP = document.createElement("p");
    var newDiv = document.createElement("div");
    newDiv.setAttribute("class", "mynewmessage");
    var myTextNode = document.createTextNode(text);
    newP.appendChild(myTextNode);
    newDiv.appendChild(newP);
    messages.appendChild(newDiv);
    textarea.value = "";
    loading();
    if(window.navigator.onLine)
        getResponse(text);
    else {
        loading(false);
        var newP = document.createElement("p");
        var newDiv =  messages.childNodes[messages.childElementCount];
        newDiv.setAttribute("class", "susinewmessage");
        var myTextNode = document.createTextNode("Not connected to Internet!");
        newP.appendChild(myTextNode);
        newDiv.appendChild(newP);
        messages.appendChild(newDiv);
    }
    messages.scrollTop = messages.scrollHeight;
}

textarea.onkeyup = function (e) {
    if (e.which === 13 && !e.shiftKey) {
        e.preventDefault();
        submitForm();
    }
};

formid.addEventListener("submit", function (e) {
    e.preventDefault();
    submitForm();
});
<commit_msg>add composesusi message for errors<commit_after>/*jslint browser:true */
var message = document.getElementById("message");
var messages = document.getElementById("messages");
var formid = document.getElementById("formid");
var textarea = document.getElementById("textarea");

function composeResponse(data){
    var link = data["answers"][0]["data"][0]["link"];
    var image1 = data["answers"][0]["data"][0]["answer"];
    var image2 = data["answers"][0]["data"][0]["webformatURL"];
    var image3 = data["answers"][0]["data"][0]["image"];
    var answer = data["answers"][0]["data"][0]["answer"];
    var image;
    try {
        if (image2.startsWith("https")) {
            image=image2;
            answer="";
        }
    }catch(err)
    {}
    try {
        if (image3.startsWith("https")) {
            image=image3;
        }
    }
    catch(err)
    {}
    try {
        if (image1.startsWith("https")) {
            image=image1;
            answer="";
        }
    }
    catch(err)
    {}
    return {
        error: false,
        link,
        image,
        answer
    };
}

function getResponse(query) {
    $.ajax({
        dataType: "jsonp",
        type: "GET",
        url: "https://api.susi.ai/susi/chat.json?timezoneOffset=-300&q=" + query,
        error: function(xhr,textStatus,errorThrown) {
            loading(false);
            var response = {
                error: true,
                errorText: "Sorry! request could not be made"
            };
            composeSusiMessage(response);
        },
        success: function (data) {
            var recQuery = data["answers"][0]["data"][0]["query"];
            if (query !== recQuery) {
                return getResponse(query);
            }
            var response = composeResponse(data);
            loading(false);
            composeSusiMessage(response);
        }
    });
}

function loading(condition=true){
    if(condition == true){
        var newDiv = document.createElement('div');
        var newImg = document.createElement('img');
        newImg.setAttribute("src","loading.gif");
        newImg.setAttribute("style","height:10px;width:auto");
        newDiv.appendChild(newImg);
        newDiv.setAttribute("class","susinewmessage");
        messages.appendChild(newDiv);
        messages.scrollTop = messages.scrollHeight;
    }
    else{
        messages.childNodes[messages.childElementCount].innerHTML = "";
    }
}

function composeMyMessage(text) {
    var newP = document.createElement("p");
    var newDiv = document.createElement("div");
    newDiv.setAttribute("class", "mynewmessage");
    var myTextNode = document.createTextNode(text);
    newP.appendChild(myTextNode);
    newDiv.appendChild(newP);
    messages.appendChild(newDiv);
    textarea.value = "";
    messages.scrollTop = messages.scrollHeight;
}

function composeLink(link) {
    var newA = document.createElement("a");
    newA.appendChild(document.createTextNode(link));
    newA.setAttribute("href", link);
    newA.setAttribute("target", "_blank");
    return newA;
}

function composeImage(image) {
    var newImg = document.createElement("img");
    newImg.setAttribute("src", image);
    newImg.setAttribute("class", "susi-img");
    return newImg;
}

function composeSusiMessage(response) {
    var newP = document.createElement("p");
    var newDiv =  messages.childNodes[messages.childElementCount];
    newDiv.setAttribute("class", "susinewmessage");
    var susiTextNode;
    if(response.error===true){
        susiTextNode = document.createTextNode(response.errorText);
        newP.appendChild(susiTextNode);
        newDiv.appendChild(newP);
    }
    else {
            susiTextNode = document.createTextNode(response.answer);
            newP.appendChild(susiTextNode);
            newDiv.appendChild(newP);
            if (response.link) {
                var newA = composeLink(response.link);
                newDiv.appendChild(document.createElement("br"));
                newDiv.appendChild(newA);
            }
            if (response.image) {
                var newImg = composeImage(response.image);
                newDiv.appendChild(document.createElement("br"));
                newDiv.appendChild(newImg);
            }
    }
    messages.appendChild(newDiv);
    messages.scrollTop = messages.scrollHeight;
}

function submitForm() {
    var text = textarea.value;
    text = text.trim();
    if (text === "") {
        return console.log("Empty Query!");
    }
    composeMyMessage(text);
    loading();
    if(window.navigator.onLine)
        getResponse(text);
    else {
        loading(false);
        var response = {
            error: true,
            errorText: "Not connected to Internet!"
        };
        composeSusiMessage(response);
    }
}

textarea.onkeyup = function (e) {
    if (e.which === 13 && !e.shiftKey) {
        e.preventDefault();
        submitForm();
    }
};

formid.addEventListener("submit", function (e) {
    e.preventDefault();
    submitForm();
});
<|endoftext|>


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

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

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

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

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

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

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

			mUserInfo = data['userInfo'];

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

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

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

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

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

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

			localChatIDForColor++;

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

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

			var str = generateChatMsgStr(msgObj);

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

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

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

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

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

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

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

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

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

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

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

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

				potCount = pot.length;

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

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

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

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

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

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

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

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

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

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

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

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

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

	return str;
}

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

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

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

		var itemRealPrice = getFormattedPrice(itemPrice);

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

	return str;
}

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

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

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

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

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

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

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

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

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

	return '$' + price;
}<commit_msg>Remove argument for getting formatted time<commit_after>//Copyright (c) 2015 Jordan Turley, CSGO Win Big. All Rights Reserved.

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

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

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

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

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

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

			mUserInfo = data['userInfo'];

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

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

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

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

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

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

			localChatIDForColor++;

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

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

			var str = generateChatMsgStr(msgObj);

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

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

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

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

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

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

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

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

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

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

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

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

				potCount = pot.length;

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

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

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

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

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

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

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

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

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

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

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

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

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

	return str;
}

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

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

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

		var itemRealPrice = getFormattedPrice(itemPrice);

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

	return str;
}

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

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

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

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

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

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

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

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

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

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


<commit_before>var scripts = {};

function loadScript( url, callback, parent ) {
	if ( parent ) {
		loadText( url, function( text ) {
			var script = create( "script", parent.ownerDocument );
			script.text = text;
			add( script, parent );
			parent.removeChild( script );
			callback();
		} );
	} else {
		( scripts[ url ] || ( ( scripts[ url ] = Future(function( future ) {
			loadScript( url, future.s, documentElement );
		} ) ) ) ).g( callback );
	}
}
<commit_msg>Adds some value now that use.script uses loaderFactory<commit_after>var scripts = {};

function loadScript( url, callback, parent ) {
	if ( parent ) {
		loadText( url, function( text ) {
			var script = create( "script", parent.ownerDocument );
			script.text = text;
			add( script, parent );
			parent.removeChild( script );
			callback( url );
		} );
	} else {
		( scripts[ url ] || ( ( scripts[ url ] = Future(function( future ) {
			loadScript( url, future.s, documentElement );
		} ) ) ) ).g( callback );
	}
}
<|endoftext|>


<commit_before>var TWEEN;

require("raf.js");

// Just here to simplify the initialization logic.  If
// window doesn't exist, this module is useless anyway
if(typeof window === 'undefined') { window = {}; }

// The build will declare TWEEN as external. However, if it isn't provided by
// browserify, we really want to check to see if it was included directly via
// script tag first.  Only if it isn't will we try a require.  This *should*
// make it easier to bundle/or not and to use with requirejs...
TWEEN = window.TWEEN || require("tween.js");

function Scroll(viewOrSelector, listener) {
    var view,
        min, max, offset, reference, pressed,
        velocity, frame, timestamp, ticker, tweenTicker,
        amplitude, target, timeConstant, innerHeight;

    var p0 = { y: 0 };
    var t0 = false;

    function ypos(e) {
        // touch event
        if (e.targetTouches && (e.targetTouches.length >= 1)) {
            return e.targetTouches[0].clientY;
        }

        // mouse event
        return e.clientY;
    }

    function scroll(y) {
        offset = (y > max) ? max : (y < min) ? min : y;

        view.scrollTop = offset;
        listener.call(view);
    }

    function track() {
        var now, elapsed, delta, v;

        now = Date.now();
        elapsed = now - timestamp;
        timestamp = now;
        delta = offset - frame;
        frame = offset;

        v = 1000 * delta / (1 + elapsed);
        velocity = 0.8 * v + 0.2 * velocity;
    }

    function tick() {
        TWEEN.update();
    }

    function tap(e) {
        pressed = true;
        reference = ypos(e);

        velocity = amplitude = 0;
        frame = offset;
        timestamp = Date.now();
        clearInterval(ticker);
        ticker = setInterval(track, 100);

        if(t0) {
            t0.stop();
            t0 = false;
        }
    }

    function drag(e) {
        var y, delta;
        if (pressed) {
            y = ypos(e);
            delta = reference - y;
            if (delta > 2 || delta < -2) {
                reference = y;
                scroll(offset + delta);
            }
        }
        e.preventDefault();
    }

    function release(/*e*/) {
        pressed = false;

        clearInterval(ticker);

        // If no velocity yet, track once make sure
        if(velocity === 0) { track(); }

        if (velocity > 10 || velocity < -10) {
            amplitude = 0.8 * velocity;
            target = Math.round(offset + amplitude);
            timestamp = Date.now();

            p0.y = view.scrollTop;
            t0 = new TWEEN.Tween(p0)
                .to({y: target}, timeConstant)
                .easing(TWEEN.Easing.Quintic.Out)
                .onUpdate(function() {
                    scroll(p0.y);
                    tweenTicker = window.requestAnimationFrame(tick);
                })
                .onComplete(function() {
                    scroll(p0.y);
                    t0.stop();
                    t0 = false;
                });

            t0.start();
            tweenTicker = window.requestAnimationFrame(tick);
        }
    }

    view = typeof viewOrSelector === 'string' ? document.querySelector(viewOrSelector) : viewOrSelector;
    this.bind = function attach() {
        if (typeof window.ontouchstart !== 'undefined') {
            view.addEventListener('touchstart', tap);
            view.addEventListener('touchmove', drag);
            view.addEventListener('touchend', release);
        }
    };

    this.unbind = function detach() {
        if (typeof window.ontouchstart !== 'undefined') {
            view.removeEventListener('touchstart', tap);
            view.removeEventListener('touchmove', drag);
            view.removeEventListener('touchend', release);
        }
    };

    this.reset = function reset() {
        max = parseInt(window.getComputedStyle(view).height, 10) - innerHeight;
        offset = min = 0;
        pressed = false;
        clearInterval(ticker);
        window.cancelAnimationFrame(tweenTicker);
    };

    timeConstant = 2000; // ms

    this.reset();
    this.bind();
}

module.exports = Scroll;
<commit_msg>Add attribution to ariya/kinetic<commit_after>// borrowed heavily from [ariya/kinetic](https://github.com/ariya/kinetic)
var TWEEN;

require("raf.js");

// Just here to simplify the initialization logic.  If
// window doesn't exist, this module is useless anyway
if(typeof window === 'undefined') { window = {}; }

// The build will declare TWEEN as external. However, if it isn't provided by
// browserify, we really want to check to see if it was included directly via
// script tag first.  Only if it isn't will we try a require.  This *should*
// make it easier to bundle/or not and to use with requirejs...
TWEEN = window.TWEEN || require("tween.js");

function Scroll(viewOrSelector, listener) {
    var view,
        min, max, offset, reference, pressed,
        velocity, frame, timestamp, ticker, tweenTicker,
        amplitude, target, timeConstant, innerHeight;

    var p0 = { y: 0 };
    var t0 = false;

    function ypos(e) {
        // touch event
        if (e.targetTouches && (e.targetTouches.length >= 1)) {
            return e.targetTouches[0].clientY;
        }

        // mouse event
        return e.clientY;
    }

    function scroll(y) {
        offset = (y > max) ? max : (y < min) ? min : y;

        view.scrollTop = offset;
        listener.call(view);
    }

    function track() {
        var now, elapsed, delta, v;

        now = Date.now();
        elapsed = now - timestamp;
        timestamp = now;
        delta = offset - frame;
        frame = offset;

        v = 1000 * delta / (1 + elapsed);
        velocity = 0.8 * v + 0.2 * velocity;
    }

    function tick() {
        TWEEN.update();
    }

    function tap(e) {
        pressed = true;
        reference = ypos(e);

        velocity = amplitude = 0;
        frame = offset;
        timestamp = Date.now();
        clearInterval(ticker);
        ticker = setInterval(track, 100);

        if(t0) {
            t0.stop();
            t0 = false;
        }
    }

    function drag(e) {
        var y, delta;
        if (pressed) {
            y = ypos(e);
            delta = reference - y;
            if (delta > 2 || delta < -2) {
                reference = y;
                scroll(offset + delta);
            }
        }
        e.preventDefault();
    }

    function release(/*e*/) {
        pressed = false;

        clearInterval(ticker);

        // If no velocity yet, track once make sure
        if(velocity === 0) { track(); }

        if (velocity > 10 || velocity < -10) {
            amplitude = 0.8 * velocity;
            target = Math.round(offset + amplitude);
            timestamp = Date.now();

            p0.y = view.scrollTop;
            t0 = new TWEEN.Tween(p0)
                .to({y: target}, timeConstant)
                .easing(TWEEN.Easing.Quintic.Out)
                .onUpdate(function() {
                    scroll(p0.y);
                    tweenTicker = window.requestAnimationFrame(tick);
                })
                .onComplete(function() {
                    scroll(p0.y);
                    t0.stop();
                    t0 = false;
                });

            t0.start();
            tweenTicker = window.requestAnimationFrame(tick);
        }
    }

    view = typeof viewOrSelector === 'string' ? document.querySelector(viewOrSelector) : viewOrSelector;
    this.bind = function attach() {
        if (typeof window.ontouchstart !== 'undefined') {
            view.addEventListener('touchstart', tap);
            view.addEventListener('touchmove', drag);
            view.addEventListener('touchend', release);
        }
    };

    this.unbind = function detach() {
        if (typeof window.ontouchstart !== 'undefined') {
            view.removeEventListener('touchstart', tap);
            view.removeEventListener('touchmove', drag);
            view.removeEventListener('touchend', release);
        }
    };

    this.reset = function reset() {
        max = parseInt(window.getComputedStyle(view).height, 10) - innerHeight;
        offset = min = 0;
        pressed = false;
        clearInterval(ticker);
        window.cancelAnimationFrame(tweenTicker);
    };

    timeConstant = 2000; // ms

    this.reset();
    this.bind();
}

module.exports = Scroll;
<|endoftext|>


<commit_before><commit_msg>Try again, Fix CI build, ES6 syntax fixes.<commit_after><|endoftext|>