<commit_before>/*global require:true, process:true */
var util = require("util");
var fs   = require("fs");
//var path = require("path");

function main(args) {
  function printArgs(args) {
    args.forEach(function(arg) {
      util.error(arg);
    });
  }

  function abort(message) {
    util.error(message);
    process.exit(1);
  }

  function readStream(inputStream, callback) {
    var input = "";
    inputStream.on("data", function(data) { input += data; });
    inputStream.on("end", function() { callback(input); });
  }

  function readFile(fn, callback) {
    var inS = fs.createReadStream(fn);
    inS.on("error", function() {
      abort("Can't read from file \"" + fn + "\".");
    });
    readStream(inS, callback);
  }

  var obj, fileList = args, idMap, highestID = 0;

  function merge(obj1, obj2) {
    if (obj2 === undefined) {
      return;
    }
    if (Array.isArray(obj1)) {
      if (Array.isArray(obj2)) {
        obj2.forEach(function (element) {
          obj1.push(element);
        });
      } else {
        obj1.push(obj2);
      }
    } else {
      var key;
      for (key in obj2) {
        if (obj2.hasOwnProperty(key)) {
          if (obj1[key]) {
            if (typeof obj1 === 'object') {
              merge(obj1[key], obj2[key]);
            }
          } else {
            obj1[key] = obj2[key];
          }
        }
      }
    }
  }
  function findHighestID (obj) {
    var key;
    if (Array.isArray(obj)) {
      obj.forEach(function(element) {
        findHighestID(element);
      });
    } else if (typeof obj === 'object') {
      for (key in obj) {
        if (obj.hasOwnProperty(key)) {
          if (key === 'guid') {
            if (obj[key] && typeof obj[key] === 'number') {
              highestID = Math.max(highestID, obj[key]);
            } else {
              abort('Unset or non-numeric guid: ' + obj[key]);
            }
          } else {
            findHighestID(obj[key]);
          }
        }
      }
    }
  }
  function remapIDs (obj) {
    var key;
    if (Array.isArray(obj)) {
      obj.forEach(function(element) {
        remapIDs(element);
      });
    } else if (typeof obj === 'object') {
      for (key in obj) {
        if (obj.hasOwnProperty(key)) {
          if (key === 'guid') {
            highestID++;
            idMap[obj[key]] = highestID;
            obj[key] = highestID;
          } else {
            remapIDs(obj[key]);
          }
        }
      }
    }
  }
  function rereferenceIDs (obj) {
    var key;
    if (Array.isArray(obj)) {
      obj.forEach(function(element) {
        rereferenceIDs(element);
      });
    } else if (typeof obj === 'object') {
      for (key in obj) {
        if (obj.hasOwnProperty(key)) {
          if (key === 'id' || key === 'parent') {
            obj[key] = idMap[obj[key]];
          } else {
            rereferenceIDs(obj[key]);
          }
        }
      }
    }
  }
  function assembleObj(buf) {
    var fn = fileList.splice(0, 1)[0], newObj;
//    if (fn) { util.error('reading ' + fn); }
    if (buf) {
      newObj = JSON.parse(buf);
      if (!obj) {
        obj = newObj;
        findHighestID(obj);
      } else {
        idMap = {};
        remapIDs(newObj);
        rereferenceIDs(newObj);
        merge(obj, newObj);
      }
    }
    if (fn) {
      readFile(fn, assembleObj);
    } else {
      util.puts(JSON.stringify(obj, null, '  '));
    }
  }
//  var outputStream = process.stdout;
//  printArgs(args);
//  args.forEach(function(arg) {
//    var objs = [];
//    readFile(arg, function (buf) {
//      objs.push(JSON.parse(buf));
//    });
//    util.puts('objs: ' + objs.length);
//  });
  assembleObj();

}
main(process.argv.slice(2));<commit_msg>Add merge tool.<commit_after>/*global require:true, process:true */
var util = require("util");
var fs   = require("fs");
//var path = require("path");

function main(args) {
/*
  function printArgs(args) {
    args.forEach(function(arg) {
      util.error(arg);
    });
  }
*/

  function abort(message) {
    util.error(message);
    process.exit(1);
  }

  function readStream(inputStream, callback) {
    var input = "";
    inputStream.on("data", function(data) { input += data; });
    inputStream.on("end", function() { callback(input); });
  }

  function readFile(fn, callback) {
    var inS = fs.createReadStream(fn);
    inS.on("error", function() {
      abort("Can't read from file \"" + fn + "\".");
    });
    readStream(inS, callback);
  }

  var obj, fileList = args, idMap, highestID = 0;

  function merge(obj1, obj2) {
    if (obj2 === undefined) {
      return;
    }
    if (Array.isArray(obj1)) {
      if (Array.isArray(obj2)) {
        obj2.forEach(function (element) {
          obj1.push(element);
        });
      } else {
        obj1.push(obj2);
      }
    } else {
      var key;
      for (key in obj2) {
        if (obj2.hasOwnProperty(key)) {
          if (obj1[key]) {
            if (typeof obj1 === 'object') {
              merge(obj1[key], obj2[key]);
            }
          } else {
            obj1[key] = obj2[key];
          }
        }
      }
    }
  }
  function findHighestID (obj) {
    var key;
    if (Array.isArray(obj)) {
      obj.forEach(function(element) {
        findHighestID(element);
      });
    } else if (typeof obj === 'object') {
      for (key in obj) {
        if (obj.hasOwnProperty(key)) {
          if (key === 'guid') {
            if (obj[key] && typeof obj[key] === 'number') {
              highestID = Math.max(highestID, obj[key]);
            } else {
              abort('Unset or non-numeric guid: ' + obj[key]);
            }
          } else {
            findHighestID(obj[key]);
          }
        }
      }
    }
  }
  function remapIDs (obj) {
    var key;
    if (Array.isArray(obj)) {
      obj.forEach(function(element) {
        remapIDs(element);
      });
    } else if (typeof obj === 'object') {
      for (key in obj) {
        if (obj.hasOwnProperty(key)) {
          if (key === 'guid') {
            highestID++;
            idMap[obj[key]] = highestID;
            obj[key] = highestID;
          } else {
            remapIDs(obj[key]);
          }
        }
      }
    }
  }
  function rereferenceIDs (obj) {
    var key;
    if (Array.isArray(obj)) {
      obj.forEach(function(element) {
        rereferenceIDs(element);
      });
    } else if (typeof obj === 'object') {
      for (key in obj) {
        if (obj.hasOwnProperty(key)) {
          if (key === 'id' || key === 'parent') {
            obj[key] = idMap[obj[key]];
          } else {
            rereferenceIDs(obj[key]);
          }
        }
      }
    }
  }
  function assembleObj(buf) {
    var fn = fileList.splice(0, 1)[0], newObj;
//    if (fn) { util.error('reading ' + fn); }
    if (buf) {
      newObj = JSON.parse(buf);
      if (!obj) {
        obj = newObj;
        findHighestID(obj);
      } else {
        idMap = {};
        remapIDs(newObj);
        rereferenceIDs(newObj);
        merge(obj, newObj);
      }
    }
    if (fn) {
      readFile(fn, assembleObj);
    } else {
      util.puts(JSON.stringify(obj, null, '  '));
    }
  }
//  var outputStream = process.stdout;
//  printArgs(args);
//  args.forEach(function(arg) {
//    var objs = [];
//    readFile(arg, function (buf) {
//      objs.push(JSON.parse(buf));
//    });
//    util.puts('objs: ' + objs.length);
//  });
  assembleObj();

}
main(process.argv.slice(2));
<|endoftext|>


<commit_before>import React from 'react';
import { validateControl,isObject,bindControlToRule } from './../utils/utils';
const withForm = function(Wrappedcomp,controls, formpropname="form"){
    if(!isObject(controls) || Object.keys(controls).length <= 0){
        throw new Error('you need to provide controls in secocde parameter');
    }
    return class WithFormComponent extends React.Component{
        constructor(props){
            super(props);
            this.state = {
                values:{},
                errors:{},
                rules:{},
                dirtys:{}
            }

            Object.keys(controls).map((name) =>{
                this.state.rules[name] = controls[name][1] ? controls[name][1] : [];
                this.state.dirtys[name] = false;
                if(props.prefill && props.prefill[name]){
                    this.state.values[name] = props.prefill[name];
                }else{
                    this.state.values[name] = controls[name][0];
                }

                const bindrules = bindControlToRule(this.state.rules[name],this.state.values);

                this.state.errors[name] = validateControl(this.state.values[name],bindrules,name);
            });
        }

        updateValue(name,value,setDirty){
            const newValues = {
                ...this.state.values,
                [name]:value
            };
            const newDirtys = {
                ...this.state.dirtys,
                [name]:setDirty
            }
            let newErrors = {};
            Object.keys(controls).map((name) => {
                const bindrules = bindControlToRule(this.state.rules[name],newValues);
                newErrors[name] = validateControl(newValues[name],bindrules,name);
            });

            this.setState(()=>{
                return {
                    errors:newErrors,
                    values:newValues,
                    dirtys:newDirtys
                }
            });

        }

        render(){
            const formProp = {
                [formpropname]:{
                    ...this.state,
                    handleChange:(name)=>{
                        return (event)=>{
                            let value;
                            if(event.target.type == "checkbox"){
                                value = event.target.checked;
                            }else{
                                value = event.target.value;
                            }

                            this.updateValue.bind(this)(name,value,true);
                        }

                    },
                    handleValue:(name) => {
                        return (value,setDirty = false)=>{
                            this.updateValue.bind(this)(name,value,setDirty)
                        }
                    }
                }
            }

            return (<Wrappedcomp {...formProp} {...this.props} />);
        }
    }
}

export default withForm;<commit_msg>add support for submitted<commit_after>import React from 'react';
import { validateControl,isObject,bindControlToRule } from './../utils/utils';
const withForm = function(Wrappedcomp,controls, formpropname="form"){
    if(!isObject(controls) || Object.keys(controls).length <= 0){
        throw new Error('you need to provide controls in secocde parameter');
    }
    return class WithFormComponent extends React.Component{
        constructor(props){
            super(props);
            this.state = {
                values:{},
                errors:{},
                rules:{},
                dirtys:{},
                submitted: false
            }

            Object.keys(controls).map((name) =>{
                this.state.rules[name] = controls[name][1] ? controls[name][1] : [];
                this.state.dirtys[name] = false;
                if(props.prefill && props.prefill[name]){
                    this.state.values[name] = props.prefill[name];
                }else{
                    this.state.values[name] = controls[name][0];
                }

                const bindrules = bindControlToRule(this.state.rules[name],this.state.values);

                this.state.errors[name] = validateControl(this.state.values[name],bindrules,name);
            });
        }

        updateValue(name,value,setDirty){
            const newValues = {
                ...this.state.values,
                [name]:value
            };
            const newDirtys = {
                ...this.state.dirtys,
                [name]:setDirty
            }
            let newErrors = {};
            Object.keys(controls).map((name) => {
                const bindrules = bindControlToRule(this.state.rules[name],newValues);
                newErrors[name] = validateControl(newValues[name],bindrules,name);
            });

            this.setState(()=>{
                return {
                    errors:newErrors,
                    values:newValues,
                    dirtys:newDirtys
                }
            });

        }

        setSubmitted(isSubmit){
            this.setState({
                submitted:isSubmit
            });
        }

        render(){
            const formProp = {
                [formpropname]:{
                    ...this.state,
                    handleChange:(name)=>{
                        return (event)=>{
                            let value;
                            if(event.target.type == "checkbox"){
                                value = event.target.checked;
                            }else{
                                value = event.target.value;
                            }

                            this.updateValue.bind(this)(name,value,true);
                        }

                    },
                    handleValue:(name) => {
                        return (value,setDirty = false)=>{
                            this.updateValue.bind(this)(name,value,setDirty)
                        }
                    },
                    setSubmitted:(isSubmit = true) => {
                        this.setSubmitted(isSubmit);
                    }
                }
            }

            return (<Wrappedcomp {...formProp} {...this.props} />);
        }
    }
}

export default withForm;<|endoftext|>


<commit_before>import slug from 'limax'
import path from 'path'

import {config} from '../../'

export function clean(str) {
  if (typeof str === 'undefined' || str === null) return null
  str = str.split(path.sep)
  str[str.length - 1] = slugify(decodeURIComponent(str[str.length - 1]))
  return str.join('/')
}

function slugify(str) {
  str = str.replace(/\..+$/, '')
  str = slug(str, {separateNumbers: false})
  str = `${str}.${config.files.templates.extension}`
  return str.toLowerCase()
}
<commit_msg>fix: Bug under windows on post creation<commit_after>import slug from 'limax'
import path from 'path'

import {config} from '../../'

export function clean(str) {
  if (typeof str === 'undefined' || str === null) return null
  str = str.split('/')
  str[str.length - 1] = slugify(decodeURIComponent(str[str.length - 1]))
  return str.join('/')
}

function slugify(str) {
  str = str.replace(/\..+$/, '')
  str = slug(str, {separateNumbers: false})
  str = `${str}.${config.files.templates.extension}`
  return str.toLowerCase()
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 Titanium I.T. LLC. All rights reserved. See LICENSE.txt for details.
/*global describe, it, expect, dump, $, wwp, afterEach Raphael*/

(function() {
  "use strict";

  describe("Drawing area", function() {

    var drawingDiv;

    afterEach(function() {
      drawingDiv.remove();
    });

    it("should be initialized with Raphael", function() {
      drawingDiv = $('

');
      $(document.body).append(drawingDiv);

      // initialize it (production code)
      wwp.initializeDrawingArea(drawingDiv[0]);

      // verify it was initialized correctly
      var tagName = $(drawingDiv).children()[0].tagName.toLowerCase();
      if (Raphael.type === 'SVG'){
        expect(tagName).to.equal("svg");
      }
      else if(Raphael.type === 'VML'){
        expect(tagName).to.equal("div");
      } else {
        throw new Error("Raphael doesn't support this browser");
      }
    });

    it("should have the same dimensions as its enclosing div", function() {
      drawingDiv = $("
hi
");
      $(document.body).append(drawingDiv);

      var paper = wwp.initializeDrawingArea(drawingDiv[0]);
      expect(paper.width).to.equal(400);
      expect(paper.height).to.equal(200);
    });

    it("should draw a line", function(){
      drawingDiv = $("
hi
");
      $(document.body).append(drawingDiv);
      var paper = wwp.initializeDrawingArea(drawingDiv[0]);

      wwp.drawLine(20, 30, 30, 300);

      var elements = [];
      paper.forEach(function(element){
        elements.push(element);
      });
      expect(elements.length).to.equal(1);
      var element = elements[0];
      var path = pathFor(element);
      expect(path).to.equal("M20,30L30,300");
    });

    function pathFor(element) {
      var path = element.node.attributes.d.value;
      if(path.indexOf(",") !== -1){
        return path;
      }else{
        var ie9Path = /M (\d+) (\d+) L (\d+) (\d+)/;
        var ie9 = path.match(ie9Path);
        return "M" + ie9[1] + "," + ie9[2] + "L" + ie9[3] + "," + ie9[4];
      }
      return path;
    }
  });
}());
<commit_msg>Got Raphael path testing working in IE8<commit_after>// Copyright (c) 2012 Titanium I.T. LLC. All rights reserved. See LICENSE.txt for details.
/*global describe, it, expect, dump, $, wwp, afterEach Raphael*/

(function() {
  "use strict";

  describe("Drawing area", function() {

    var drawingDiv;

    afterEach(function() {
      drawingDiv.remove();
    });

    it("should be initialized with Raphael", function() {
      drawingDiv = $('

');
      $(document.body).append(drawingDiv);

      // initialize it (production code)
      wwp.initializeDrawingArea(drawingDiv[0]);

      // verify it was initialized correctly
      var tagName = $(drawingDiv).children()[0].tagName.toLowerCase();
      if (Raphael.type === 'SVG'){
        expect(tagName).to.equal("svg");
      }
      else if(Raphael.type === 'VML'){
        expect(tagName).to.equal("div");
      } else {
        throw new Error("Raphael doesn't support this browser");
      }
    });

    it("should have the same dimensions as its enclosing div", function() {
      drawingDiv = $("
hi
");
      $(document.body).append(drawingDiv);

      var paper = wwp.initializeDrawingArea(drawingDiv[0]);
      expect(paper.width).to.equal(400);
      expect(paper.height).to.equal(200);
    });

    it("should draw a line", function(){
      drawingDiv = $("
hi
");
      $(document.body).append(drawingDiv);
      var paper = wwp.initializeDrawingArea(drawingDiv[0]);

      wwp.drawLine(20, 30, 30, 300);

      var elements = [];
      paper.forEach(function(element){
        elements.push(element);
      });
      expect(elements.length).to.equal(1);
      var element = elements[0];
      var path = pathFor(element);
      expect(path).to.equal("M20,30L30,300");
    });

    function pathFor(element) {
      var path;
      if(Raphael.vml){
        var VLM_MAGIC_NUMBER = 21600;
        path = element.node.path.value;
        var ie8PathRegex = /m(\d+),(\d+) l(\d+),(\d+) e/;
        var ie8 = path.match(ie8PathRegex);
        var startX = ie8[1] / VLM_MAGIC_NUMBER;
        var startY = ie8[2] / VLM_MAGIC_NUMBER;
        var endX = ie8[3] / VLM_MAGIC_NUMBER;
        var endY = ie8[4] / VLM_MAGIC_NUMBER;
        return 'M' + startX + ',' + startY + 'L' + endX + ',' + endY;
      }
      path = element.node.attributes.d.value;
      if(path.indexOf(",") !== -1){
        return path;
      }else{
        var ie9PathRegex = /M (\d+) (\d+) L (\d+) (\d+)/;
        var ie9 = path.match(ie9PathRegex);
        return "M" + ie9[1] + "," + ie9[2] + "L" + ie9[3] + "," + ie9[4];
      }
      return path;
    }
  });
}());
<|endoftext|>


<commit_before>goog.provide('sand.Game');

goog.require('sand.Config');
goog.require('ss2d.MultiplayerScene');
goog.require('sand.Ball');
goog.require('sand.UserAvatar');
/**
 * @constructor
 * @extends {ss2d.DisplayObjectContainer}
 * */
sand.Game = function()
{
	ss2d.MultiplayerScene.call(this);

	if(COMPILING_SERVER)
	{
		var c=100;
		while(c--)
		{
			var newBall = new sand.Ball(0.5*sand.Config.CANVAS_WIDTH + Math.random()*10, 0.5*sand.Config.CANVAS_HEIGHT + Math.random()*10,10, '#'+Math.floor(Math.max(Math.random(), 0.2)*16777215).toString(16));
			this.addObject(newBall);
		}

		this.mUserTracker = new ss2d.DisplayObjectContainer();
		this.addObject(this.mUserTracker);
	}
}

goog.inherits(sand.Game, ss2d.MultiplayerScene);

ss2d.Object.assignClassId(sand.Game, 3002);

if(COMPILING_CLIENT)
{

	//cast raw object to class
	sand.Game.convert = function(obj)
	{
		ss2d.DisplayObjectContainer.convert.call(obj);
		obj.__proto__ = sand.Game.prototype;

		return obj;
	}

	sand.Game.createFromSerializedObject = function(obj)
	{
		var newDoc = new sand.Game();
		newDoc.mObjectId = obj['doid'];
		return newDoc;
	}
}

if(COMPILING_SERVER)
{
	sand.Game.prototype.onUserConnect = function(connection)
	{
		this.mUserTracker.addObject(new sand.UserAvatar(connection));
	};

	sand.Game.prototype.onUserDisconnect = function(connection)
	{
		for(var iut = 0; iut < this.mUserTracker.mChildren.length; ++iut)
		{
			var child = this.mUserTracker.mChildren[iut];
			if(child.mConnection == connection)
			{
				this.mUserTracker.removeObject(child);
				iut = this.mUserTracker.mChildren.length;
				console.log(connection.mUserName+' disconnect');
			}
		}
	};

	sand.Game.prototype.onUserChangeName = function(connection)
	{
		for(var iut = 0; iut < this.mUserTracker.mChildren.length; ++iut)
		{
			var child = this.mUserTracker.mChildren[iut];
			if(child.mConnection == connection)
			{
				child.mUserName = connection.mUserName;
				iut = this.mUserTracker.mChildren.length;
			}
		}
	};

	sand.Game.prototype.onUserMessage = function(commandPackage, connection)
	{

	};
}
<commit_msg>First correction :D<commit_after>goog.provide('sand.Game');

goog.require('sand.Config');
goog.require('ss2d.MultiplayerScene');
goog.require('sand.Ball');
goog.require('sand.UserAvatar');
/**
 * @constructor
 * @extends {ss2d.MultiplayerScene}
 * */
sand.Game = function()
{
	ss2d.MultiplayerScene.call(this);

	if(COMPILING_SERVER)
	{
		var c=100;
		while(c--)
		{
			var newBall = new sand.Ball(0.5*sand.Config.CANVAS_WIDTH + Math.random()*10, 0.5*sand.Config.CANVAS_HEIGHT + Math.random()*10,10, '#'+Math.floor(Math.max(Math.random(), 0.2)*16777215).toString(16));
			this.addObject(newBall);
		}

		this.mUserTracker = new ss2d.DisplayObjectContainer();
		this.addObject(this.mUserTracker);
	}
}

goog.inherits(sand.Game, ss2d.MultiplayerScene);

ss2d.Object.assignClassId(sand.Game, 3002);

if(COMPILING_CLIENT)
{

	//cast raw object to class
	sand.Game.convert = function(obj)
	{
		ss2d.DisplayObjectContainer.convert.call(obj);
		obj.__proto__ = sand.Game.prototype;

		return obj;
	}

	sand.Game.createFromSerializedObject = function(obj)
	{
		var newDoc = new sand.Game();
		newDoc.mObjectId = obj['doid'];
		return newDoc;
	}
}

if(COMPILING_SERVER)
{
	sand.Game.prototype.onUserConnect = function(connection)
	{
		this.mUserTracker.addObject(new sand.UserAvatar(connection));
	};

	sand.Game.prototype.onUserDisconnect = function(connection)
	{
		for(var iut = 0; iut < this.mUserTracker.mChildren.length; ++iut)
		{
			var child = this.mUserTracker.mChildren[iut];
			if(child.mConnection == connection)
			{
				this.mUserTracker.removeObject(child);
				iut = this.mUserTracker.mChildren.length;
				console.log(connection.mUserName+' disconnect');
			}
		}
	};

	sand.Game.prototype.onUserChangeName = function(connection)
	{
		for(var iut = 0; iut < this.mUserTracker.mChildren.length; ++iut)
		{
			var child = this.mUserTracker.mChildren[iut];
			if(child.mConnection == connection)
			{
				child.mUserName = connection.mUserName;
				iut = this.mUserTracker.mChildren.length;
			}
		}
	};

	sand.Game.prototype.onUserMessage = function(commandPackage, connection)
	{

	};
}
<|endoftext|>


<commit_before>import ProtectedRoute from './protected';

export default ProtectedRoute.extend({
  model: function () {
    return Ember.$.getJSON(UriTemplate.expand(this.get('session').get('currentUser').received_events_url));
  }
});
<commit_msg>Correctly import<commit_after>import Ember from 'ember';
import ProtectedRoute from './protected';

export default ProtectedRoute.extend({
  model: function () {
    return Ember.$.getJSON(UriTemplate.expand(this.get('session').get('currentUser').received_events_url));
  }
});
<|endoftext|>


<commit_before>module.exports = function (express, Language, helperLang) {
    'use strict';

    var Router = express.Router();
    var _ = require('lodash');

    // DECLARATION

    // returns available language list
    Router.get('/list', getLanguages);
    Router.get('/parse', parseLanguages);
    Router.get('/translation/:code', getTranslateByCode);
    Router.get('/switch/:code', switchLanguageByCode);
    // creates new language set
    Router.post('/', postLanguage);
    Router.put('/edit/:code', putLanguageByCode);
    Router.put('/translation/:code/:hash', putLanguageTranslateByCodeAndHash);

    return Router;

    // IMPLEMENTATION

    function getLanguages(req, res) {
        var findObj = {};

        // Interpreters can use only assigned language (for translation)
        if (req.isAuthenticated() && req.user.role === 'interpreter') {
            findObj.code = req.user.assignedLanguage;
        }

        Language
            .find(findObj, '-_id -__v -data')
            .then(function (languages) {
                return res.json(languages);
            })
            .catch(function (err) {
                console.log("Can't get language list: ", err);
                return res.sendStatus(500);
            })
    }

    function switchLanguageByCode(req, res) {
        Language
            .findOne({code: req.params.code})
            .then((language)=> {
                if (!language) return res.sendStatus(404);

                var dictionary = {};
                _.each(language.data, (element)=> {
                    if (element.tr) {
                        dictionary[element.hash] = element.tr;
                    }
                });

                return res.json(dictionary);
            })
            .catch((err)=> {
                console.log("Can't send dictionary: ", err);
                res.sendStatus(err.status || 500);
            });
    }

    function postLanguage(req, res) {
        if (!req.isAuthenticated() || req.user.role !== "admin") {
            return res.sendStatus(403);
        }

        if (!req.body.code || !req.body.name) {
            return res.sendStatus(400);
        }

        Language
            .findOne({code: req.body.code})
            .then(function (language) {
                if (language) {
                    var err = new Error();
                    err.status = 409;
                    throw err;
                }
                language = {
                    code: req.body.code,
                    name: req.body.name
                };
                return Language.createAsync(language);
            })
            .then(function () {
                return res.sendStatus(201);
            })
            .catch(function (err) {
                console.log("Finding duplicate language error: ", err);
                return res.sendStatus(err.status || 500);
            });
    }

    function getTranslateByCode(req, res) {
        if (!req.isAuthenticated()
            || !_.contains(["admin", "interpreter"], req.user.role)) {
            return res.sendStatus(403);
        }

        Language.findOne({code: req.params.code})
            .then((language)=> {
                if (!language) {
                    var err = new Error("Languages not found");
                    err.status = 404;
                    throw err;
                }

                return res.json(language.data);
            })
            .catch((err)=> {
                console.log("Can't get language: ", err);
                return res.sendStatus(err.status || 500);
            })
    }

    function putLanguageByCode(req, res) {
        if (!req.isAuthenticated() || "admin" !== req.user.role) {
            return res.sendStatus(403);
        }

        if (!req.body.name && !req.body.isActive) {
            return res.sendStatus(400);
        }

        Language
            .findOne({code: req.params.code})
            .then((language)=> {
                if (!language) {
                    let err = new Error();
                    err.status = 404;
                    throw err;
                }

                if (req.body.name) language.name = req.body.name;
                if (req.body.isActive === true || req.body.isActive === false) language.isActive = req.body.isActive;

                return language.save();

            })
            .then(()=> res.sendStatus(200))
            .catch((err)=> {
                console.log("Can't modify language: ", err);
                return res.sendStatus(err.status || 500)
            })
    }

    function parseLanguages(req, res) {
        if (!req.isAuthenticated() || "admin" !== req.user.role) {
            return res.sendStatus(403);
        }

        console.log('Parsing language files');
        helperLang.parse()
            .then((parsedStrings)=> {
                return helperLang.updateDB(parsedStrings);
            })
            .then(()=>res.sendStatus(200))
            .catch((err)=> {
                console.log("Can't parse files: ", err);
                return res.sendStatus(err.status || 500);
            });
    }

    function putLanguageTranslateByCodeAndHash(req, res) {
        if (!req.isAuthenticated()
            || !_.contains(["admin", "interpreter"], req.user.role)) {
            return res.sendStatus(403);
        }

        if (_.isUndefined(req.body.translation)) return res.sendStatus(400);

        Language
            .findOne({code: req.params.code})
            .then((language)=> {
                if (!language) {
                    let err = new Error();
                    err.status = 404;
                    throw err;
                }

                // !!! Hash is NUMBER value !!!
                var idx = _.findIndex(language.data, 'hash', Number(req.params.hash));
                if (idx === -1) {
                    let err = new Error();
                    err.status = 404;
                    throw err;
                }

                language.data[idx].tr = req.body.translation;
                language.data[idx].status = req.body.translation ? '!' : '+';

                return language.save();

            })
            .then(()=> res.sendStatus(200))
            .catch((err)=> {
                console.log("Can't modify translation: ", err);
                return res.sendStatus(err.status || 500)
            })
    }

};
<commit_msg>Interpreter can parse language files too<commit_after>module.exports = function (express, Language, helperLang) {
    'use strict';

    var Router = express.Router();
    var _ = require('lodash');

    // DECLARATION

    // returns available language list
    Router.get('/list', getLanguages);
    Router.get('/parse', parseLanguages);
    Router.get('/translation/:code', getTranslateByCode);
    Router.get('/switch/:code', switchLanguageByCode);
    // creates new language set
    Router.post('/', postLanguage);
    Router.put('/edit/:code', putLanguageByCode);
    Router.put('/translation/:code/:hash', putLanguageTranslateByCodeAndHash);

    return Router;

    // IMPLEMENTATION

    function getLanguages(req, res) {
        var findObj = {};

        // Interpreters can use only assigned language (for translation)
        if (req.isAuthenticated() && req.user.role === 'interpreter') {
            findObj.code = req.user.assignedLanguage;
        }

        Language
            .find(findObj, '-_id -__v -data')
            .then(function (languages) {
                return res.json(languages);
            })
            .catch(function (err) {
                console.log("Can't get language list: ", err);
                return res.sendStatus(500);
            })
    }

    function switchLanguageByCode(req, res) {
        Language
            .findOne({code: req.params.code})
            .then((language)=> {
                if (!language) return res.sendStatus(404);

                var dictionary = {};
                _.each(language.data, (element)=> {
                    if (element.tr) {
                        dictionary[element.hash] = element.tr;
                    }
                });

                return res.json(dictionary);
            })
            .catch((err)=> {
                console.log("Can't send dictionary: ", err);
                res.sendStatus(err.status || 500);
            });
    }

    function postLanguage(req, res) {
        if (!req.isAuthenticated() || req.user.role !== "admin") {
            return res.sendStatus(403);
        }

        if (!req.body.code || !req.body.name) {
            return res.sendStatus(400);
        }

        Language
            .findOne({code: req.body.code})
            .then(function (language) {
                if (language) {
                    var err = new Error();
                    err.status = 409;
                    throw err;
                }
                language = {
                    code: req.body.code,
                    name: req.body.name
                };
                return Language.createAsync(language);
            })
            .then(function () {
                return res.sendStatus(201);
            })
            .catch(function (err) {
                console.log("Finding duplicate language error: ", err);
                return res.sendStatus(err.status || 500);
            });
    }

    function getTranslateByCode(req, res) {
        if (!req.isAuthenticated()
            || !_.contains(["admin", "interpreter"], req.user.role)) {
            return res.sendStatus(403);
        }

        Language.findOne({code: req.params.code})
            .then((language)=> {
                if (!language) {
                    var err = new Error("Languages not found");
                    err.status = 404;
                    throw err;
                }

                return res.json(language.data);
            })
            .catch((err)=> {
                console.log("Can't get language: ", err);
                return res.sendStatus(err.status || 500);
            })
    }

    function putLanguageByCode(req, res) {
        if (!req.isAuthenticated() || "admin" !== req.user.role) {
            return res.sendStatus(403);
        }

        if (!req.body.name && !req.body.isActive) {
            return res.sendStatus(400);
        }

        Language
            .findOne({code: req.params.code})
            .then((language)=> {
                if (!language) {
                    let err = new Error();
                    err.status = 404;
                    throw err;
                }

                if (req.body.name) language.name = req.body.name;
                if (req.body.isActive === true || req.body.isActive === false) language.isActive = req.body.isActive;

                return language.save();

            })
            .then(()=> res.sendStatus(200))
            .catch((err)=> {
                console.log("Can't modify language: ", err);
                return res.sendStatus(err.status || 500)
            })
    }

    function parseLanguages(req, res) {
        if (!req.isAuthenticated()
            || !_.contains(["admin", "interpreter"], req.user.role)) {
            return res.sendStatus(403);
        }

        console.log('Parsing language files');
        helperLang.parse()
            .then((parsedStrings)=> {
                return helperLang.updateDB(parsedStrings);
            })
            .then(()=>res.sendStatus(200))
            .catch((err)=> {
                console.log("Can't parse files: ", err);
                return res.sendStatus(err.status || 500);
            });
    }

    function putLanguageTranslateByCodeAndHash(req, res) {
        if (!req.isAuthenticated()
            || !_.contains(["admin", "interpreter"], req.user.role)) {
            return res.sendStatus(403);
        }

        if (_.isUndefined(req.body.translation)) return res.sendStatus(400);

        Language
            .findOne({code: req.params.code})
            .then((language)=> {
                if (!language) {
                    let err = new Error();
                    err.status = 404;
                    throw err;
                }

                // !!! Hash is NUMBER value !!!
                var idx = _.findIndex(language.data, 'hash', Number(req.params.hash));
                if (idx === -1) {
                    let err = new Error();
                    err.status = 404;
                    throw err;
                }

                language.data[idx].tr = req.body.translation;
                language.data[idx].status = req.body.translation ? '!' : '+';

                return language.save();

            })
            .then(()=> res.sendStatus(200))
            .catch((err)=> {
                console.log("Can't modify translation: ", err);
                return res.sendStatus(err.status || 500)
            })
    }

};
<|endoftext|>


<commit_before>'use strict';

/**
 * Main game object
 * @type {Object}
 * @param {string} [canvasId] id of the canvas where the game needs to take place
 */
var Game = function(canvasId) {
  var ctx = document.getElementById(canvasId).getContext('2d');

  var clearCanvas = function() {
    // Store the current transformation matrix
    ctx.save();
    // Use the identity matrix while clearing the canvas
    ctx.setTransform(1, 0, 0, 1, 0, 0);
    ctx.clearRect(0, 0, stage.width, stage.height);
    // Restore the transform
    ctx.restore();
  };

  /**
   * Settings
   */
  var stage = {
    width: 480,
    height: 320,
    speed: 600 // speed of the game - lower is faster
  };

  var KEYS = {
    left: 37,
    up: 38,
    right: 39,
    down: 40
  };

  /**
   * Game related variables and init
   */
  var intervalId;
  var snake = new Snake(stage.width / 2, stage.height / 2, 3);
  var food = new Food();

  // starting input direction
  var direction = {
    axis: 'x',
    sign: -1
  };

  var draw = function() {
    clearCanvas(ctx);
    snake.move(direction);
    if (food) {
      food.draw();
    }

    if (snake.ate(food)) {
      food = new Food();
      food.draw();
    }
    snake.draw();
  };

  var init = function() {
    snake.draw();
    intervalId = window.setInterval(draw, stage.speed);
  };

  var stop = function() {
    window.clearInterval(intervalId);
  };

  var keyListener = function(e) {
    e = e || window.event;

    switch (e.keyCode) {
    case KEYS.left:
      direction = { axis: 'x', sign: -1 };
      break;
    case KEYS.right:
      direction = { axis: 'x', sign: 1 };
      break;
    case KEYS.down:
      direction = { axis: 'y', sign: 1 };
      break;
    case KEYS.up:
      direction = { axis: 'y', sign: -1 };
      break;
    }
  };

  document.onkeydown = keyListener;

  var deadScreen = function() {
    stop();
    ctx.fillStyle = 'black';
    ctx.strokeStyle = 'black';
    ctx.font = 'bold 20px sans-serif';
    ctx.fillText('YOU DEAD', 50, 50);
  };

  /**
   * Snake constructor takes initial position of the snake and number of segments to start with
   * @param {float} [x]
   * @param {float} [y]
   * @param {int} [segments] [number of segments the work should be costructed with]
   */
  function Snake(x, y, segments) {
    this.height = 20;
    this.width = this.height;
    this.x = x;
    this.y = y;
    this.speed = this.height;
    this.color = 'rgb(200,0,0)';
    this.direction = {
      axis: 'x',
      sign: -1
    };
    this.length = 0;

    this.bottomEdge = function () {
      return this.y + this.height;
    };
    this.rightEdge = function () {
      return this.x + this.width;
    };

    this.addSegment = function (x, y, toEnd) {
      var block = {
        width: this.height,
        height: this.height,
        x: x,
        y: y
      };

      if (toEnd) {
        this.segments.push(block);
      } else {
        this.segments.unshift(block);
      }
      this.length++;
    };

    this.segments = [];

    for (var i = 0; i < segments; i++) {
      this.addSegment(this.x + this.width * i, this.y, true);
    }
  }

  Snake.prototype.draw = function() {

    ctx.fillStyle = this.color;
    for (var i = 0; i < this.segments.length; i++) {
      ctx.fillRect(this.segments[i].x, this.segments[i].y, this.segments[i].width, this.segments[i].height);
    }
  };

  Snake.prototype.move = function(direction) {
    // See if the input is trying to make the snake move back into itself.
    var movingOpposite = this.direction.axis === direction.axis && this.direction.sign != direction.sign;
    var moveBy = movingOpposite ? this.width * this.direction.sign : this.width * direction.sign;

    // Set the head position of the snake
    if (direction.axis === 'x') {
      this.x = this.x + moveBy;
    } else if (direction.axis === 'y') {
      this.y = this.y + moveBy;
    }

    // Check if not hitting the walls
    if (this.x < 0 || this.rightEdge() > stage.width ||
        this.y < 0 || this.bottomEdge() > stage.height) {

      deadScreen();
    } else {
      // Draw the next segment and remove the previous one
      this.addSegment(this.x, this.y);
      this.segments.pop();
    }

    // Assign new direction to the snake
    if (!movingOpposite) {
      this.direction = {
        axis: direction.axis,
        sign: direction.sign
      };
    }

  };

  Snake.prototype.ate = function(food) {
    var overlapX = this.x >= food.x && this.x <= (food.x + food.size);
    var overlapY = this.y >= food.y && this.y <= (food.y + food.size);
    if (overlapX && overlapY) {
      var lastSegment = this.segments[this.segments.length - 1];
      this.addSegment(lastSegment.x + this.width * this.direction.sign, lastSegment.y + this.height * this.direction.sign, true);
      return true;
    }
    return false;
  };

  function Food(x, y) {
    this.size = 20;
    this.x = x || snapToGrid(Math.random() * (stage.width - this.size));
    this.y = y || snapToGrid(Math.random() * (stage.height - this.size));
    this.color = '#377ABD';

    this.draw = function() {
      ctx.fillStyle = this.color;
      ctx.beginPath();
      ctx.arc(this.x + this.size/2, this.y + this.size/2, this.size/2, 0, Math.PI*2, false);
      ctx.fill();
    };
  }

  function snapToGrid(coordinate) {
    coordinate = Math.floor(coordinate);
    var remainder = coordinate % 20;
    return coordinate - remainder;
  }

  return {
    init: init,
    stop: stop
  };
};

var game = new Game('game-screen');
game.init();<commit_msg>Fixed tail segment addition into proper position after eating<commit_after>'use strict';

/**
 * Main game object
 * @type {Object}
 * @param {string} [canvasId] id of the canvas where the game needs to take place
 */
var Game = function(canvasId) {
  var ctx = document.getElementById(canvasId).getContext('2d');

  var clearCanvas = function() {
    // Store the current transformation matrix
    ctx.save();
    // Use the identity matrix while clearing the canvas
    ctx.setTransform(1, 0, 0, 1, 0, 0);
    ctx.clearRect(0, 0, stage.width, stage.height);
    // Restore the transform
    ctx.restore();
  };

  /**
   * Settings
   */
  var stage = {
    width: 480,
    height: 320,
    speed: 600 // speed of the game - lower is faster
  };

  var KEYS = {
    left: 37,
    up: 38,
    right: 39,
    down: 40
  };

  /**
   * Game related variables and init
   */
  var intervalId;
  var snake = new Snake(stage.width / 2, stage.height / 2, 3);
  var food = new Food();

  // starting input direction
  var direction = {
    axis: 'x',
    sign: -1
  };

  var draw = function() {
    clearCanvas(ctx);
    snake.move(direction);
    if (food) {
      food.draw();
    }

    if (snake.ate(food)) {
      food = new Food();
      food.draw();
    }
    snake.draw();
  };

  var init = function() {
    snake.draw();
    intervalId = window.setInterval(draw, stage.speed);
  };

  var stop = function() {
    window.clearInterval(intervalId);
  };

  var keyListener = function(e) {
    e = e || window.event;

    switch (e.keyCode) {
    case KEYS.left:
      direction = { axis: 'x', sign: -1 };
      break;
    case KEYS.right:
      direction = { axis: 'x', sign: 1 };
      break;
    case KEYS.down:
      direction = { axis: 'y', sign: 1 };
      break;
    case KEYS.up:
      direction = { axis: 'y', sign: -1 };
      break;
    }
  };

  document.onkeydown = keyListener;

  var deadScreen = function() {
    stop();
    ctx.fillStyle = 'black';
    ctx.strokeStyle = 'black';
    ctx.font = 'bold 20px sans-serif';
    ctx.fillText('YOU DEAD', 50, 50);
  };

  /**
   * Snake constructor takes initial position of the snake and number of segments to start with
   * @param {float} [x]
   * @param {float} [y]
   * @param {int} [segments] [number of segments the work should be costructed with]
   */
  function Snake(x, y, segments) {
    this.height = 20;
    this.width = this.height;
    this.x = x;
    this.y = y;
    this.speed = this.height;
    this.color = 'rgb(200,0,0)';
    this.direction = {
      axis: 'x',
      sign: -1
    };
    this.length = 0;
    this.tailPosition = {};

    this.bottomEdge = function () {
      return this.y + this.height;
    };
    this.rightEdge = function () {
      return this.x + this.width;
    };

    this.addSegment = function (x, y, toEnd) {
      var block = {
        width: this.height,
        height: this.height,
        x: x,
        y: y
      };

      if (toEnd) {
        this.segments.push(block);
      } else {
        this.segments.unshift(block);
      }
      this.length++;
    };

    this.segments = [];

    for (var i = 0; i < segments; i++) {
      this.addSegment(this.x + this.width * i, this.y, true);
    }
  }

  Snake.prototype.draw = function() {

    ctx.fillStyle = this.color;
    for (var i = 0; i < this.segments.length; i++) {
      ctx.fillRect(this.segments[i].x, this.segments[i].y, this.segments[i].width, this.segments[i].height);
    }
  };

  Snake.prototype.move = function(direction) {
    // See if the input is trying to make the snake move back into itself.
    var movingOpposite = this.direction.axis === direction.axis && this.direction.sign != direction.sign;
    var moveBy = movingOpposite ? this.width * this.direction.sign : this.width * direction.sign;

    // Set the head position of the snake
    if (direction.axis === 'x') {
      this.x = this.x + moveBy;
    } else if (direction.axis === 'y') {
      this.y = this.y + moveBy;
    }

    // Check if not hitting the walls
    if (this.x < 0 || this.rightEdge() > stage.width ||
        this.y < 0 || this.bottomEdge() > stage.height) {

      deadScreen();
    } else {
      // Draw the next segment and remove the previous one
      this.addSegment(this.x, this.y);
      this.tailPosition = {
        x: this.segments[this.segments.length - 1].x,
        y: this.segments[this.segments.length - 1].y
      };
      this.segments.pop();
    }

    // Assign new direction to the snake
    if (!movingOpposite) {
      this.direction = {
        axis: direction.axis,
        sign: direction.sign
      };
    }

  };

  Snake.prototype.ate = function(food) {
    var overlapX = this.x >= food.x && this.x <= (food.x + food.size);
    var overlapY = this.y >= food.y && this.y <= (food.y + food.size);
    if (overlapX && overlapY) {
      this.addSegment(this.tailPosition.x, this.tailPosition.y, true);
      return true;
    }
    return false;
  };

  function Food(x, y) {
    this.size = 20;
    this.x = x || snapToGrid(Math.random() * (stage.width - this.size));
    this.y = y || snapToGrid(Math.random() * (stage.height - this.size));
    this.color = '#377ABD';

    this.draw = function() {
      ctx.fillStyle = this.color;
      ctx.beginPath();
      ctx.arc(this.x + this.size/2, this.y + this.size/2, this.size/2, 0, Math.PI*2, false);
      ctx.fill();
    };
  }

  function snapToGrid(coordinate) {
    coordinate = Math.floor(coordinate);
    var remainder = coordinate % 20;
    return coordinate - remainder;
  }

  return {
    init: init,
    stop: stop
  };
};

var game = new Game('game-screen');
game.init();<|endoftext|>


<commit_before>import { createSelector } from 'reselect';
import _ from 'lodash';

const getProducts = state => state.products;
const getPromotionSets = state => state.promotionSets;
const getMobileTopup = state => state.mobileTopup;
const getDiscounts = state => state.discounts;
const getEvent = state => state.event;

const getSelectedEvent = createSelector(
  [getEvent],
  (event) => {
    return event.selectedEvent;
  }
);

const getEventId = createSelector(
  [getSelectedEvent],
  (event) => {
    return event.eventId;
  }
);

const getEventProduct = createSelector(
  [getSelectedEvent],
  (event) => {
    return event.product || {}
  }
);

const getEventRewards = createSelector(
  [getSelectedEvent],
  (event) => {
    return event.rewards || [];
  }
);

const getEventNextReward = createSelector(
  [getEventRewards],
  (eventRewards) => {
    if (_.size(eventRewards) <= 0) return '';
    const nextItem = _.find(eventRewards, item => item.completed === false);
    return nextItem;
  }
);

const getEventRewardInstantly = createSelector(
  [getEventRewards],
  (eventRewards) => {
    return _.find(eventRewards, eventReward => _.includes(['VENDING_MACHINE_NOW'], eventReward.channel.toUpperCase()));
  }
);

const getEventNextRewardRoute = createSelector(
  [getEventNextReward],
  (eventNextReward) => {
    if (!eventNextReward) return 'REWARD_NOT_FOUND';
    const targetProduct = eventNextReward.name;
    switch (targetProduct) {
      case 'MOBILE_TOPUP':
        return '/topup';
      case 'PRODUCT':
        return '/product/single';
      default:
        return 'PAGE_NOT_FOUND';
    }
  }
);

const getEventInputs = createSelector(
  [getSelectedEvent],
  (selectedEvent) => {
    return selectedEvent.inputs || [];
  }
);

const getEventNextInput = createSelector(
  [getEventInputs],
  (eventInputs) => {
    if (_.size(eventInputs) <= 0) return '';
    const nextItem = _.find(eventInputs, item => item.completed === false);
    return nextItem ? nextItem.name.toUpperCase() : '';
  }
);

const getEventWatches = createSelector(
  [getSelectedEvent],
  (selectedEvent) => {
    return selectedEvent.watches || [];
  }
);

const getEventNextWatch = createSelector(
  [getEventWatches],
  (eventWatches) => {
    if (_.size(eventWatches) <= 0) return '';
    const nextItem = _.find(eventWatches, item => item.completed === false);
    return nextItem;
  }
);

const verifyEventShouldSendReward = createSelector(
  [getEventRewards],
  (eventRewards) => {
    const foundChannel = _.some(eventRewards, reward => _.includes(['SMS', 'EMAIL'], reward.channel.toUpperCase()));
    return foundChannel;
  }
);

const verifyEventShouldUseRewardInstantly = createSelector(
  [getEventRewards],
  (eventRewards) => {
    const foundChannel = _.some(eventRewards, reward => _.includes(['VENDING_MACHINE'], reward.channel.toUpperCase()));
    return foundChannel;
  }
);

const getDiscount = createSelector(
  [getDiscounts],
  (discounts) => {
    return _.head(discounts);
  }
);

const getDiscountAmount = createSelector(
  [getDiscounts],
  (discounts) => {
    return Number(_.sumBy(discounts, discount => Number(discount.value)));
  }
);

const verifyOrderHasDiscount = createSelector(
  [getDiscounts],
  (discounts) => {
    return _.size(discounts) > 0;
  }
);

const getTopupMSISDN = createSelector([getMobileTopup], mobileTopup => mobileTopup.MSISDN || '');

const getSelectedMobileTopupProvider = createSelector(
  [getMobileTopup],
  mobileTopup => mobileTopup.selectedMobileTopupProvider || {},
);

const getSelectedMobileTopupValue = createSelector(
  [getMobileTopup],
  mobileTopup => mobileTopup.selectedMobileTopupValue || {},
);

const getSelectedMobileTopupPrice = createSelector(
  [getSelectedMobileTopupValue],
  selectedMobileTopupValue => Number(selectedMobileTopupValue.value),
);

const getSelectedMobileTopupTotalPrice = createSelector(
  [getSelectedMobileTopupValue, getSelectedMobileTopupPrice],
  (selectedMobileTopupValue, selectedMobileTopupPrice) =>
    selectedMobileTopupPrice + Number(selectedMobileTopupValue.fee),
);

const getMobileTopupName = createSelector(
  [getSelectedMobileTopupProvider],
  selectedMobileTopupProvider => selectedMobileTopupProvider.name || '',
);

const getMobileTopupBanner = createSelector(
  [getSelectedMobileTopupProvider],
  selectedMobileTopupProvider => selectedMobileTopupProvider.banner || '',
);

const getMobileTopupServiceCode = createSelector(
  [getSelectedMobileTopupProvider],
  selectedMobileTopupProvider => selectedMobileTopupProvider.serviceCode || '',
);

const getMobileTopupToService = createSelector(
  [getMobileTopupServiceCode, getTopupMSISDN, getSelectedMobileTopupPrice],
  (serviceCode, MSISDN, mobileTopupValue) => ({
    serviceCode,
    MSISDN,
    mobileTopupValue,
  }),
);

const getSingleProduct = createSelector([getProducts], products => _.head(products));

const getPromotionSet = createSelector([getPromotionSets], promotionSets => _.head(promotionSets));

const getPromotionSetProducts = createSelector([getPromotionSet], promotionSet =>
  _.get(promotionSet, 'products', []),
);

const getSingleProductPrice = createSelector([getSingleProduct], singleProduct =>
  Number(_.get(singleProduct, 'price', '')),
);

const getPromotionSetPrice = createSelector([getPromotionSet], promotionSet =>
  Number(_.get(promotionSet, 'price', '')),
);

const getPromotionSetFirstProductPrice = createSelector([getPromotionSetProducts], products =>
  Number(_.head(products).price),
);

const getDroppedProducts = createSelector([getProducts], products =>
  _.filter(products, product => product.isDropped),
);

const getDroppedProductSummaryPrice = createSelector([getDroppedProducts], products =>
  _.sumBy(products, product => Number(product.price)),
);

const getProductToDrop = createSelector([getProducts], products =>
  _.find(products, product => !product.isDropped),
);

const getDropProductTargetRowColumn = createSelector(
  [getProductToDrop],
  productToDrop => `${productToDrop.row}${productToDrop.col}`,
);

const verifyOrderHasProduct = createSelector([getProducts], products => _.size(products) > 0);

const verifyHasDroppedProduct = createSelector([getProducts], products =>
  _.some(products, product => product.isDropped),
);

const verifyAllOrderDropped = createSelector([getProducts], products =>
  _.every(products, product => product.isDropped),
);

const verifyOrderHasPromotionSet = createSelector(
  [getPromotionSets],
  promotionSets => _.size(promotionSets) > 0,
);

const verifyMobileTopupOrder = createSelector(
  [getSelectedMobileTopupProvider],
  selectedMobileTopup => !_.isEmpty(selectedMobileTopup),
);

const getOrderGrandTotalAmount = createSelector(
  [
    verifyOrderHasPromotionSet,
    verifyMobileTopupOrder,
    getSelectedMobileTopupTotalPrice,
    getSingleProductPrice,
    getPromotionSetPrice,
    getDiscountAmount,
  ],
  (
    hasPromotionSet,
    hasMobileTopup,
    selectedMobileTopupTotalPrice,
    singleProductPrice,
    promotionSetPrice,
    discountAmount,
  ) => {
    if (hasMobileTopup) return selectedMobileTopupTotalPrice;
    return hasPromotionSet ? promotionSetPrice - discountAmount : singleProductPrice - discountAmount;
  },
);

export default {
  // ======================================================
  // Event
  // ======================================================
  getEvent,
  getSelectedEvent,
  getEventId,
  getEventProduct,
  getEventRewards,
  getEventRewardInstantly,
  getEventNextReward,
  getEventNextRewardRoute,
  getEventInputs,
  getEventNextInput,
  getEventWatches,
  getEventNextWatch,
  verifyEventShouldSendReward,
  verifyEventShouldUseRewardInstantly,
  // ======================================================
  // Mobile Topup
  // ======================================================
  getMobileTopup,
  getTopupMSISDN,
  getSelectedMobileTopupProvider,
  getSelectedMobileTopupValue,
  getSelectedMobileTopupTotalPrice,
  getMobileTopupName,
  getMobileTopupBanner,
  getMobileTopupServiceCode,
  getMobileTopupToService,
  // ======================================================
  // Single Product
  // ======================================================
  getProducts,
  getSingleProduct,
  getSingleProductPrice,
  // ======================================================
  // PromotionSet
  // ======================================================
  getPromotionSet,
  getPromotionSetProducts,
  getPromotionSetPrice,
  getPromotionSetFirstProductPrice,
  getProductToDrop,
  getDropProductTargetRowColumn,
  getDroppedProductSummaryPrice,
  // ======================================================
  // Flag
  // ======================================================
  verifyOrderHasProduct,
  verifyHasDroppedProduct,
  verifyAllOrderDropped,
  verifyOrderHasPromotionSet,
  verifyMobileTopupOrder,
  // ======================================================
  // Payment
  // ======================================================
  getOrderGrandTotalAmount,
  // ======================================================
  // Discount
  // ======================================================
  getDiscounts,
  getDiscount,
  getDiscountAmount,
  verifyOrderHasDiscount
};
<commit_msg>Fix Mobile Topup don't minus discount<commit_after>import { createSelector } from 'reselect';
import _ from 'lodash';

const getProducts = state => state.products;
const getPromotionSets = state => state.promotionSets;
const getMobileTopup = state => state.mobileTopup;
const getDiscounts = state => state.discounts;
const getEvent = state => state.event;

const getSelectedEvent = createSelector(
  [getEvent],
  (event) => {
    return event.selectedEvent;
  }
);

const getEventId = createSelector(
  [getSelectedEvent],
  (event) => {
    return event.eventId;
  }
);

const getEventProduct = createSelector(
  [getSelectedEvent],
  (event) => {
    return event.product || {}
  }
);

const getEventRewards = createSelector(
  [getSelectedEvent],
  (event) => {
    return event.rewards || [];
  }
);

const getEventNextReward = createSelector(
  [getEventRewards],
  (eventRewards) => {
    if (_.size(eventRewards) <= 0) return '';
    const nextItem = _.find(eventRewards, item => item.completed === false);
    return nextItem;
  }
);

const getEventRewardInstantly = createSelector(
  [getEventRewards],
  (eventRewards) => {
    return _.find(eventRewards, eventReward => _.includes(['VENDING_MACHINE_NOW'], eventReward.channel.toUpperCase()));
  }
);

const getEventNextRewardRoute = createSelector(
  [getEventNextReward],
  (eventNextReward) => {
    if (!eventNextReward) return 'REWARD_NOT_FOUND';
    const targetProduct = eventNextReward.name;
    switch (targetProduct) {
      case 'MOBILE_TOPUP':
        return '/topup';
      case 'PRODUCT':
        return '/product/single';
      default:
        return 'PAGE_NOT_FOUND';
    }
  }
);

const getEventInputs = createSelector(
  [getSelectedEvent],
  (selectedEvent) => {
    return selectedEvent.inputs || [];
  }
);

const getEventNextInput = createSelector(
  [getEventInputs],
  (eventInputs) => {
    if (_.size(eventInputs) <= 0) return '';
    const nextItem = _.find(eventInputs, item => item.completed === false);
    return nextItem ? nextItem.name.toUpperCase() : '';
  }
);

const getEventWatches = createSelector(
  [getSelectedEvent],
  (selectedEvent) => {
    return selectedEvent.watches || [];
  }
);

const getEventNextWatch = createSelector(
  [getEventWatches],
  (eventWatches) => {
    if (_.size(eventWatches) <= 0) return '';
    const nextItem = _.find(eventWatches, item => item.completed === false);
    return nextItem;
  }
);

const verifyEventShouldSendReward = createSelector(
  [getEventRewards],
  (eventRewards) => {
    const foundChannel = _.some(eventRewards, reward => _.includes(['SMS', 'EMAIL'], reward.channel.toUpperCase()));
    return foundChannel;
  }
);

const verifyEventShouldUseRewardInstantly = createSelector(
  [getEventRewards],
  (eventRewards) => {
    const foundChannel = _.some(eventRewards, reward => _.includes(['VENDING_MACHINE'], reward.channel.toUpperCase()));
    return foundChannel;
  }
);

const getDiscount = createSelector(
  [getDiscounts],
  (discounts) => {
    return _.head(discounts);
  }
);

const getDiscountAmount = createSelector(
  [getDiscounts],
  (discounts) => {
    return Number(_.sumBy(discounts, discount => Number(discount.value)));
  }
);

const verifyOrderHasDiscount = createSelector(
  [getDiscounts],
  (discounts) => {
    return _.size(discounts) > 0;
  }
);

const getTopupMSISDN = createSelector([getMobileTopup], mobileTopup => mobileTopup.MSISDN || '');

const getSelectedMobileTopupProvider = createSelector(
  [getMobileTopup],
  mobileTopup => mobileTopup.selectedMobileTopupProvider || {},
);

const getSelectedMobileTopupValue = createSelector(
  [getMobileTopup],
  mobileTopup => mobileTopup.selectedMobileTopupValue || {},
);

const getSelectedMobileTopupPrice = createSelector(
  [getSelectedMobileTopupValue],
  selectedMobileTopupValue => Number(selectedMobileTopupValue.value),
);

const getSelectedMobileTopupTotalPrice = createSelector(
  [getSelectedMobileTopupValue, getSelectedMobileTopupPrice],
  (selectedMobileTopupValue, selectedMobileTopupPrice) =>
    selectedMobileTopupPrice + Number(selectedMobileTopupValue.fee),
);

const getMobileTopupName = createSelector(
  [getSelectedMobileTopupProvider],
  selectedMobileTopupProvider => selectedMobileTopupProvider.name || '',
);

const getMobileTopupBanner = createSelector(
  [getSelectedMobileTopupProvider],
  selectedMobileTopupProvider => selectedMobileTopupProvider.banner || '',
);

const getMobileTopupServiceCode = createSelector(
  [getSelectedMobileTopupProvider],
  selectedMobileTopupProvider => selectedMobileTopupProvider.serviceCode || '',
);

const getMobileTopupToService = createSelector(
  [getMobileTopupServiceCode, getTopupMSISDN, getSelectedMobileTopupPrice],
  (serviceCode, MSISDN, mobileTopupValue) => ({
    serviceCode,
    MSISDN,
    mobileTopupValue,
  }),
);

const getSingleProduct = createSelector([getProducts], products => _.head(products));

const getPromotionSet = createSelector([getPromotionSets], promotionSets => _.head(promotionSets));

const getPromotionSetProducts = createSelector([getPromotionSet], promotionSet =>
  _.get(promotionSet, 'products', []),
);

const getSingleProductPrice = createSelector([getSingleProduct], singleProduct =>
  Number(_.get(singleProduct, 'price', '')),
);

const getPromotionSetPrice = createSelector([getPromotionSet], promotionSet =>
  Number(_.get(promotionSet, 'price', '')),
);

const getPromotionSetFirstProductPrice = createSelector([getPromotionSetProducts], products =>
  Number(_.head(products).price),
);

const getDroppedProducts = createSelector([getProducts], products =>
  _.filter(products, product => product.isDropped),
);

const getDroppedProductSummaryPrice = createSelector([getDroppedProducts], products =>
  _.sumBy(products, product => Number(product.price)),
);

const getProductToDrop = createSelector([getProducts], products =>
  _.find(products, product => !product.isDropped),
);

const getDropProductTargetRowColumn = createSelector(
  [getProductToDrop],
  productToDrop => `${productToDrop.row}${productToDrop.col}`,
);

const verifyOrderHasProduct = createSelector([getProducts], products => _.size(products) > 0);

const verifyHasDroppedProduct = createSelector([getProducts], products =>
  _.some(products, product => product.isDropped),
);

const verifyAllOrderDropped = createSelector([getProducts], products =>
  _.every(products, product => product.isDropped),
);

const verifyOrderHasPromotionSet = createSelector(
  [getPromotionSets],
  promotionSets => _.size(promotionSets) > 0,
);

const verifyMobileTopupOrder = createSelector(
  [getSelectedMobileTopupProvider],
  selectedMobileTopup => !_.isEmpty(selectedMobileTopup),
);

const getOrderGrandTotalAmount = createSelector(
  [
    verifyOrderHasPromotionSet,
    verifyMobileTopupOrder,
    getSelectedMobileTopupTotalPrice,
    getSingleProductPrice,
    getPromotionSetPrice,
    getDiscountAmount,
  ],
  (
    hasPromotionSet,
    hasMobileTopup,
    selectedMobileTopupTotalPrice,
    singleProductPrice,
    promotionSetPrice,
    discountAmount,
  ) => {
    if (hasMobileTopup) return selectedMobileTopupTotalPrice - discountAmount;
    return hasPromotionSet ? promotionSetPrice - discountAmount : singleProductPrice - discountAmount;
  },
);

export default {
  // ======================================================
  // Event
  // ======================================================
  getEvent,
  getSelectedEvent,
  getEventId,
  getEventProduct,
  getEventRewards,
  getEventRewardInstantly,
  getEventNextReward,
  getEventNextRewardRoute,
  getEventInputs,
  getEventNextInput,
  getEventWatches,
  getEventNextWatch,
  verifyEventShouldSendReward,
  verifyEventShouldUseRewardInstantly,
  // ======================================================
  // Mobile Topup
  // ======================================================
  getMobileTopup,
  getTopupMSISDN,
  getSelectedMobileTopupProvider,
  getSelectedMobileTopupValue,
  getSelectedMobileTopupTotalPrice,
  getMobileTopupName,
  getMobileTopupBanner,
  getMobileTopupServiceCode,
  getMobileTopupToService,
  // ======================================================
  // Single Product
  // ======================================================
  getProducts,
  getSingleProduct,
  getSingleProductPrice,
  // ======================================================
  // PromotionSet
  // ======================================================
  getPromotionSet,
  getPromotionSetProducts,
  getPromotionSetPrice,
  getPromotionSetFirstProductPrice,
  getProductToDrop,
  getDropProductTargetRowColumn,
  getDroppedProductSummaryPrice,
  // ======================================================
  // Flag
  // ======================================================
  verifyOrderHasProduct,
  verifyHasDroppedProduct,
  verifyAllOrderDropped,
  verifyOrderHasPromotionSet,
  verifyMobileTopupOrder,
  // ======================================================
  // Payment
  // ======================================================
  getOrderGrandTotalAmount,
  // ======================================================
  // Discount
  // ======================================================
  getDiscounts,
  getDiscount,
  getDiscountAmount,
  verifyOrderHasDiscount
};
<|endoftext|>


<commit_before>const path = require('path');
const paths = require('../paths');
const jsonImporter = require('node-sass-json-importer')

const sassLoader = {
  loader: 'sass-loader',
  options: {
    includePaths: [paths.app.cssBase, 'node_modules'],
    importer: jsonImporter
  }
}

const postcssLoader = {
  loader: 'postcss-loader',
  options: {
    config: {
      path: path.resolve('.config/postcss.config.js')
    }
  }
}

// Note that svg fonts won't be picked up by this loader
const fontLoader = () => ({
  test: /\.(ttf|eot|woff|woff2)$/,
  use: {
    loader: 'file-loader',
    options: {
      name: 'fonts/[name].[ext]'
    }
  }
})

const imageLoader = ({ isProd, assetHash }) => ({
  test: /\.(gif|png|jpe?g|svg)$/i,
  use: [
    {
      loader: 'file-loader',
      options: {
        name: isProd ? '[hash].[ext]' : '[path][name].[ext]',
        outputPath: '/files/',
        publicPath: assetHash + '/files/',
        context: 'frontend'
      }
    },
    {
      loader: 'image-webpack-loader',
      options: {
        disable: true, // disabled in dev mode
        optipng: {
          enabled: false
        },
        pngquant: {
          quality: '90-95'
        }
      }
    }
  ]
})

module.exports = {
  sassLoader: sassLoader,
  postcssLoader: postcssLoader,
  fontLoader: fontLoader,
  imageLoader: imageLoader,
}
<commit_msg>Update webpack config<commit_after>const path = require('path')
const paths = require('../paths')
const jsonImporter = require('node-sass-json-importer')

const sassLoader = {
  loader: 'sass-loader',
  options: {
    sassOptions: {
      includePaths: [paths.app.cssBase, 'node_modules'],
      importer: jsonImporter,
    },
  },
}

const postcssLoader = {
  loader: 'postcss-loader',
  options: {
    postcssOptions: {
      config: path.resolve('.config/postcss.config.js'),
    },
  },
}

// Note that svg fonts won't be picked up by this loader
const fontLoader = () => ({
  test: /\.(ttf|eot|woff|woff2)$/,
  use: {
    loader: 'file-loader',
    options: {
      name: 'fonts/[name].[ext]',
    },
  },
})

const imageLoader = ({ isProd, assetHash }) => ({
  test: /\.(gif|png|jpe?g|svg)$/i,
  use: [
    {
      loader: 'file-loader',
      options: {
        name: isProd ? '[hash].[ext]' : '[path][name].[ext]',
        outputPath: '/files/',
        publicPath: assetHash + '/files/',
        context: 'frontend',
      },
    },
    {
      loader: 'image-webpack-loader',
      options: {
        disable: true, // disabled in dev mode
        optipng: {
          enabled: false,
        },
        pngquant: {
          quality: '90-95',
        },
      },
    },
  ],
})

module.exports = {
  sassLoader: sassLoader,
  postcssLoader: postcssLoader,
  fontLoader: fontLoader,
  imageLoader: imageLoader,
}
<|endoftext|>


<commit_before>// web3.setProvider(new web3.providers.HttpProvider('http://localhost:30303'));
var app = angular.module('listlogs', []);

// Quick utility methods to grab specific HTML elements
var el = function(x) { return document.getElementById(x); }
var qs = function(x) { return document.querySelectorAll(x); }

// Main controller
function ListLogsCtrl($scope, $rootScope, $http) {
    var eth = web3.eth;
    var mainContract = eth.contract(window.accounts.main.abi).at(window.accounts.main.address);
    $scope.mc = mainContract;
    $scope.boundary = 419998;
    $scope.latestBlock = 0;
    web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545'));
    $scope.logFilter = mainContract.Log({}, {fromBlock: $scope.boundary});
    $scope.logs = new filtered_list($scope.logFilter, function() { if (!$scope.$$phase) $scope.$apply(); });
    $scope.logString = "";
    $scope.accounts = eth.accounts;
    $scope.myAccount = "";
    window.mainScope = $scope;
    var onBlock = function(err, block) {
        $scope.boundary = 420001;
        if (!$scope.$$phase) $scope.$apply();
        eth.getBlockNumber(function(err, blockNumber) {
            $scope.boundary = 420002;
            if (!$scope.$$phase) $scope.$apply();
            $scope.latestBlock = blockNumber;
            mainContract.getLatestBreak(function(err, res) {
                $scope.boundary = 420003;
                var res2 = web3.toDecimal(res);
                if (res2 != $scope.boundary) {
                    $scope.boundary = res2;
                    console.log('updating filter', $scope.boundary);
                    $scope.logs.shutdown();
                    $scope.logFilter = mainContract.Log({}, {fromBlock: $scope.boundary});
                    $scope.logs = new filtered_list($scope.logFilter);
                }
                if (!$scope.$$phase) $scope.$apply();
            });
        });
    }
    setInterval(function() { if (!$scope.$$phase) $scope.$apply(); }, 200);
    $scope.boundary = 419999;
    eth.filter('latest', onBlock);
    onBlock();
    $scope.addLog = function() {
        mainContract.addLog($scope.logString, {from: $scope.myAccount}, function(err, result) {
            if (err) { alert(err); return; }
            console.log('sending tx: ', result);
            $scope.logs.addLog({
                transactionHash: result,
                args: { value: $scope.logString }
            })
        });
    }
    $scope.addBreak = function() {
        var x = mainContract.addBreak({from: $scope.myAccount});
        console.log('sending tx: ', x);
    }
}
<commit_msg>updates<commit_after>// web3.setProvider(new web3.providers.HttpProvider('http://localhost:30303'));
var app = angular.module('listlogs', []);

// Quick utility methods to grab specific HTML elements
var el = function(x) { return document.getElementById(x); }
var qs = function(x) { return document.querySelectorAll(x); }

// Main controller
function ListLogsCtrl($scope, $rootScope, $http) {
    var eth = web3.eth;
    var mainContract = eth.contract(window.accounts.main.abi).at(window.accounts.main.address);
    $scope.mc = mainContract;
    $scope.boundary = 419998;
    $scope.latestBlock = 0;
    web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545'));
    $scope.logFilter = mainContract.Log({}, {fromBlock: $scope.boundary});
    $scope.logs = new filtered_list($scope.logFilter, function() { if (!$scope.$$phase) $scope.$apply(); });
    $scope.logString = "";
    $scope.accounts = eth.accounts;
    $scope.myAccount = "";
    window.mainScope = $scope;
    var onBlock = function(err, block) {
        $scope.boundary = 420001;
        if (!$scope.$$phase) $scope.$apply();
        eth.getBlockNumber(function(err, blockNumber) {
            $scope.boundary = 1000000 + blockNumber;
            if (!$scope.$$phase) $scope.$apply();
            $scope.latestBlock = blockNumber;
            mainContract.getLatestBreak(function(err, res) {
                $scope.boundary = 420003;
                var res2 = web3.toDecimal(res);
                if (res2 != $scope.boundary) {
                    $scope.boundary = res2;
                    console.log('updating filter', $scope.boundary);
                    $scope.logs.shutdown();
                    $scope.logFilter = mainContract.Log({}, {fromBlock: $scope.boundary});
                    $scope.logs = new filtered_list($scope.logFilter);
                }
                if (!$scope.$$phase) $scope.$apply();
            });
        });
    }
    setInterval(function() { if (!$scope.$$phase) $scope.$apply(); }, 200);
    $scope.boundary = 419999;
    eth.filter('latest', onBlock);
    onBlock();
    $scope.addLog = function() {
        mainContract.addLog($scope.logString, {from: $scope.myAccount}, function(err, result) {
            if (err) { alert(err); return; }
            console.log('sending tx: ', result);
            $scope.logs.addLog({
                transactionHash: result,
                args: { value: $scope.logString }
            })
        });
    }
    $scope.addBreak = function() {
        var x = mainContract.addBreak({from: $scope.myAccount});
        console.log('sending tx: ', x);
    }
}
<|endoftext|>


<commit_before>define([
  "namespace",

  // Libs
  "use!backbone"

  // Modules

  // Plugins
],

function(namespace, Backbone) {
	/*
	 * This module defines the API properties.
	 */
    var app = namespace.app;

  	// Create a new module
  	var Leaguevine = namespace.module();

  	Leaguevine.Router = Backbone.Router.extend({

		routes: {
			"access_:hash": "token_received"
		},

		token_received: function(hash) {//route matched by oauth/:hash
			hash = hash.split("&"); //break the URL hash into its segments.
			_.each(hash, function(element){ //For each segment...
				var pair = element.split("="); //Get the key and value.
				var temp_obj = {};
				temp_obj[pair[0]]=pair[1]; //Put the key and value into a temp object.
				_.extend(app.api,temp_obj); //Extend/overwrite our app.api with the key/value of the temp object.
			});
			localStorage.setItem('auth_object', JSON.stringify(app.api));
			//TODO: After token is received, navigate to the href saved below.
			Backbone.history.navigate('teams', true);//After the token has been updated, navigate to some index site.
		}
	});
    Leaguevine.router = new Leaguevine.Router();// INITIALIZE ROUTER

  	Leaguevine.API = {
        root: "http://api.playwithlv.com/v1/",
        base: "http://playwithlv.com/oauth2/authorize/?response_type=token&scope=universal",
        client_id: "5b830cb7c788b095c94732c8ca03cb",
        redirect_uri: "http://localhost:8000/",
        season_id: 20041,
        d_token: function() {//Modules will reference this dynamic token
            if (!this.token) {
                var stored_api = JSON.parse(localStorage.getItem('auth_object')); //Pull our token out of local storage if it exists.
                _.extend(this,stored_api);
            }
            if (!this.token) {
                //TODO: Save the href.
                this.login();
            }
            else {
                return this.token;
            }
        },
        is_logged_in: function() {//Returns true if the user is logged in and false if not
            return (localStorage.getItem('auth_object') != null)
        },
        login: function() {//Redirects a user to the login screen
            window.location.href = this.base + "&client_id=" + this.client_id + "&redirect_uri=" + this.redirect_uri;
            return false;
        },
        logout: function() {//Logs a user out by removing the locally stored token
            localStorage.removeItem('auth_object');
            this.token = undefined;
        },
    };

    if (typeof localSettings != 'undefined' &&
        typeof localSettings.Leaguevine != 'undefined' &&
        typeof localSettings.Leaguevine.API != 'undefined') {
        _.extend(Leaguevine.API, localSettings.Leaguevine.API);
    }

	return Leaguevine;
});
<commit_msg>Added a redirect after login. Closes #27<commit_after>define([
  "namespace",

  // Libs
  "use!backbone"

  // Modules

  // Plugins
],

function(namespace, Backbone) {
	/*
	 * This module defines the API properties.
	 */
    var app = namespace.app;

  	// Create a new module
  	var Leaguevine = namespace.module();

  	Leaguevine.Router = Backbone.Router.extend({

		routes: {
			"access_:hash": "token_received"
		},

		token_received: function(hash) {//route matched by oauth/:hash
			hash = hash.split("&"); //break the URL hash into its segments.
			_.each(hash, function(element){ //For each segment...
				var pair = element.split("="); //Get the key and value.
				var temp_obj = {};
				temp_obj[pair[0]]=pair[1]; //Put the key and value into a temp object.
				_.extend(app.api,temp_obj); //Extend/overwrite our app.api with the key/value of the temp object.
			});

			//After token is received, navigate to the href that was saved earlier
			localStorage.setItem('auth_object', JSON.stringify(app.api));
            window.location.href = '#' + localStorage.getItem('login_redirect');
            return false;
		}
	});
    Leaguevine.router = new Leaguevine.Router();// INITIALIZE ROUTER

  	Leaguevine.API = {
        root: "http://api.playwithlv.com/v1/",
        base: "http://playwithlv.com/oauth2/authorize/?response_type=token&scope=universal",
        client_id: "5b830cb7c788b095c94732c8ca03cb",
        redirect_uri: "http://localhost:8000/",
        season_id: 20041,
        d_token: function() {//Modules will reference this dynamic token
            if (!this.token) {
                var stored_api = JSON.parse(localStorage.getItem('auth_object')); //Pull our token out of local storage if it exists.
                _.extend(this,stored_api);
            }
            if (!this.token) {
                this.login();
            }
            else {
                return this.token;
            }
        },
        is_logged_in: function() {//Returns true if the user is logged in and false if not
            return (localStorage.getItem('auth_object') != null)
        },
        login: function() {//Redirects a user to the login screen
            localStorage.setItem('login_redirect', Backbone.history.fragment);
            window.location.href = this.base + "&client_id=" + this.client_id + "&redirect_uri=" + this.redirect_uri;
            return false;
        },
        logout: function() {//Logs a user out by removing the locally stored token
            localStorage.removeItem('auth_object');
            this.token = undefined;
        },
    };

    if (typeof localSettings != 'undefined' &&
        typeof localSettings.Leaguevine != 'undefined' &&
        typeof localSettings.Leaguevine.API != 'undefined') {
        _.extend(Leaguevine.API, localSettings.Leaguevine.API);
    }

	return Leaguevine;
});
<|endoftext|>


<commit_before>const fs = require('fs-extra');
const csv = require('fast-csv');
const dateFormat = require('dateformat');
const path = require('path');
const eol = require('os').EOL;
const sanitize = require('sanitize-filename');

module.exports = {
  defaultConfig: {
    enabled: false,
    logWipes: false
  },
  defaultConfigDetails: {
    logWipes: { label: 'Log Wipes' }
  },
  pluginName: 'RunLogger',
  pluginDescription: 'Creates a local csv file and saves data of every dungeon and scenario run in there.',
  temp: {},
  init(proxy, config) {
    proxy.on('apiCommand', (req, resp) => {
      if (config.Config.Plugins[this.pluginName].enabled) {
        const { command, wizard_id } = req;

        if (!this.temp[wizard_id])
          this.temp[wizard_id] = {};

        if (command === 'BattleScenarioStart')
          this.temp[wizard_id].stage = gMapping.scenario[req.region_id] ? `${gMapping.scenario[req.region_id]} ${gMapping.difficulty[req.difficulty]} - ${req.stage_no}` : 'Unknown';

        if (command === 'BattleScenarioResult' || command === 'BattleDungeonResult')
          this.log(proxy, req, resp);
      }
    });
  },
  getItem(crate) {
    if (crate.random_scroll && crate.random_scroll.item_master_id === 1)
      return `Unknown Scroll x${crate.random_scroll.item_quantity}`;
    if (crate.random_scroll && crate.random_scroll.item_master_id === 8)
      return `Summoning Stones x${crate.random_scroll.item_quantity}`;
    if (crate.random_scroll && crate.random_scroll.item_master_id === 2)
      return 'Mystical Scroll';
    if (crate.costume_point)
      return `Shapeshifting Stone x${crate.costume_point}`;
    if (crate.rune_upgrade_stone)
      return `Power Stone x${crate.rune_upgrade_stone.item_quantity}`;
    if (crate.unit_info)
      return `${gMapping.getMonsterName(crate.unit_info.unit_master_id)} ${crate.unit_info.class}`;
    if (crate.material) {
      let id = crate.material.item_master_id.toString();
      let attribute = Number(id.slice(-1));
      let grade = Number(id.slice(1, -3));
      return `Essence of ${gMapping.essence.attribute[attribute]}(${gMapping.essence.grade[grade]}) x${crate.material.item_quantity}`;
    }
    if (crate.craft_stuff && gMapping.craftMaterial[crate.craft_stuff.item_master_id])
      return `${gMapping.craftMaterial[crate.craft_stuff.item_master_id]} x${crate.craft_stuff.item_quantity}`;
    if (crate.summon_pieces)
      return `Summoning Piece ${gMapping.getMonsterName(crate.summon_pieces.item_master_id)} x${crate.summon_pieces.item_quantity}`;

    return 'Unknown Drop';
  },
  log(proxy ,req, resp) {
    const { command } = req;
    const { wizard_id, wizard_name } = resp.wizard_info;

    let entry = {};

    if (command === 'BattleDungeonResult') {
      if (gMapping.dungeon[req.dungeon_id]) {
        entry.dungeon = `${gMapping.dungeon[req.dungeon_id]} B${req.stage_id}`;
      } else {
        entry.dungeon = req.dungeon_id > 10000 ? 'Hall of Heroes' : 'Unknown';
      }
    }

    if (command === 'BattleScenarioResult')
      entry.dungeon = this.temp[wizard_id].stage ? this.temp[wizard_id].stage : 'Unknown';

    let winLost = resp.win_lose == 1 ? 'Win' : 'Lost';
    if (winLost === 'Lost' && !config.Config.Plugins[this.pluginName].logWipes)
      return;

    entry.date = dateFormat(new Date(), 'yyyy-mm-dd HH:MM');
    entry.result = winLost;

    let reward = resp.reward ? resp.reward : {};
    entry.mana = reward.mana ? reward.mana : 0;
    entry.energy = reward.energy ? reward.energy : 0;
    entry.crystal = reward.crystal ? reward.crystal : 0;

    let seconds = Math.floor(resp.clear_time.current_time / 1000 % 60) < 10 ? '0' + Math.floor(resp.clear_time.current_time / 1000 % 60) : Math.floor(resp.clear_time.current_time / 1000 % 60);
    let time = [Math.floor(resp.clear_time.current_time / 1000 / 60), seconds];
    entry.time = `${time[0]}:${time[1]}`;

    if (reward.crate) {
      entry.mana = reward.crate.mana ? entry.mana + reward.crate.mana : entry.mana;
      entry.energy = reward.crate.energy ? entry.energy + reward.crate.energy : entry.energy;
      entry.crystal = reward.crate.crystal ? entry.crystal + reward.crate.crystal : entry.crystal;

      if (reward.crate.rune) {
        let rune = reward.crate.rune;
        entry.drop = 'Rune';
        entry.grade = `${rune.class}*`;
        entry.sell_value = rune.sell_value;
        entry.set = gMapping.rune.sets[rune.set_id];
        entry.slot = rune.slot_no;
        entry.efficiency = gMapping.getRuneEfficiency(rune).current;
        entry.rarity = gMapping.rune.class[rune.sec_eff.length];
        entry.main_stat = gMapping.getRuneEffect(rune.pri_eff);
        entry.prefix_stat = gMapping.getRuneEffect(rune.prefix_eff);

        rune.sec_eff.forEach((substat, i) => {
          entry['sub' + (i + 1)] = gMapping.getRuneEffect(substat);
        });
      } else {
        entry.drop = this.getItem(reward.crate);
      }
    }

    if (resp.unit_list && resp.unit_list.length > 0) {
      resp.unit_list.forEach((unit, i) => {
        entry['team' + (i + 1)] = gMapping.getMonsterName(unit.unit_master_id);
      });
    }

    if (resp.instance_info)
      entry.drop = 'Secret Dungeon';

    let csvData = [];
    const headers = ['date', 'dungeon', 'result', 'time', 'mana', 'crystal', 'energy', 'drop', 'grade', 'sell_value',
      'set', 'efficiency', 'slot', 'rarity', 'main_stat', 'prefix_stat', 'sub1', 'sub2', 'sub3', 'sub4', 'team1', 'team2', 'team3', 'team4', 'team5'];

    const filename = sanitize(`${wizard_name}-${wizard_id}-runs.csv`);
    const self = this;

    fs.ensureFile(path.join(config.Config.App.filesPath, filename), err => {
      csv.fromPath(path.join(config.Config.App.filesPath, filename), { ignoreEmpty: true, headers: headers, renameHeaders: true }).on('data', function (data) {
        csvData.push(data);
      }).on('end', function () {
        csvData.push(entry);
        csv.writeToPath(path.join(config.Config.App.filesPath, filename), csvData, { headers: headers }).on("finish", function () {
          proxy.log({ type: 'success', source: 'plugin', name: self.pluginName, message: `Saved run data to ${filename}` });
        });
      });
    })

  }
}
<commit_msg>Bump version Small changes<commit_after>const fs = require('fs-extra');
const csv = require('fast-csv');
const dateFormat = require('dateformat');
const path = require('path');
const sanitize = require('sanitize-filename');

module.exports = {
  defaultConfig: {
    enabled: false,
    logWipes: false
  },
  defaultConfigDetails: {
    logWipes: { label: 'Log Wipes' }
  },
  pluginName: 'RunLogger',
  pluginDescription: 'Creates a local csv file and saves data of every dungeon and scenario run in there.',
  temp: {},
  init(proxy, config) {
    proxy.on('apiCommand', (req, resp) => {
      if (config.Config.Plugins[this.pluginName].enabled) {
        const { command, wizard_id } = req;

        if (!this.temp[wizard_id])
          this.temp[wizard_id] = {};

        if (command === 'BattleScenarioStart')
          this.temp[wizard_id].stage = gMapping.scenario[req.region_id] ? `${gMapping.scenario[req.region_id]} ${gMapping.difficulty[req.difficulty]} - ${req.stage_no}` : 'Unknown';

        if (command === 'BattleScenarioResult' || command === 'BattleDungeonResult')
          this.log(proxy, req, resp);
      }
    });
  },
  getItem(crate) {
    if (crate.random_scroll && crate.random_scroll.item_master_id === 1)
      return `Unknown Scroll x${crate.random_scroll.item_quantity}`;
    if (crate.random_scroll && crate.random_scroll.item_master_id === 8)
      return `Summoning Stones x${crate.random_scroll.item_quantity}`;
    if (crate.random_scroll && crate.random_scroll.item_master_id === 2)
      return 'Mystical Scroll';
    if (crate.costume_point)
      return `Shapeshifting Stone x${crate.costume_point}`;
    if (crate.rune_upgrade_stone)
      return `Power Stone x${crate.rune_upgrade_stone.item_quantity}`;
    if (crate.unit_info)
      return `${gMapping.getMonsterName(crate.unit_info.unit_master_id)} ${crate.unit_info.class}`;
    if (crate.material) {
      let id = crate.material.item_master_id.toString();
      let attribute = Number(id.slice(-1));
      let grade = Number(id.slice(1, -3));
      return `Essence of ${gMapping.essence.attribute[attribute]}(${gMapping.essence.grade[grade]}) x${crate.material.item_quantity}`;
    }
    if (crate.craft_stuff && gMapping.craftMaterial[crate.craft_stuff.item_master_id])
      return `${gMapping.craftMaterial[crate.craft_stuff.item_master_id]} x${crate.craft_stuff.item_quantity}`;
    if (crate.summon_pieces)
      return `Summoning Piece ${gMapping.getMonsterName(crate.summon_pieces.item_master_id)} x${crate.summon_pieces.item_quantity}`;

    return 'Unknown Drop';
  },
  log(proxy ,req, resp) {
    const { command } = req;
    const { wizard_id, wizard_name } = resp.wizard_info;

    let entry = {};

    if (command === 'BattleDungeonResult') {
      if (gMapping.dungeon[req.dungeon_id]) {
        entry.dungeon = `${gMapping.dungeon[req.dungeon_id]} B${req.stage_id}`;
      } else {
        entry.dungeon = req.dungeon_id > 10000 ? 'Hall of Heroes' : 'Unknown';
      }
    }

    if (command === 'BattleScenarioResult')
      entry.dungeon = this.temp[wizard_id].stage ? this.temp[wizard_id].stage : 'Unknown';

    let winLost = resp.win_lose == 1 ? 'Win' : 'Lost';
    if (winLost === 'Lost' && !config.Config.Plugins[this.pluginName].logWipes)
      return;

    entry.date = dateFormat(new Date(), 'yyyy-mm-dd HH:MM');
    entry.result = winLost;

    let reward = resp.reward ? resp.reward : {};
    entry.mana = reward.mana ? reward.mana : 0;
    entry.energy = reward.energy ? reward.energy : 0;
    entry.crystal = reward.crystal ? reward.crystal : 0;

    let seconds = Math.floor(resp.clear_time.current_time / 1000 % 60) < 10 ? '0' + Math.floor(resp.clear_time.current_time / 1000 % 60) : Math.floor(resp.clear_time.current_time / 1000 % 60);
    let time = [Math.floor(resp.clear_time.current_time / 1000 / 60), seconds];
    entry.time = `${time[0]}:${time[1]}`;

    if (reward.crate) {
      entry.mana = reward.crate.mana ? entry.mana + reward.crate.mana : entry.mana;
      entry.energy = reward.crate.energy ? entry.energy + reward.crate.energy : entry.energy;
      entry.crystal = reward.crate.crystal ? entry.crystal + reward.crate.crystal : entry.crystal;

      if (reward.crate.rune) {
        let rune = reward.crate.rune;
        entry.drop = 'Rune';
        entry.grade = `${rune.class}*`;
        entry.sell_value = rune.sell_value;
        entry.set = gMapping.rune.sets[rune.set_id];
        entry.slot = rune.slot_no;
        entry.efficiency = gMapping.getRuneEfficiency(rune).current;
        entry.rarity = gMapping.rune.class[rune.sec_eff.length];
        entry.main_stat = gMapping.getRuneEffect(rune.pri_eff);
        entry.prefix_stat = gMapping.getRuneEffect(rune.prefix_eff);

        rune.sec_eff.forEach((substat, i) => {
          entry['sub' + (i + 1)] = gMapping.getRuneEffect(substat);
        });
      } else {
        entry.drop = this.getItem(reward.crate);
      }
    }

    if (resp.unit_list && resp.unit_list.length > 0) {
      resp.unit_list.forEach((unit, i) => {
        entry['team' + (i + 1)] = gMapping.getMonsterName(unit.unit_master_id);
      });
    }

    if (resp.instance_info)
      entry.drop = 'Secret Dungeon';

    let csvData = [];
    const headers = ['date', 'dungeon', 'result', 'time', 'mana', 'crystal', 'energy', 'drop', 'grade', 'sell_value',
      'set', 'efficiency', 'slot', 'rarity', 'main_stat', 'prefix_stat', 'sub1', 'sub2', 'sub3', 'sub4', 'team1', 'team2', 'team3', 'team4', 'team5'];

    const filename = sanitize(`${wizard_name}-${wizard_id}-runs.csv`);
    const self = this;

    fs.ensureFile(path.join(config.Config.App.filesPath, filename), err => {
      csv.fromPath(path.join(config.Config.App.filesPath, filename), { ignoreEmpty: true, headers: headers, renameHeaders: true }).on('data', function (data) {
        csvData.push(data);
      }).on('end', function () {
        csvData.push(entry);
        csv.writeToPath(path.join(config.Config.App.filesPath, filename), csvData, { headers: headers }).on("finish", function () {
          proxy.log({ type: 'success', source: 'plugin', name: self.pluginName, message: `Saved run data to ${filename}` });
        });
      });
    })

  }
}
<|endoftext|>