<commit_before>"use strict";
var Blob = function (x, y, radius) {
  this.x = x;
  this.y = y;
  this.radius = radius || 0.33;
}

Blob.prototype.hasHit = function ( checkX, checkY ) {
  // Distance between blob center and graph coordinate
  var pointDistance =
    Math.sqrt( Math.pow(checkX - this.x, 2) + Math.pow(checkY - this.y, 2) );

  return (pointDistance < this.radius);
};

var GameState = function (windowObj) {
  this._blobs = [];
  this.setWindow(windowObj);
};

GameState.prototype.createBlobs = function (coordinateList) {
  if (this._blobs.length > 0) throw "Blobs are already created.";
  if ( !(coordinateList instanceof Array) )
    throw "coordinateList must be array.";
  if (coordinateList.length === 0) throw "coordinateList must not be empty.";

  coordinateList.forEach(function(coordinate){
    // x, y in nested array
    this._blobs.push(new Blob(coordinate[0], coordinate[1]));
  }.bind(this));
};

GameState.prototype.destroyBlobs = function () {
  this._blobs = [];
};

GameState.prototype.getBlobs = function () {
  return this._blobs;
};

GameState.prototype.createRandomBlobs = function (blobsToCreate) {
  if (typeof blobsToCreate !== "number")
    throw "Number of blobs must be integer";

  if (blobsToCreate < 1) throw "Number of blobs must be non-zero";

  var coordinates = [];
  for (var i = 0; i < blobsToCreate; i++) {
    coordinates.push(
      [
        Math.random() *
        (
          this._graphWindow.maxX -
          this._graphWindow.minX
        ) + this._graphWindow.minX,
        Math.random() *
        (
          this._graphWindow.maxY -
          this._graphWindow.minY
        ) + this._graphWindow.minY,
      ]);
  }

  this.createBlobs(coordinates);
};

GameState.prototype.setWindow = function (windowObj) {
  var allNums;
  for(var name in windowObj){
    allNums = typeof windowObj[name] === "number";
    allNums = allNums && ["minX", "maxX", "minY", "maxY"].includes(name);
    if(!allNums) break;
  }

  if (!allNums)
    throw "Not correct properties on window object." +
    " Check types and that you have minX, maxX, minY, maxY.";

  if ((windowObj.minX >= windowObj.maxX) && (windowObj.minY >= windowObj.maxY))
    throw "minX must be less than maxX and minY must be less than maxY";
  if (windowObj.minX >= windowObj.maxX) throw "minX must be less than maxX";
  if (windowObj.minY >= windowObj.maxY) throw "minY must be less than maxY";

  this._graphWindow = windowObj;
};

var Graph = function (expression, xResolution, yResolution) {
  this._compileExpression(expression);
  this.xResolution = xResolution;
  this.yResolution = yResolution;
};

Graph.prototype._compileExpression =
function (expression) {
  // TODO: precompile expression for easy rendering.
  console.error("compileExpression() is not yet implemented");
};

Graph.prototype.hasPoint = function (x, y) {
  //dx is width of domain to check for point
  //dy is height of range to check for point
  if (typeof x === "object") {
    y = x.y; //Use y component of object as y
    x = x.x; //Use x component of object as x
  }
  //TODO: Implement evaluation for any equation.
  //console.error("hasPoint() not yet implemented.");
  var atLeastMinimum = (
    Math.pow(5, 2) >=
    Math.pow((x)- 3, 2) +
    Math.pow((y) + 3, 2)
  );
  var atMostMaximum = (
    Math.pow(5 - (this.xResolution + this.yResolution),2) <=
    Math.pow( (x) - 3, 2) +
    Math.pow( (y) + 3, 2)
  );
  /*var atLeastMinimum = (
    y >= -Math.pow(x, 2)
  );
  var atMostMaximum = (
    y - (this.xResolution + this.yResolution) <= -Math.pow(x, 2)
  );*/
  return  atLeastMinimum && atMostMaximum;
};

var Equation = function Equation(equationString) {
  if (typeof equationString !== "string")
    throw "Equation necessary for processing.";
  this._parseEquation(equationString);
  this._parseExpressions();

};

Equation.prototype._parseExpressions = function () {
  this.parsedExpressions = [];
  this.expressions.forEach(function (expression) {

  })
};

Equation.prototype._parseEquation = function (equationString) {
  equationString = equationString.toLowerCase();

  if (equationString.indexOf("x") == -1 || equationString.indexOf("y") == -1)
    throw "Equation must relate x and y."

  this.comparisonOperators = { "=" : [], "<": [], ">": [], "<=": [], ">=": []};
  //Dynamically add keys to the RegExp for matching.
  var comparisonOperatorsRegExp = new RegExp(
    //Sort comparison operators by length, then join them to match longest first
    Object.keys(this.comparisonOperators).sort(
      function compare(a, b){
        return Math.sign(b.length - a.length);
      }
    ).join("|")
  );
  var searchString = equationString;
  this.expressions = [];

  var lastMatchedLocation = -1;
  //While there is a comparison happening
  while ( (comparisonOperatorsRegExp).test(searchString) ) {
    //Grab the matched operator.
    var matchedOperator = searchString.match(comparisonOperatorsRegExp);
    //Add it's location in the string to the object, plus
    //the location of the current string in the general equation string
    //plus one because length is 1 based, while indices are 0 based.
    this.comparisonOperators[matchedOperator[0]].
    push(matchedOperator.index + lastMatchedLocation + 1);
    lastMatchedLocation = matchedOperator.index;
    //add the expression to the list of expressions to evaluate
    this.expressions.push(
      searchString.substring(0, matchedOperator.index).trim()
    );
    //reevaluate only the new part of the string
    searchString = searchString.substring(
      matchedOperator.index + matchedOperator[0].length
    );
  }
  //Push the last expression that has no comparisonOperators into expressions
  this.expressions.push(searchString.trim());

  //Make sure there's at least one comparison AND no expressions are blank
  if ( this.expressions.length < 2 ||
    this.expressions.reduce(
      function (accumulator, arrayValue) {
        //checks if previous string is empty or if current one is empty.
        return accumulator || (arrayValue.length == 0);
      },
      false
    )
  ) throw "Equation must pose either an equality or inequality";
};

var Expression = function Expression(expressionString) {
  if (typeof expressionString !== "string") throw "Expression must be specified";

  if (expressionString.trim() === "") {
    this.entryPoint = function(){return 0;}
    return;
  }

  this._compiledExpression = [];

  this._compiledUnaryExpressions = [];

  this.orderOfBinaryOperations = {
    "^": function exponent(a, b) {
      return Math.pow(a, b);
    },
    "*": function multiplication(a, b) {
      return b * a;
    },
    "/": function division(a, b) {
      return b / a;
    },
    "+": function addition(a, b) {
      return b + a;
    },
    "-": function subtraction(a, b) {
      return b - a;
    }
  };

  this.orderOfUnaryOperations = {
    "(": function parentheses() {
      throw "Parentheses not implemented";
    },
    "+": function (a) {
      return +a;
    },
    "-": function (a) {
      return -a;
    },
    "sin": function sine(a) {
      return Math.sin(a);
    },
    "cos": function cosine(a) {
      return Math.cos(a);
    }
  }

  //remove single pair of parens if they are on the ends and end matches beginning as they don't matter.
  expressionString = expressionString.trim();
  if (/^\(.*\)$/.test(expressionString)) {
    var leftUnmatched = 0; //error if goes below 0
    var endIndex = [];
    //Only two scenarios (()) and ()() to disambiguate bc recursion takes care of rest
    expressionString.split("").forEach(function (char, index) {
      if (char === "(") leftUnmatched++;
      if (char === ")") leftUnmatched--;
      if (leftUnmatched === 0) endIndex.push(index);
    })
    //get the first completed closure of () after beginning
    if (endIndex[0] === expressionString.length - 1)
    expressionString = expressionString.substring(1, expressionString.length - 1);
  }

  //Base case for recursion: if there are no operations being applied to string,
  //return the number in a function that returns that number
  // or letter in a function that takes a value for that variable as a parameter

if (
    Object.keys(this.orderOfUnaryOperations).reduce(
      function (collector, item) {
        return collector && (expressionString.indexOf(item) === -1);
      },
      true
    ) &&
  Object.keys(this.orderOfBinaryOperations).reduce(
    function (collector, item) {
      return collector && (expressionString.indexOf(item) === -1);
    },
    true
  )
) {
  expressionString = expressionString.trim();
  if (/[A-z]/.test(expressionString)){
    this.entryPoint = function (variablesObj) {
      return variablesObj[expressionString];
    }
  } else {
    this.entryPoint = function () {
      return parseFloat(expressionString);
    }
  }
  return;
}
  //Split so that right, ex the minus is evaluated first 2x + 3 - 2
  //That way when we break it apart the first term is evaluated first
//  var indexOfSymbol = -1; //Keep scope here so I can check if symbol is found.
  var tempExpressionString = expressionString; //for processing string only
  var isUnary = function (symbol, expressionString) {
    var regions = expressionString.split(symbol);
    //Regions will be <2 only if it's not found, so it's not unary.
    if (regions.length < 2) return false;
    //get one before last one
    var testStr = regions[regions.length - 2].trim();
    return testStr === "" || /[^A-z0-9()]$/.test(expressionString);
  };

  var isInParens = function (indexOfLocation, expressionString) {
    var openParensBefore = 0;
    var openParensAfter = 0;
    var before = expressionString.substring(0, indexOfLocation - 1);
    var after = expressionString.substring(indexOfLocation + 1);
    before.split("").forEach(function (letter) {
      if (letter === "(") ++openParensBefore;
      if (letter === ")") --openParensBefore;
    });
    after.split("").forEach(function (letter) {
      if (letter === "(") ++openParensAfter;
      if (letter === ")") --openParensAfter;
    });

    return !(openParensBefore === 0 && openParensAfter === 0);
  }

  this.entryPoint = null; //will hold first function to call in stack.
  // Do binary after unary
  Object.keys(this.orderOfUnaryOperations).
  concat(Object.keys(this.orderOfBinaryOperations)).
  reverse().forEach(function (symbol) {
  var indexOfSymbol = expressionString.lastIndexOf(symbol);
  //Don't eval any symbols in parens, the parens op. will do that!

  if (indexOfSymbol > -1)
  if (isInParens(indexOfSymbol, expressionString)) return;
    if (isUnary(symbol, expressionString)) {
      if (/\(/.test(symbol)){
        this.entryPoint = function (variablesObj) {
          return (new Expression(
            expressionString.substring(
              expressionString.indexOf("(") + 1,
              expressionString.indexOf(")")
            )).evaluate(variablesObj)) +
            (new Expression(
              expressionString.substring(
                expressionString.indexOf(")") + 1
              )
            ).evaluate(variablesObj));
        }
      } else {
        this.entryPoint = function (variablesObj) {
          return this.orderOfUnaryOperations[symbol](
            (new Expression(
            expressionString.substring(indexOfSymbol + symbol.length)
          )).evaluate(variablesObj));
        };
      }
    } else {
      this.entryPoint = function(variablesObj) {
        return this.orderOfBinaryOperations[symbol](
          (new Expression(
            expressionString.substring(0, indexOfSymbol)
          )).evaluate(variablesObj),
          (new Expression(
            expressionString.substring(indexOfSymbol + symbol.length)
          )).evaluate(variablesObj)
        );
      };
    }
    return;
  }.bind(this));

  // console.log(this.entryPoint);

  /*while (indexOfSymbol === -1){
    indexOfSymbol = -1;

    var isInParens = function (indexOfLocation, expressionString) {
      return indexOfLocation > expressionString.indexOf("(") &&
        indexOfLocation < expressionString.lastIndexOf(")");
    }
    // Do binary after unary
    Object.keys(this.orderOfBinaryOperations).
    concat(Object.keys(this.orderOfUnaryOperations)).
    reverse().forEach(function (symbol) {

      //detect if is truly a unary symbol by encountering either
      //the string boundary or a non-letter or non-number on the left
      //and it not being a space
      this.unaryCount = 0;
      var currentIsUnary = isUnary(symbol, expressionString);
      //Don't execute of symbol is already found
      if (indexOfSymbol > -1) return;
      indexOfSymbol = tempExpressionString.lastIndexOf(symbol);
      //Symbol will be evaluated in nested expression, so not now
      if (isInParens(indexOfSymbol, expressionString)) {
        indexOfSymbol = -1;
        return;
      }

      if (currentIsUnary){
        if (indexOfSymbol > -1) { //symbol has to exist
          if (symbol === "(") {
            var indexOfEndParens = tempExpressionString.lastIndexOf(")");
            this._compiledExpression.concat(
              new Expression(
                tempExpressionString.substring(
                  indexOfSymbol + symbol.length,
                  indexOfEndParens
                )
              )._compiledExpression // Just evaluate stuff inside of parentheses
            );
            tempExpressionString = tempExpressionString.substring(indexOfSymbol);
          } else {
            //Increment unary count and push the value as a symbol.
            this._compiledExpression.push("u" + ++this.unaryCount);
            afterText = tempExpressionString.
            split(symbol).pop().
            match(/[A-z0-9]+/)[0];

            this._compiledUnaryExpressions.push(new Expression(afterText));
          }
        }
      } else {
        if (indexOfSymbol > -1) { //symbol has to exist
          this._compiledExpression.push(symbol);
          this._compiledExpression.concat(
            new Expression(
              tempExpressionString.substring(indexOfSymbol + symbol.length)
            )._compiledExpression
          );
          tempExpressionString = tempExpressionString.substring(indexOfSymbol);
        }
      }

    }.bind(this));
  }*/

}

Expression.prototype.evaluate = function (variablesObj) {
  return this.entryPoint(variablesObj);
};
<commit_msg>Scoping problem corrected to allow closure to keep value.<commit_after>"use strict";
var Blob = function (x, y, radius) {
  this.x = x;
  this.y = y;
  this.radius = radius || 0.33;
}

Blob.prototype.hasHit = function ( checkX, checkY ) {
  // Distance between blob center and graph coordinate
  var pointDistance =
    Math.sqrt( Math.pow(checkX - this.x, 2) + Math.pow(checkY - this.y, 2) );

  return (pointDistance < this.radius);
};

var GameState = function (windowObj) {
  this._blobs = [];
  this.setWindow(windowObj);
};

GameState.prototype.createBlobs = function (coordinateList) {
  if (this._blobs.length > 0) throw "Blobs are already created.";
  if ( !(coordinateList instanceof Array) )
    throw "coordinateList must be array.";
  if (coordinateList.length === 0) throw "coordinateList must not be empty.";

  coordinateList.forEach(function(coordinate){
    // x, y in nested array
    this._blobs.push(new Blob(coordinate[0], coordinate[1]));
  }.bind(this));
};

GameState.prototype.destroyBlobs = function () {
  this._blobs = [];
};

GameState.prototype.getBlobs = function () {
  return this._blobs;
};

GameState.prototype.createRandomBlobs = function (blobsToCreate) {
  if (typeof blobsToCreate !== "number")
    throw "Number of blobs must be integer";

  if (blobsToCreate < 1) throw "Number of blobs must be non-zero";

  var coordinates = [];
  for (var i = 0; i < blobsToCreate; i++) {
    coordinates.push(
      [
        Math.random() *
        (
          this._graphWindow.maxX -
          this._graphWindow.minX
        ) + this._graphWindow.minX,
        Math.random() *
        (
          this._graphWindow.maxY -
          this._graphWindow.minY
        ) + this._graphWindow.minY,
      ]);
  }

  this.createBlobs(coordinates);
};

GameState.prototype.setWindow = function (windowObj) {
  var allNums;
  for(var name in windowObj){
    allNums = typeof windowObj[name] === "number";
    allNums = allNums && ["minX", "maxX", "minY", "maxY"].includes(name);
    if(!allNums) break;
  }

  if (!allNums)
    throw "Not correct properties on window object." +
    " Check types and that you have minX, maxX, minY, maxY.";

  if ((windowObj.minX >= windowObj.maxX) && (windowObj.minY >= windowObj.maxY))
    throw "minX must be less than maxX and minY must be less than maxY";
  if (windowObj.minX >= windowObj.maxX) throw "minX must be less than maxX";
  if (windowObj.minY >= windowObj.maxY) throw "minY must be less than maxY";

  this._graphWindow = windowObj;
};

var Graph = function (expression, xResolution, yResolution) {
  this._compileExpression(expression);
  this.xResolution = xResolution;
  this.yResolution = yResolution;
};

Graph.prototype._compileExpression =
function (expression) {
  // TODO: precompile expression for easy rendering.
  console.error("compileExpression() is not yet implemented");
};

Graph.prototype.hasPoint = function (x, y) {
  //dx is width of domain to check for point
  //dy is height of range to check for point
  if (typeof x === "object") {
    y = x.y; //Use y component of object as y
    x = x.x; //Use x component of object as x
  }
  //TODO: Implement evaluation for any equation.
  //console.error("hasPoint() not yet implemented.");
  var atLeastMinimum = (
    Math.pow(5, 2) >=
    Math.pow((x)- 3, 2) +
    Math.pow((y) + 3, 2)
  );
  var atMostMaximum = (
    Math.pow(5 - (this.xResolution + this.yResolution),2) <=
    Math.pow( (x) - 3, 2) +
    Math.pow( (y) + 3, 2)
  );
  /*var atLeastMinimum = (
    y >= -Math.pow(x, 2)
  );
  var atMostMaximum = (
    y - (this.xResolution + this.yResolution) <= -Math.pow(x, 2)
  );*/
  return  atLeastMinimum && atMostMaximum;
};

var Equation = function Equation(equationString) {
  if (typeof equationString !== "string")
    throw "Equation necessary for processing.";
  this._parseEquation(equationString);
  this._parseExpressions();

};

Equation.prototype._parseExpressions = function () {
  this.parsedExpressions = [];
  this.expressions.forEach(function (expression) {

  })
};

Equation.prototype._parseEquation = function (equationString) {
  equationString = equationString.toLowerCase();

  if (equationString.indexOf("x") == -1 || equationString.indexOf("y") == -1)
    throw "Equation must relate x and y."

  this.comparisonOperators = { "=" : [], "<": [], ">": [], "<=": [], ">=": []};
  //Dynamically add keys to the RegExp for matching.
  var comparisonOperatorsRegExp = new RegExp(
    //Sort comparison operators by length, then join them to match longest first
    Object.keys(this.comparisonOperators).sort(
      function compare(a, b){
        return Math.sign(b.length - a.length);
      }
    ).join("|")
  );
  var searchString = equationString;
  this.expressions = [];

  var lastMatchedLocation = -1;
  //While there is a comparison happeningi
  while ( (comparisonOperatorsRegExp).test(searchString) ) {
    //Grab the matched operator.
    var matchedOperator = searchString.match(comparisonOperatorsRegExp);
    //Add it's location in the string to the object, plus
    //the location of the current string in the general equation string
    //plus one because length is 1 based, while indices are 0 based.
    this.comparisonOperators[matchedOperator[0]].
    push(matchedOperator.index + lastMatchedLocation + 1);
    lastMatchedLocation = matchedOperator.index;
    //add the expression to the list of expressions to evaluate
    this.expressions.push(
      searchString.substring(0, matchedOperator.index).trim()
    );
    //reevaluate only the new part of the string
    searchString = searchString.substring(
      matchedOperator.index + matchedOperator[0].length
    );
  }
  //Push the last expression that has no comparisonOperators into expressions
  this.expressions.push(searchString.trim());

  //Make sure there's at least one comparison AND no expressions are blank
  if ( this.expressions.length < 2 ||
    this.expressions.reduce(
      function (accumulator, arrayValue) {
        //checks if previous string is empty or if current one is empty.
        return accumulator || (arrayValue.length == 0);
      },
      false
    )
  ) throw "Equation must pose either an equality or inequality";
};

var Expression = function Expression(expressionString) {
  if (typeof expressionString !== "string") throw "Expression must be specified";

  if (expressionString.trim() === "") {
    this.entryPoint = function(){return 0;}
    return;
  }

  this._compiledExpression = [];

  this._compiledUnaryExpressions = [];

  this.orderOfBinaryOperations = {
    "^": function exponent(a, b) {
      return Math.pow(a, b);
    },
    "*": function multiplication(a, b) {
      return b * a;
    },
    "/": function division(a, b) {
      return b / a;
    },
    "+": function addition(a, b) {
      return b + a;
    },
    "-": function subtraction(a, b) {
      return b - a;
    }
  };

  this.orderOfUnaryOperations = {
    "(": function parentheses() {
      throw "Parentheses not implemented";
    },
    "+": function (a) {
      return +a;
    },
    "-": function (a) {
      return -a;
    },
    "sin": function sine(a) {
      return Math.sin(a);
    },
    "cos": function cosine(a) {
      return Math.cos(a);
    }
  }

  //remove single pair of parens if they are on the ends and end matches beginning as they don't matter.
  expressionString = expressionString.trim();
  if (/^\(.*\)$/.test(expressionString)) {
    var leftUnmatched = 0; //error if goes below 0
    var endIndex = [];
    //Only two scenarios (()) and ()() to disambiguate bc recursion takes care of rest
    expressionString.split("").forEach(function (char, index) {
      if (char === "(") leftUnmatched++;
      if (char === ")") leftUnmatched--;
      if (leftUnmatched === 0) endIndex.push(index);
    })
    //get the first completed closure of () after beginning
    if (endIndex[0] === expressionString.length - 1)
    expressionString = expressionString.substring(1, expressionString.length - 1);
  }

  //Base case for recursion: if there are no operations being applied to string,
  //return the number in a function that returns that number
  // or letter in a function that takes a value for that variable as a parameter

  if (
      Object.keys(this.orderOfUnaryOperations).reduce(
        function (collector, item) {
          return collector && (expressionString.indexOf(item) === -1);
        },
        true
      ) &&
    Object.keys(this.orderOfBinaryOperations).reduce(
      function (collector, item) {
        return collector && (expressionString.indexOf(item) === -1);
      },
      true
    )
  ) {
    expressionString = expressionString.trim();
    if (/[A-z]/.test(expressionString)){
      this.entryPoint = function (variablesObj) {
        return variablesObj[expressionString];
      }
    } else {
      this.entryPoint = function () {
        return parseFloat(expressionString);
      }
    }
    return;
  }
  //Split so that right, ex the minus is evaluated first 2x + 3 - 2
  //That way when we break it apart the first term is evaluated first
//  var indexOfSymbol = -1; //Keep scope here so I can check if symbol is found.
  var tempExpressionString = expressionString; //for processing string only
  var isUnary = function (symbol, expressionString) {
    var regions = expressionString.split(symbol);
    //Regions will be <2 only if it's not found, so it's not unary.
    if (regions.length < 2) return false;
    //get one before last one
    var testStr = regions[regions.length - 2].trim();
    return testStr === "" || /[^A-z0-9]$/.test(testStr);
  };

  var isInParens = function (indexOfLocation, expressionString) {
    var openParensBefore = 0;
    var openParensAfter = 0;
    var before = expressionString.substring(0, indexOfLocation - 1);
    var after = expressionString.substring(indexOfLocation + 1);
    before.split("").forEach(function (letter) {
      if (letter === "(") ++openParensBefore;
      if (letter === ")") --openParensBefore;
    });
    after.split("").forEach(function (letter) {
      if (letter === "(") ++openParensAfter;
      if (letter === ")") --openParensAfter;
    });

    return !(openParensBefore === 0 && openParensAfter === 0);
  }

  this.entryPoint = null; //will hold first function to call in stack.
  // Do binary after unary
  Object.keys(this.orderOfUnaryOperations).
  concat(Object.keys(this.orderOfBinaryOperations)).
  reverse().forEach(
    function (symbol) {
      var indexOfSymbol = expressionString.lastIndexOf(symbol);
      //Don't eval any symbols in parens, the parens op. will do that!

      //if we found a symbol we shouldn't check other symbols
      if (indexOfSymbol > -1) {
        if (isInParens(indexOfSymbol, expressionString)) return;
        if (isUnary(symbol, expressionString)) {
          if (/\(/.test(symbol)){
            this.entryPoint = function (variablesObj) {
              return (new Expression(
                expressionString.substring(
                  expressionString.indexOf("(") + 1,
                  expressionString.indexOf(")")
                )).evaluate(variablesObj)) +
                (new Expression(
                  expressionString.substring(
                    expressionString.indexOf(")") + 1
                  )
                ).evaluate(variablesObj));
            }
          } else {
            this.entryPoint = function (variablesObj) {
              return this.orderOfUnaryOperations[symbol](
                (new Expression(
                expressionString.substring(indexOfSymbol + symbol.length)
              )).evaluate(variablesObj));
            };
          }
        } else {
          this.entryPoint = function(variablesObj) {
            // if expression isn't unary,
            // then we pass the fn it represents the two sides
            return this.orderOfBinaryOperations[symbol](
              (new Expression(
                expressionString.substring(0, indexOfSymbol)
              )).evaluate(variablesObj),
              (new Expression(
                expressionString.substring(indexOfSymbol + symbol.length)
              )).evaluate(variablesObj)
            );
          };
        }
      }
  }.bind(this)
);
//{
  // console.log(this.entryPoint);

  /*while (indexOfSymbol === -1){
    indexOfSymbol = -1;

    var isInParens = function (indexOfLocation, expressionString) {
      return indexOfLocation > expressionString.indexOf("(") &&
        indexOfLocation < expressionString.lastIndexOf(")");
    }
    // Do binary after unary
    Object.keys(this.orderOfBinaryOperations).
    concat(Object.keys(this.orderOfUnaryOperations)).
    reverse().forEach(function (symbol) {

      //detect if is truly a unary symbol by encountering either
      //the string boundary or a non-letter or non-number on the left
      //and it not being a space
      this.unaryCount = 0;
      var currentIsUnary = isUnary(symbol, expressionString);
      //Don't execute of symbol is already found
      if (indexOfSymbol > -1) return;
      indexOfSymbol = tempExpressionString.lastIndexOf(symbol);
      //Symbol will be evaluated in nested expression, so not now
      if (isInParens(indexOfSymbol, expressionString)) {
        indexOfSymbol = -1;
        return;
      }

      if (currentIsUnary){
        if (indexOfSymbol > -1) { //symbol has to exist
          if (symbol === "(") {
            var indexOfEndParens = tempExpressionString.lastIndexOf(")");
            this._compiledExpression.concat(
              new Expression(
                tempExpressionString.substring(
                  indexOfSymbol + symbol.length,
                  indexOfEndParens
                )
              )._compiledExpression // Just evaluate stuff inside of parentheses
            );
            tempExpressionString = tempExpressionString.substring(indexOfSymbol);
          } else {
            //Increment unary count and push the value as a symbol.
            this._compiledExpression.push("u" + ++this.unaryCount);
            afterText = tempExpressionString.
            split(symbol).pop().
            match(/[A-z0-9]+/)[0];

            this._compiledUnaryExpressions.push(new Expression(afterText));
          }
        }
      } else {
        if (indexOfSymbol > -1) { //symbol has to exist
          this._compiledExpression.push(symbol);
          this._compiledExpression.concat(
            new Expression(
              tempExpressionString.substring(indexOfSymbol + symbol.length)
            )._compiledExpression
          );
          tempExpressionString = tempExpressionString.substring(indexOfSymbol);
        }
      }

    }.bind(this));
  }}*/
if (!this.entryPoint) throw "No EntryPoint exception";
}

Expression.prototype.evaluate = function (variablesObj) {
  return this.entryPoint(variablesObj);
};
<|endoftext|>


<commit_before>import React from 'react';
import {
  View,
  Text,
  ScrollView,
  Image,
} from 'react-native';
import Dimensions from 'Dimensions';
import styles from '../styles/styles.ios';
import stylePropType from 'react-style-proptype';

export default class AboutScene extends React.Component {
    constructor(props) {
      super(props);
    }

    componentWillMount() {
      this.props.bg();
    }

    render() {
      const WIDTH = Dimensions.get('window').width - 20;
      return (
        <ScrollView style={{flex: 1, backgroundColor: '#3c3c3b'}}>
          <Text style={styles.ctext}>
            Aplikace vznikla ve spolupráci Zoo Brno a Masarykovy univerzity. Na projektu se podíleli studenti oboru Český jazyk se specializací počítačová lingvistika (PLIN) a pracovníci Ústavu českého jazyka Filozofické fakulty MU. Nasazení aplikace do praxe bylo finančně podpořeno Centrem pro transfer technologií MU.
          </Text>
          <View style={{height: 100, backgroundColor: 'white', marginTop: 10}}>
          <View style={{flex: 1, flexDirection: 'row', alignItems: 'center', justifyContent: 'center'}}>
              <Image source={require('../images/logo/logo-zoo.png')} style={{width: WIDTH/3, height: 90, marginRight: 5}} resizeMode='contain'/>
              <Image source={require('../images/logo/logo-ctt.png')} style={{width: WIDTH/3, height: 90, marginRight: 5}} resizeMode='contain'/>
              <Image source={require('../images/logo/logo-plin.jpg')} style={{width: WIDTH/3, height: 90}} resizeMode='contain'/>
          </View>
          </View>
          <View style={{height: 100, backgroundColor: 'white', marginTop: 10}}>
          <View style={{flex: 1, flexDirection: 'row', alignItems: 'center', justifyContent: 'center'}}>
            <Image source={require('../images/logo/logo-ff.png')} style={{width: WIDTH/3, height: 90}} resizeMode='contain'/>
            <Image source={require('../images/logo/logo-mu.png')} style={{width: WIDTH/3, height: 90}} resizeMode='contain'/>
            <Image source={require('../images/logo/logo-kevin.png')} style={{width: WIDTH/3, height: 90}} resizeMode='contain'/>
          </View>
          </View>
          <Text style={[styles.ctext, {paddingTop: 10}]}>
          Koordinace projektu: Dana Hlaváčková
          </Text><Text style={[styles.ctext, {paddingTop: 10}]}>
          Programování aplikace: Marek Grác
          </Text><Text style={[styles.ctext, {paddingTop: 10}]}>
          Dizajn: Kevin Scherrer
          </Text><Text style={[styles.ctext, {paddingTop: 10}]}>
          Závěrečné korektury v češtině: Hana Žižková
          </Text><Text style={[styles.ctext, {paddingTop: 10}]}>
          Příprava textů, korektury, překlady do angličtiny a všechny další pomocné práce:
          Babincová Adriana,
          Bendáková Eliška,
          Findejsová Lucie,
          Geržová Helena,
          Holaj Richard,
          Jančová Nikola,
          Kachlířová Miroslava,
          Klement David,
          Konečný Jakub,
          Koníková Michaela,
          Kubešová Nikola,
          Kunovský Adam,
          Masopustová Markéta,
          Novotná Marie,
          Obluková Barbora,
          Paulíčková Lucie,
          Petříková Nikola,
          Plocková Anna,
          Procházková Jana,
          Stará Marie,
          Šebestová Běla,
          Tomečková Kateřina,
          Vacíková Michala,
          Vostřelová Klára
          </Text>
        </ScrollView>
      );
    }
};

AboutScene.propTypes = {
    bg: React.PropTypes.func.isRequired,
//@fix    navigator: React.PropTypes.func.isRequired,
};
<commit_msg>[grammar] Fix typo<commit_after>import React from 'react';
import {
  View,
  Text,
  ScrollView,
  Image,
} from 'react-native';
import Dimensions from 'Dimensions';
import styles from '../styles/styles.ios';
import stylePropType from 'react-style-proptype';

export default class AboutScene extends React.Component {
    constructor(props) {
      super(props);
    }

    componentWillMount() {
      this.props.bg();
    }

    render() {
      const WIDTH = Dimensions.get('window').width - 20;
      return (
        <ScrollView style={{flex: 1, backgroundColor: '#3c3c3b'}}>
          <Text style={styles.ctext}>
            Aplikace vznikla ve spolupráci Zoo Brno a Masarykovy univerzity. Na projektu se podíleli studenti oboru Český jazyk se specializací počítačová lingvistika (PLIN) a pracovníci Ústavu českého jazyka Filozofické fakulty MU. Nasazení aplikace do praxe bylo finančně podpořeno Centrem pro transfer technologií MU.
          </Text>
          <View style={{height: 100, backgroundColor: 'white', marginTop: 10}}>
          <View style={{flex: 1, flexDirection: 'row', alignItems: 'center', justifyContent: 'center'}}>
              <Image source={require('../images/logo/logo-zoo.png')} style={{width: WIDTH/3, height: 90, marginRight: 5}} resizeMode='contain'/>
              <Image source={require('../images/logo/logo-ctt.png')} style={{width: WIDTH/3, height: 90, marginRight: 5}} resizeMode='contain'/>
              <Image source={require('../images/logo/logo-plin.jpg')} style={{width: WIDTH/3, height: 90}} resizeMode='contain'/>
          </View>
          </View>
          <View style={{height: 100, backgroundColor: 'white', marginTop: 10}}>
          <View style={{flex: 1, flexDirection: 'row', alignItems: 'center', justifyContent: 'center'}}>
            <Image source={require('../images/logo/logo-ff.png')} style={{width: WIDTH/3, height: 90}} resizeMode='contain'/>
            <Image source={require('../images/logo/logo-mu.png')} style={{width: WIDTH/3, height: 90}} resizeMode='contain'/>
            <Image source={require('../images/logo/logo-kevin.png')} style={{width: WIDTH/3, height: 90}} resizeMode='contain'/>
          </View>
          </View>
          <Text style={[styles.ctext, {paddingTop: 10}]}>
          Koordinace projektu: Dana Hlaváčková
          </Text><Text style={[styles.ctext, {paddingTop: 10}]}>
          Programování aplikace: Marek Grác
          </Text><Text style={[styles.ctext, {paddingTop: 10}]}>
          Design: Kevin Scherrer
          </Text><Text style={[styles.ctext, {paddingTop: 10}]}>
          Závěrečné korektury v češtině: Hana Žižková
          </Text><Text style={[styles.ctext, {paddingTop: 10}]}>
          Příprava textů, korektury, překlady do angličtiny a všechny další pomocné práce:
          Babincová Adriana,
          Bendáková Eliška,
          Findejsová Lucie,
          Geržová Helena,
          Holaj Richard,
          Jančová Nikola,
          Kachlířová Miroslava,
          Klement David,
          Konečný Jakub,
          Koníková Michaela,
          Kubešová Nikola,
          Kunovský Adam,
          Masopustová Markéta,
          Novotná Marie,
          Obluková Barbora,
          Paulíčková Lucie,
          Petříková Nikola,
          Plocková Anna,
          Procházková Jana,
          Stará Marie,
          Šebestová Běla,
          Tomečková Kateřina,
          Vacíková Michala,
          Vostřelová Klára
          </Text>
        </ScrollView>
      );
    }
};

AboutScene.propTypes = {
    bg: React.PropTypes.func.isRequired,
//@fix    navigator: React.PropTypes.func.isRequired,
};
<|endoftext|>


<commit_before>var tls = require('tls');
var Q = require('q');
var cert = require('./cert');
var MAX_SERVERS = 256;
var MAX_PORT = 60000;
var curPort = 50000;
var DELAY = 360;

function ServerAgent() {
	this._cache = {};
	this._serverCount = 0;
}

var proto = ServerAgent.prototype;

proto.createServer = function createServer(hostname, secureConnectionListener, callback) {
	var self = this;
	var cache = self._cache;

	var promise = cache[hostname];
	var defer;

	if (!promise) {
		defer = Q.defer();
		cache[hostname] = promise = defer.promise;
	}

	promise.done(callback);

	if (!defer) {
		return ;
	}

	var certs = cert.getCert(hostname);
	self.freeServer();
	getServer({
		key: certs[0],
		cert: certs[1]
	}, secureConnectionListener,
			function(port, server) {
		server.on('error', function() {
			if (cache[hostname]) {
				tls.createServer(options, secureConnectionListener)
				.on('error', noop);
			}
		});

		setTimeout(function() {
			promise.server = server;
			defer.resolve(port);
		}, DELAY);
	});
	self._serverCount++;

	return self;
};

proto.freeServer = function() {
	var self = this;
	if (self._serverCount < MAX_SERVERS) {
		return;
	}

	var cache = self._cache;
	for (var i in cache) {
		destroy(i);
	}

	function destroy(hostname) {
		var promise = cache[hostname];
		promise.done(function(port) {
			var server = promise.server;
			if (!server.connections && self._serverCount > MAX_SERVERS) {
				delete cache[hostname];
				--self._serverCount;
				setTimeout(function() {
					server.close();
				}, DELAY);
			}
		});
	}
};

proto.destroy = function destroy() {
	var cache = this._cache;
	this._cache = {};
	this._serverCount = 0;
	for (var i in cache) {
		var promise = cache[i];
		promise.done(function(port) {
			setTimeout(function() {
				promise.server.close();
			}, DELAY);
		});
	}
};

function getServer(options, secureConnectionListener, callback) {
	var self = this;

	if (curPort > MAX_PORT) {
		curPort = MIN_PORT = 40000;
	}

	var server = tls.createServer(options, secureConnectionListener);
	var next = function() {
		getServer(options, secureConnectionListener, callback);
	};
	server.on('error', next);

	var port = curPort++;
	server.listen(port, 'localhost', function() {
		server.removeListener('error', next);
		callback(port, server);
	});
}

function noop() {}

module.exports = ServerAgent;

<commit_msg>server agent<commit_after>var tls = require('tls');
var Q = require('q');
var cert = require('./cert');
var MAX_SERVERS = 256;
var MAX_PORT = 60000;
var curPort = 50000;
var DELAY = 500;

function ServerAgent() {
	this._cache = {};
	this._serverCount = 0;
}

var proto = ServerAgent.prototype;

proto.createServer = function createServer(hostname, secureConnectionListener, callback) {
	var self = this;
	var cache = self._cache;

	var promise = cache[hostname];
	var defer;

	if (!promise) {
		defer = Q.defer();
		cache[hostname] = promise = defer.promise;
	}

	promise.done(callback);

	if (!defer) {
		return ;
	}

	var certs = cert.getCert(hostname);
	self.freeServer();
	getServer({
		key: certs[0],
		cert: certs[1]
	}, secureConnectionListener,
			function(port, server) {
		server.on('error', function() {
			if (cache[hostname]) {
				tls.createServer(options, secureConnectionListener)
				.on('error', noop);
			}
		});

		setTimeout(function() {
			promise.server = server;
			defer.resolve(port);
		}, DELAY);
	});
	self._serverCount++;

	return self;
};

proto.freeServer = function() {
	var self = this;
	if (self._serverCount < MAX_SERVERS) {
		return;
	}

	var cache = self._cache;
	for (var i in cache) {
		destroy(i);
	}

	function destroy(hostname) {
		var promise = cache[hostname];
		promise.done(function(port) {
			var server = promise.server;
			if (!server.connections && self._serverCount > MAX_SERVERS) {
				delete cache[hostname];
				--self._serverCount;
				setTimeout(function() {
					server.close();
				}, DELAY);
			}
		});
	}
};

proto.destroy = function destroy() {
	var cache = this._cache;
	this._cache = {};
	this._serverCount = 0;
	for (var i in cache) {
		var promise = cache[i];
		promise.done(function(port) {
			setTimeout(function() {
				promise.server.close();
			}, DELAY);
		});
	}
};

function getServer(options, secureConnectionListener, callback) {
	var self = this;

	if (curPort > MAX_PORT) {
		curPort = MIN_PORT = 40000;
	}

	var server = tls.createServer(options, secureConnectionListener);
	var next = function() {
		getServer(options, secureConnectionListener, callback);
	};
	server.on('error', next);

	var port = curPort++;
	server.listen(port, 'localhost', function() {
		server.removeListener('error', next);
		callback(port, server);
	});
}

function noop() {}

module.exports = ServerAgent;

<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
	Schema = mongoose.Schema;

/**
 * Shop grocery Schema
 */
var ShopGrocerySchema = new Schema({
	name: {
		type: String,
		default: '',
		required: 'Please fill Shop grocery name',
		trim: true
	},
  phone: {
    type: String,
    default: '',
    required: 'Please fill Shop grocery Phone Numbers',
    trim: true
  },
  address: {
    type: String,
    default: '',
    unique: true,
    required: 'Please fill Shop grocery address',
    trim: true
  },

  loc: { 'type': {type: String, enum: "Point", default: "Point"}, coordinates: { type: [Number],   default: [0,0]} },

  category: {
    type: String,
    default: 'Grocery',
    required: 'Please fill Shop grocery category',
    trim: true
  },
  city: {
    type: String,
    default: '',
    required: 'Please fill Shop grocery city',
    trim: true
  },
  mobile: {
    type: String,
    default: '',
    trim: true
  },
	created: {
		type: Date,
		default: Date.now
	},

  appDownloaded: {
    type : Boolean
  },
  deliveryDistance:{
    type: String,
    default: "1"
  },
  deliveryTime:{
    type: String
  },
  startTime:{
    type: String,
    default: "9"
  },
  closeTime:{
    type: String,
    default: "10"
  },
  ourExperience:{
    type: String
  },
  OffDay:{
    type: String
  },
	user: {
		type: Schema.ObjectId,
		ref: 'User'
	}
});
ShopGrocerySchema.index({loc: '2dsphere'});
mongoose.model('ShopGrocery', ShopGrocerySchema);
<commit_msg>files modified for tc<commit_after>'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
	Schema = mongoose.Schema;

/**
 * Shop grocery Schema
 */
var ShopGrocerySchema = new Schema({
	name: {
		type: String,
		default: '',
		required: 'Please fill Shop grocery name',
		trim: true
	},
  phone: {
    type: String,
    default: '',
    required: 'Please fill Shop grocery Phone Numbers',
    trim: true
  },
  address: {
    type: String,
    default: '',
    unique: true,
    required: 'Please fill Shop grocery address',
    trim: true
  },

  loc: { 'type': {type: String, enum: "Point", default: "Point"}, coordinates: { type: [Number],   default: [0,0]} },

  category: {
    type: String,
    default: 'Grocery',
    required: 'Please fill Shop grocery category',
    trim: true
  },
  city: {
    type: String,
    default: '',
    required: 'Please fill Shop grocery city',
    trim: true
  },
  mobile: {
    type: String,
    default: '',
    trim: true
  },
	created: {
		type: Date,
		default: Date.now
	},

  appDownloaded: {
    type : Boolean
  },
  deliveryDistance:{
    type: String,
    default: "1"
  },
  deliveryTime:{
    type: String,
    default: "30"
  },
  startTime:{
    type: String,
    default: "9"
  },
  closeTime:{
    type: String,
    default: "10"
  },
  ourExperience:{
    type: String
  },
  OffDay:{
    type: String
  },
	user: {
		type: Schema.ObjectId,
		ref: 'User'
	}
});
ShopGrocerySchema.index({loc: '2dsphere'});
mongoose.model('ShopGrocery', ShopGrocerySchema);
<|endoftext|>


<commit_before>steal('can/event', function() {
	// Adds propagation of events
	// can.extend(Class.prototype, can.event, { __propagate: 'prop' })
	var dispatch = can.dispatch;
	can.dispatch = can.event.dispatch = can.event.trigger = function (event, args) {
		var propagate = this.__propagate || false;

		// Inject propagation into event, when applicable
		if (propagate && typeof event.isPropagationStopped === 'undefined') {
			// Initialize the event into an object
			if (typeof event === 'string') {
				event = {
					type: event
				};
			}

			// Add extra event properties
			// This could be done with can.simpleExtend, but this avoids extra logic execution
			var stop = false,
				prevent = false;
			event.currentTarget = this;
			event.target = event.target || this;
			event.descendants = event.target === event.currentTarget ? [] : [event.target];
			event.stopPropagation = function() {
				stop = true;
			};
			event.isPropagationStopped = function() {
				return stop;
			};
			event.preventDefault = function() {
				prevent = true;
			};
			event.isDefaultPrevented = function() {
				return prevent;
			};
		}
		else if (propagate) {
			// Set the current target when propagating
			event = can.simpleExtend({}, event);
			event.descendants = [event.currentTarget].concat(event.descendants);
			event.currentTarget = this;
		}

		// Call original dispatch
		dispatch.call(this, event, args);

		// Call propagated events
		if (propagate && !event.isPropagationStopped() && this[propagate]) {
			// Call the propagated can.dispatch (otherwise it'll only propagate one level)
			can.dispatch.call(this[propagate], event, args);
		}
	};

	return can.event;
});
<commit_msg>Tweaking injection of propagation enhancements, prevent default should always be present<commit_after>steal('can/event', function() {
	// Adds propagation of events
	// can.extend(Class.prototype, can.event, { __propagate: 'prop' })
	var dispatch = can.dispatch;
	can.dispatch = can.event.dispatch = can.event.trigger = function (event, args) {
		var propagate = this.__propagate || false;

		// Inject propagation into event, when applicable
		if (typeof event.isPropagationStopped === 'undefined') {
			// Initialize the event into an object
			if (typeof event === 'string') {
				event = {
					type: event
				};
			}

			// Add extra event properties
			// This could be done with can.simpleExtend, but this avoids extra logic execution
			var stop = false,
				prevent = false;

			// Add propagation, if applicable
			if (propagate) {
				event.currentTarget = this;
				event.target = event.target || this;
				event.descendants = event.target === event.currentTarget ? [] : [event.target];
				event.stopPropagation = function() {
					stop = true;
				};
				event.isPropagationStopped = function() {
					return stop;
				};
			}

			// Always add default prevention
			event.preventDefault = function() {
				prevent = true;
			};
			event.isDefaultPrevented = function() {
				return prevent;
			};
		}
		else if (propagate) {
			// Set the current target when propagating
			event = can.simpleExtend({}, event);
			event.descendants = [event.currentTarget].concat(event.descendants);
			event.currentTarget = this;
		}

		// Call original dispatch
		dispatch.call(this, event, args);

		// Call propagated events
		if (propagate && !event.isPropagationStopped() && this[propagate]) {
			// Call the propagated can.dispatch (otherwise it'll only propagate one level)
			can.dispatch.call(this[propagate], event, args);
		}
	};

	return can.event;
});
<|endoftext|>


<commit_before>/*
  Module
  Synchronous dependency resolver.

  * What Is it?

    Module is a javascript dependency resolver. It helps you structure
    your app as modules.

    Basically, you define your app as a bunch of encapsulated
    modules.

    Each module is a function that lists its dependencies to other
    modules.

    You have one module called "main" that kicks everything off. That's
    pretty much all there is to it.

  * Why Does This Exist?

    RequireJS is a fine tool, but I had some issues with it. In
    production, you usually want to compress your assets into a single
    file and serve it as such. In development, you want to serve your
    assets separately. In dev mode with RequireJS, you perform
    asynchronous requests to the server to get modules, but this
    breaks parity with how you get assets in production (ie, in prod,
    all your files are in one big glob, so you don't need to hit the
    server).

    Usually, this makes no difference, but there are cases where it
    does. For example, if you're building an Ember app and define your
    routes in different modules - the app will fail if you try to
    navigate to a route before it's module file has been loaded. In
    production mode, however, it would work.

    In development and production, Module performs loading the same
    way; synchronously. It makes no difference if your files are
    served separately, concatenated, or minified.

  * Basic Usage

    To define a module:
      module.register(moduleName, function() {...})

    To include a module:
      module.register('foobar', function(moduleA, moduleB) {...})
    OR
      needs('moduleA', 'moduleB')

  * Where To Include Files

    Suggestions on where to include your asset files (ie, <head>,
    <body>) are only guidelines. Do what's best for your app.

    - Include this file in the <head> tag so it loads quickly.
    - Include your module definition files in the <body>.
    - You modules need to be defined before they can be loaded, so
      include your main module after your module definitions.

  ** Working With Third Party Libraries

     I prefer to simply leave third-party libraries as globals, but if
     you want to be very strictly modular, you can define adapters
     like so:

       module.register('$', function() {
         var jQuery = jQuery;
         window.$ = null;  // Remove global references to jQuery.
         window.jQuery = null;
         return jQuery;
       });

       module.register('Backbone', function() {
         var Backbone = Backbone;
         window.Backbone = null;
         return Backbone;
       });

    You might want to package all your adapters into a single
    module like this:

       module.register('adaptors', function() {

         module.register('$', function() {
           var jQuery = jQuery;
           window.$ = null;  // Remove global references to jQuery.
           window.jQuery = null;
           return jQuery;
         });

         module.register('Backbone', function() {
           var Backbone = Backbone;
           window.Backbone = null;
           return Backbone;
         });

         return module.needs(['$', 'Backbone'])

       });

    Then from your main module, you can do this:

      module.register('main', function() {
        runs('adaptors');  // Same as needs, but suppresses return value.
      });

  * Issues
    - Circular dependencies are an issue. Module fails if it
      detects if it detects one. For example, this is critically bad:

        module.register('foo', function(bar) {...});
        module.register('bar', function(foo) {...});

  * Guidelines For A Good Dependency Resolver
    - Doesn't get in the way of:
      - [X] Debugging
      - [X] Minification
      - [X] Gzip compression
      - [X] File concatentation
      - [X] Caching
    - [ ] File load order doesn't matter.
    - [X] Supports fast development/reloads.
    - [X] Production and development mode is the same.

  * Differences with RequireJS

    - The biggest difference is that this library doesn't do
      asynchronous loading in dev mode. Module is not a module loader,
      it is a dependency resolver whereas RequireJS is a module loader
      AND a dependency resolver. This actually makes it more
      comparable to Almond than RequireJS.

    - RequireJS executes code within a define block as soon as the
      file is loaded. Module waits until a module is needed before it
      executes its define block.

    - Doesn't come packaged with a directory traversal or file
      minification/concatenation tool akin r.js

    - Defined modules must be given names so they can be
      referenced. The downside to this is that names must be managed,
      but module referencing is more flexible.

    - With Module, you can define a module anywhere and as many as you
      want within a single file. You can also list and get
      dependencies anywhere you want. For example, this is perfectly valid code:

        // utils.js

        module.register('domUtils', function() {});
        module.register('strUtils', function(depA, depB) {

          // This has the same effect of listing "depC" in the parameters.
          var depC = needs('depC');

          // More includes.
          var moreDeps = needs(['app', 'math', 'trig']);

          for (var i=0; i < 4; i++) {

            // Registering modules dynamically.
            module.register('module' + i, function() {
              return i;
            }));

          }

        });

    - Dependencies can be listed in function parameters similar to
      AngularJS. Example:

        // RequireJS
        define(['app/app', 'utils/dom'], function(app, domUtils), {...});

        // Module
        module.register('main', function(app, domUtils) {...});

  * Similarities with RequireJS

    - Both require an entry point file. RequireJS requires a main.js
      file. Module simply requires you to register a module named
      "main".

  * TODO
    - Give it a trendy name. Eg, Tangler, Lasso, Curkit,
      standoff. "Module" is too generic and probably taken.
    - Write unit tests.
    - What about circular dependencies?
    - Detect circular dependencies and throw errors.
    - Allow global/default options.
    - In register, disallow any tag names that can't be used as in function params.
    - Allow namespace needs(). Eg,

    Allow separator option (default=/).
    needs:
     'editor: controller view', -> editor/controller, editor/view
     'gui: controller view'     -> editor/controller, editor/view

*/

(function() {

  'use strict';

  function hasKey(obj, key) {
    return obj.hasOwnProperty(key);
  }

  // Merges object @right into object @left and returns object @left.
  function merge(left, right) {
    for (var key in right) {
      if (hasKey(right, key))
        left[key] = right[key];
    }
    return left;
  }

  // Gets function parameters as a list of strings.
  // Source: http://stackoverflow.com/a/9924463/376590
  function getFnParams(fn) {
    var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
    var fnStr = fn.toString().replace(STRIP_COMMENTS, '');
    var result = fnStr.slice(fnStr.indexOf('(') + 1, fnStr.indexOf(')')).match(/([^\s,]+)/g);
    if (result == null)
      result = [];
    return result;
  }

  function Loader() {
    this.modules = {};
    this.cache = {};
  };

  var loader = new Loader();

  merge(Loader.prototype, {

    exists: function(moduleName) {
      return hasKey(this.modules, moduleName);
    },

    // Get a module. If it doesn't exist, throw an error.
    get: function(moduleName) {
      if (this.exists(moduleName))
        return this.modules[moduleName];
      else
        throw 'ModuleError: Module [' + moduleName + '] not found.';
    },

    // Loads a module and its dependencies.
    load: function(moduleName) {

      if (!hasKey(this.cache, moduleName)) {

        var module = this.get(moduleName);
        var paramNames = getFnParams(module);
        var args = [];

        for (var i=0; i < paramNames.length; i++)
          args.push(this.load(paramNames[i]));

        var moduleThis = {
          moduleName: moduleName,
          moduleParams: paramNames
        };

        this.cache[moduleName] = module.apply(moduleThis, args);

      }

      return this.cache[moduleName];

    },

    /*
      Register a module. Similar to RequireJS's define function. Names
      are case-sensitive.
    */
    register: function(tag, fn, options) {

      /*

        options: {

          @loadNow: Load the module right now, without any other
          module calling it as a dependency. Be careful with this
          option as it allows your app to undermine the behavoir or
          "main" by having multiple entry points.

          @log: Show a message when this module is loaded.

        }

      */

      if (typeof options === 'undefined')
        var options = {};

      if (typeof tag !== 'string')
        throw "ModuleError: First parameter must be a unique tag string for the module.";
      else if (tag.length == 0)
        throw "ModuleError: Tag cannot be an empty string.";
      else if (this.exists(tag))
        throw "ModuleError: Module [" + tag + "] already exists.";

      this.modules[tag] = fn;
      if (tag === 'main' || options.loadNow)
        this.load(tag);

    }

  });

  // Alias for module.load, but can also take an array. It can also take a string with spaces.
  window.needs = function(moduleNames) {

    if (typeof moduleNames === 'string') {
      var split = moduleNames.split(' ');
      if (split.length > 1)
        moduleNames = split;
      else
        return loader.load(moduleNames);
    }

    if (moduleNames instanceof Array) {
      var moduleRets = {};
      for (var i=0; i < moduleNames.length; i++) {
        var name = moduleNames[i];
        moduleRets[name] = loader.load(name);
      }
      return moduleRets;
    }

  };

  // Alias for needs(), but suppresses return value. You can always
  // use needs() instead, but calling this instead makes it clear that
  // you care only about the module's definition code, not whatever
  // (if anything) the module returns.
  window.runs = function() {
    needs.apply(null, arguments);
    return null;
  };

  window.module = loader;

})();
<commit_msg>Changed variable name.<commit_after>/*
  Module
  Synchronous dependency resolver.

  * What Is it?

    Module is a javascript dependency resolver. It helps you structure
    your app as modules.

    Basically, you define your app as a bunch of encapsulated
    modules.

    Each module is a function that lists its dependencies to other
    modules.

    You have one module called "main" that kicks everything off. That's
    pretty much all there is to it.

  * Why Does This Exist?

    RequireJS is a fine tool, but I had some issues with it. In
    production, you usually want to compress your assets into a single
    file and serve it as such. In development, you want to serve your
    assets separately. In dev mode with RequireJS, you perform
    asynchronous requests to the server to get modules, but this
    breaks parity with how you get assets in production (ie, in prod,
    all your files are in one big glob, so you don't need to hit the
    server).

    Usually, this makes no difference, but there are cases where it
    does. For example, if you're building an Ember app and define your
    routes in different modules - the app will fail if you try to
    navigate to a route before it's module file has been loaded. In
    production mode, however, it would work.

    In development and production, Module performs loading the same
    way; synchronously. It makes no difference if your files are
    served separately, concatenated, or minified.

  * Basic Usage

    To define a module:
      module.register(moduleName, function() {...})

    To include a module:
      module.register('foobar', function(moduleA, moduleB) {...})
    OR
      needs('moduleA', 'moduleB')

  * Where To Include Files

    Suggestions on where to include your asset files (ie, <head>,
    <body>) are only guidelines. Do what's best for your app.

    - Include this file in the <head> tag so it loads quickly.
    - Include your module definition files in the <body>.
    - You modules need to be defined before they can be loaded, so
      include your main module after your module definitions.

  ** Working With Third Party Libraries

     I prefer to simply leave third-party libraries as globals, but if
     you want to be very strictly modular, you can define adapters
     like so:

       module.register('$', function() {
         var jQuery = jQuery;
         window.$ = null;  // Remove global references to jQuery.
         window.jQuery = null;
         return jQuery;
       });

       module.register('Backbone', function() {
         var Backbone = Backbone;
         window.Backbone = null;
         return Backbone;
       });

    You might want to package all your adapters into a single
    module like this:

       module.register('adaptors', function() {

         module.register('$', function() {
           var jQuery = jQuery;
           window.$ = null;  // Remove global references to jQuery.
           window.jQuery = null;
           return jQuery;
         });

         module.register('Backbone', function() {
           var Backbone = Backbone;
           window.Backbone = null;
           return Backbone;
         });

         return module.needs(['$', 'Backbone'])

       });

    Then from your main module, you can do this:

      module.register('main', function() {
        runs('adaptors');  // Same as needs, but suppresses return value.
      });

  * Issues
    - Circular dependencies are an issue. Module fails if it
      detects if it detects one. For example, this is critically bad:

        module.register('foo', function(bar) {...});
        module.register('bar', function(foo) {...});

  * Guidelines For A Good Dependency Resolver
    - Doesn't get in the way of:
      - [X] Debugging
      - [X] Minification
      - [X] Gzip compression
      - [X] File concatentation
      - [X] Caching
    - [ ] File load order doesn't matter.
    - [X] Supports fast development/reloads.
    - [X] Production and development mode is the same.

  * Differences with RequireJS

    - The biggest difference is that this library doesn't do
      asynchronous loading in dev mode. Module is not a module loader,
      it is a dependency resolver whereas RequireJS is a module loader
      AND a dependency resolver. This actually makes it more
      comparable to Almond than RequireJS.

    - RequireJS executes code within a define block as soon as the
      file is loaded. Module waits until a module is needed before it
      executes its define block.

    - Doesn't come packaged with a directory traversal or file
      minification/concatenation tool akin r.js

    - Defined modules must be given names so they can be
      referenced. The downside to this is that names must be managed,
      but module referencing is more flexible.

    - With Module, you can define a module anywhere and as many as you
      want within a single file. You can also list and get
      dependencies anywhere you want. For example, this is perfectly valid code:

        // utils.js

        module.register('domUtils', function() {});
        module.register('strUtils', function(depA, depB) {

          // This has the same effect of listing "depC" in the parameters.
          var depC = needs('depC');

          // More includes.
          var moreDeps = needs(['app', 'math', 'trig']);

          for (var i=0; i < 4; i++) {

            // Registering modules dynamically.
            module.register('module' + i, function() {
              return i;
            }));

          }

        });

    - Dependencies can be listed in function parameters similar to
      AngularJS. Example:

        // RequireJS
        define(['app/app', 'utils/dom'], function(app, domUtils), {...});

        // Module
        module.register('main', function(app, domUtils) {...});

  * Similarities with RequireJS

    - Both require an entry point file. RequireJS requires a main.js
      file. Module simply requires you to register a module named
      "main".

  * TODO
    - Give it a trendy name. Eg, Tangler, Lasso, Curkit,
      standoff. "Module" is too generic and probably taken.
    - Write unit tests.
    - What about circular dependencies?
    - Detect circular dependencies and throw errors.
    - Allow global/default options.
    - In register, disallow any tag names that can't be used as in function params.
    - Allow namespace needs(). Eg,

      Allow separator option (default=/).
      needs:
       'editor: controller view', -> editor/controller, editor/view
       'gui: controller view'     -> editor/controller, editor/view

    - Document options

*/

(function(context) {

  'use strict';

  function hasKey(obj, key) {
    return obj.hasOwnProperty(key);
  }

  // Merges object @right into object @left and returns object @left.
  function merge(left, right) {
    for (var key in right) {
      if (hasKey(right, key))
        left[key] = right[key];
    }
    return left;
  }

  // Gets function parameters as a list of strings.
  // Source: http://stackoverflow.com/a/9924463/376590
  function getFnParams(fn) {
    var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
    var fnStr = fn.toString().replace(STRIP_COMMENTS, '');
    var result = fnStr.slice(fnStr.indexOf('(') + 1, fnStr.indexOf(')')).match(/([^\s,]+)/g);
    if (result == null)
      result = [];
    return result;
  }

  function Loader() {
    this.modules = {};
    this.cache = {};
  };

  var loader = new Loader();

  merge(Loader.prototype, {

    exists: function(moduleName) {
      return hasKey(this.modules, moduleName);
    },

    // Get a module. If it doesn't exist, throw an error.
    get: function(moduleName) {
      if (this.exists(moduleName))
        return this.modules[moduleName];
      else
        throw 'ModuleError: Module [' + moduleName + '] not found.';
    },

    // Loads a module and its dependencies.
    load: function(moduleName) {

      if (!hasKey(this.cache, moduleName)) {

        var module = this.get(moduleName);
        var paramNames = getFnParams(module);
        var args = [];

        for (var i=0; i < paramNames.length; i++)
          args.push(this.load(paramNames[i]));

        var moduleThis = {
          moduleName: moduleName,
          moduleParams: paramNames
        };

        this.cache[moduleName] = module.apply(moduleThis, args);

      }

      return this.cache[moduleName];

    },

    /*
      Register a module. Similar to RequireJS's define function. Names
      are case-sensitive.
    */
    register: function(tag, fn, options) {

      /*

        options: {

          @loadNow: Load the module right now, without any other
          module calling it as a dependency. Be careful with this
          option as it allows your app to undermine the behavoir or
          "main" by having multiple entry points.

          @log: Show a message when this module is loaded.

        }

      */

      if (typeof options === 'undefined')
        var options = {};

      if (typeof tag !== 'string')
        throw "ModuleError: First parameter must be a unique tag string for the module.";
      else if (tag.length == 0)
        throw "ModuleError: Tag cannot be an empty string.";
      else if (this.exists(tag))
        throw "ModuleError: Module [" + tag + "] already exists.";

      this.modules[tag] = fn;
      if (tag === 'main' || options.loadNow)
        this.load(tag);

    }

  });

  // Alias for module.load, but can also take an array. It can also take a string with spaces.
  context.needs = function(moduleNames) {

    if (typeof moduleNames === 'string') {
      var split = moduleNames.split(' ');
      if (split.length > 1)
        moduleNames = split;
      else
        return loader.load(moduleNames);
    }

    if (moduleNames instanceof Array) {
      var moduleRets = {};
      for (var i=0; i < moduleNames.length; i++) {
        var name = moduleNames[i];
        moduleRets[name] = loader.load(name);
      }
      return moduleRets;
    }

  };

  // Alias for needs(), but suppresses return value. You can always
  // use needs() instead, but calling this instead makes it clear that
  // you care only about the module's definition code, not whatever
  // (if anything) the module returns.
  context.runs = function() {
    needs.apply(null, arguments);
    return null;
  };

  context.module = loader;

})(window);
<|endoftext|>


<commit_before>angular.module('pcApp.fcm.directives.cytoscapes', [])

    .directive('cytoscape', function ($rootScope) {
        // graph visualisation by - https://github.com/cytoscape/cytoscape.js
        return {
            restrict: 'E',
            template: '

',
            replace: true,
            scope: {
                // data objects to be passed as an attributes - for nodes and edges
                cyData: '=',
                cyEdges: '=', // controller function to be triggered when clicking on a node
                cyClick: '&',
                cyMouseup: '&',
                cyMouseover: '&', //adding mouseover functionality
                cyMouseout: '&'//adding mouseour functionality
            },
            link: function (scope, element, attrs, fn) {
                // dictionary of colors by types. Just to show some design options
                scope.typeColors = {
                    'ellipse': '#992222',
                    'triangle': '#222299',
                    'rectangle': '#661199',
                    'roundrectangle': '#772244',
                    'pentagon': '#990088',
                    'hexagon': '#229988',
                    'heptagon': '#118844',
                    'octagon': '#335577',
                    'star': '#113355'
                };

                // graph  build
                scope.doCy = function () { // will be triggered on an event broadcast
                    // initialize data object
                    scope.elements = {};
                    scope.elements.nodes = [];
                    scope.elements.edges = [];

                    // parse data and create the Nodes array
                    // object type - is the object's group
                    for (i = 0; i < scope.cyData.length; i++) {
                        // get id, name and type  from the object
                        var dId = "n" + scope.cyData[i].id;
                        var dName = scope.cyData[i].name.substring(0, 24);
                        var dType = 'roundrectangle';
                        var posX = scope.cyData[i].posX;
                        var posY = scope.cyData[i].posY;
                        // get color from the object-color dictionary
                        var typeColor = scope.typeColors[4];
                        // build the object, add or change properties as you need - just have a name and id
                        var elementObj = {
                            data: {
                                id: dId,
                                name: dName,
                                typeColor: typeColor,
                                typeShape: dType,
                                type: dType
                            },
                            position: {
                                x: posX,
                                y: posY
                            }
                        };
                        // add new object to the Nodes array
                        scope.elements.nodes.push(elementObj);
                    }

                    // parse edges
                    // you can build a complete object in the controller and pass it without rebuilding it in the directive.
                    // doing it like that allows you to add options, design or what needed to the objects
                    // doing it like that is also good if your data object/s has a different structure
                    for (i = 0; i < scope.cyEdges.length; i++) {
                        // get edge source
                        var eSource = "n" + scope.cyEdges[i].source;
                        // get edge target
                        var eTarget = "n" + scope.cyEdges[i].target;
                        // get edge id
                        var eId = "e" + scope.cyEdges[i].id;
                        // get edge weight
                        var eLabel = scope.cyEdges[i].weighted;
                        // Change arrows colors against the weight value.
                        var edgecolor = 'grey';
                        if (eLabel > 0)
                            edgecolor = 'green';
                        else if (eLabel < 0)
                            edgecolor = 'red';

                        // build the edge object
                        var edgeObj = {
                            data: {
                                id: eId,
                                source: eSource,
                                target: eTarget,
                                label: eLabel,
                                edgecolor: edgecolor

                            }
                        };
                        // adding the edge object to the edges array
                        scope.elements.edges.push(edgeObj);
                    }

                    // graph  initialization
                    // use object's properties as properties using: data(propertyName)
                    // check Cytoscapes site for much more data, options, designs etc
                    // http://cytoscape.github.io/cytoscape.js/
                    // here are just some basic options
                    $('#cy').cytoscape({
                        showOverlay: false,
                        zoom: 1,
                        layout: {
                            name: 'preset',
                            positions: undefined,
                            zoom: undefined,
                            pan: undefined,
                            fit: false,
                            padding: 30,
                            animate: false,
                            animationDuration: 500,
                            ready: undefined,
                            stop: undefined,
                        },
                        style: cytoscape.stylesheet().selector('node').css({
                            'shape': 'roundrectangle',
                            'width': '200',
                            'height': '40',
                            'background-color': 'data(typeColor)',
                            'content': 'data(name)',
                            'text-valign': 'center',
                            'color': 'white',
                            'text-outline-color': 'data(typeColor)'
                        }).selector('edge').css({
                            'target-arrow-shape': 'triangle',
                            'content': 'data(label)',
                            'text-outline-color': '#FFFFFF',
                            'text-outline-opacity': '1',
                            'text-outline-width': 2,
                            'text-valign': 'center',
                            'color': '#777777',
                            'width': '2px',
                            'line-color': 'data(edgecolor)',
                            'target-arrow-color': 'data(edgecolor)'
                        }).selector(':selected').css({
                            'background-color': '#C50C44',
                            'line-color': 'black',
                            'target-arrow-color': 'black',
                            'source-arrow-color': 'black'
                        }).selector('.faded').css({
                            'opacity': 0.65,
                            'text-opacity': 0.65
                        }),
                        ready: function () {
                            window.cy = this;

                            // giddy up...
                            cy.elements().unselectify();
                            // ##MOBA## this is to calculate the doubleClick trigger over a node in the Edit mode.
                            var tappedBefore;
                            var tappedTimeout;
                            cy.on('tap', function (event) {

                                var tappedNow = event.cyTarget;
                                if (tappedTimeout && tappedBefore) {
                                    clearTimeout(tappedTimeout);
                                }
                                if (tappedBefore === tappedNow) {
                                    tappedNow.trigger('doubleTap');
                                    tappedBefore = null;
                                } else {
                                    tappedTimeout = setTimeout(function () { tappedBefore = null; }, 300);
                                    tappedBefore = tappedNow;
                                }
                            });

                            // Event listeners
                            // with sample calling to the controller function as passed as an attribute
                            cy.on('unselect', 'node', function (e) {
                                var nodes = cy.elements('node');
                                nodes.css('background-color', 'gray');
                            });

                            cy.on('doubleTap', 'node', function (e) {
                                var nodes = cy.elements('node');
                                nodes.css('background-color', 'gray');
                                var evtTarget = e.cyTarget;
                                var nodeId = evtTarget.id();
                                var edgesFrom = cy.elements('edge[source="' + nodeId + '"]');
                                var edgesTo = cy.elements('edge[target="' + nodeId + '"]');
                                evtTarget.css('background-color', '#C50C44');
                                for (i = 0; i < edgesFrom.length; i++) {
                                    var nodeChild = edgesFrom[i].target();
                                    nodeChild.css('background-color', 'blue');
                                }
                                for (i = 0; i < edgesTo.length; i++) {
                                    var nodeParent = edgesTo[i].source();
                                    nodeParent.css('background-color', 'green');
                                }
                                scope.cyClick({ value: nodeId });
                            });

                            cy.on('mouseup', 'node', function (e) {
                                var evtTarget = e.cyTarget;
                                var nodeId = evtTarget.id();
                                var posX = evtTarget.position("x");
                                var posY = evtTarget.position("y");
                                scope.cyMouseup({
                                    value: nodeId,
                                    x: posX,
                                    y: posY
                                });
                            });

                            //Binding mouseover event
                            cy.on('mouseover', 'node', function (e) {
                                var evtTarget = e.cyTarget;
                                var nodeId = evtTarget.id();
                                var posX = evtTarget.renderedPosition("x") + $('#cy').position().left;
                                var posY = evtTarget.renderedPosition("y") + $('#cy').position().top;
                                scope.cyMouseover({
                                    value: nodeId,
                                    x: posX,
                                    y: posY
                                });
                                console.log(evtTarget.position("y") + '-' + $('#cy').position().top + '-' + posY);
                            });

                            //Binding mouseout event
                            cy.on('mouseout', 'node', function (e) {
                                var evtTarget = e.cyTarget;
                                var nodeId = evtTarget.id();
                                var posX = evtTarget.position("x");
                                var posY = evtTarget.position("y");
                                scope.cyMouseout({
                                    value: nodeId,
                                    x: posX,
                                    y: posY
                                });
                            });

                            cy.on('doubleTap', 'edge', function (e) {
                                var evtTarget = e.cyTarget;
                                var nodeId = evtTarget.id();
                                scope.cyClick({ value: nodeId });
                            });
                            cy.panzoom({
                                // options go here
                            });
                            // load the objects array
                            // use cy.add() / cy.remove() with passed data to add or remove nodes and edges without rebuilding the graph
                            // sample use can be adding a passed variable which will be broadcast on change
                            cy.load(scope.elements);

                            if (scope.elements.nodes.length > 5) {
                                cy.fit(window.defaults.fitPadding);
                            }
                        }
                    });

                }; // end doCy()

                // When the app object changed = redraw the graph
                // you can use it to pass data to be added or removed from the object without redrawing it
                // using cy.remove() / cy.add()
                $rootScope.$on('appChanged', function (e) {
                    scope.doCy();
                });
            }
        };
    });
<commit_msg>increasing the width of the concepts box policycompass/policycompass#646<commit_after>angular.module('pcApp.fcm.directives.cytoscapes', [])

    .directive('cytoscape', function ($rootScope) {
        // graph visualisation by - https://github.com/cytoscape/cytoscape.js
        return {
            restrict: 'E',
            template: '

',
            replace: true,
            scope: {
                // data objects to be passed as an attributes - for nodes and edges
                cyData: '=',
                cyEdges: '=', // controller function to be triggered when clicking on a node
                cyClick: '&',
                cyMouseup: '&',
                cyMouseover: '&', //adding mouseover functionality
                cyMouseout: '&'//adding mouseour functionality
            },
            link: function (scope, element, attrs, fn) {
                // dictionary of colors by types. Just to show some design options
                scope.typeColors = {
                    'ellipse': '#992222',
                    'triangle': '#222299',
                    'rectangle': '#661199',
                    'roundrectangle': '#772244',
                    'pentagon': '#990088',
                    'hexagon': '#229988',
                    'heptagon': '#118844',
                    'octagon': '#335577',
                    'star': '#113355'
                };

                // graph  build
                scope.doCy = function () { // will be triggered on an event broadcast
                    // initialize data object
                    scope.elements = {};
                    scope.elements.nodes = [];
                    scope.elements.edges = [];

                    // parse data and create the Nodes array
                    // object type - is the object's group
                    for (i = 0; i < scope.cyData.length; i++) {
                        // get id, name and type  from the object
                        var dId = "n" + scope.cyData[i].id;
                        var dName = scope.cyData[i].name.substring(0, 24);
                        var dType = 'roundrectangle';
                        var posX = scope.cyData[i].posX;
                        var posY = scope.cyData[i].posY;
                        // get color from the object-color dictionary
                        var typeColor = scope.typeColors[4];
                        // build the object, add or change properties as you need - just have a name and id
                        var elementObj = {
                            data: {
                                id: dId,
                                name: dName,
                                typeColor: typeColor,
                                typeShape: dType,
                                type: dType
                            },
                            position: {
                                x: posX,
                                y: posY
                            }
                        };
                        // add new object to the Nodes array
                        scope.elements.nodes.push(elementObj);
                    }

                    // parse edges
                    // you can build a complete object in the controller and pass it without rebuilding it in the directive.
                    // doing it like that allows you to add options, design or what needed to the objects
                    // doing it like that is also good if your data object/s has a different structure
                    for (i = 0; i < scope.cyEdges.length; i++) {
                        // get edge source
                        var eSource = "n" + scope.cyEdges[i].source;
                        // get edge target
                        var eTarget = "n" + scope.cyEdges[i].target;
                        // get edge id
                        var eId = "e" + scope.cyEdges[i].id;
                        // get edge weight
                        var eLabel = scope.cyEdges[i].weighted;
                        // Change arrows colors against the weight value.
                        var edgecolor = 'grey';
                        if (eLabel > 0)
                            edgecolor = 'green';
                        else if (eLabel < 0)
                            edgecolor = 'red';

                        // build the edge object
                        var edgeObj = {
                            data: {
                                id: eId,
                                source: eSource,
                                target: eTarget,
                                label: eLabel,
                                edgecolor: edgecolor

                            }
                        };
                        // adding the edge object to the edges array
                        scope.elements.edges.push(edgeObj);
                    }

                    // graph  initialization
                    // use object's properties as properties using: data(propertyName)
                    // check Cytoscapes site for much more data, options, designs etc
                    // http://cytoscape.github.io/cytoscape.js/
                    // here are just some basic options
                    $('#cy').cytoscape({
                        showOverlay: false,
                        zoom: 1,
                        layout: {
                            name: 'preset',
                            positions: undefined,
                            zoom: undefined,
                            pan: undefined,
                            fit: false,
                            padding: 30,
                            animate: false,
                            animationDuration: 500,
                            ready: undefined,
                            stop: undefined,
                        },
                        style: cytoscape.stylesheet().selector('node').css({
                            'shape': 'roundrectangle',
                            'width': '300', //https://github.com/policycompass/policycompass/issues/646
                            'height': '40',
                            'background-color': 'data(typeColor)',
                            'content': 'data(name)',
                            'text-valign': 'center',
                            'color': 'white',
                            'text-outline-color': 'data(typeColor)'
                        }).selector('edge').css({
                            'target-arrow-shape': 'triangle',
                            'content': 'data(label)',
                            'text-outline-color': '#FFFFFF',
                            'text-outline-opacity': '1',
                            'text-outline-width': 2,
                            'text-valign': 'center',
                            'color': '#777777',
                            'width': '2px',
                            'line-color': 'data(edgecolor)',
                            'target-arrow-color': 'data(edgecolor)'
                        }).selector(':selected').css({
                            'background-color': '#C50C44',
                            'line-color': 'black',
                            'target-arrow-color': 'black',
                            'source-arrow-color': 'black'
                        }).selector('.faded').css({
                            'opacity': 0.65,
                            'text-opacity': 0.65
                        }),
                        ready: function () {
                            window.cy = this;

                            // giddy up...
                            cy.elements().unselectify();
                            // ##MOBA## this is to calculate the doubleClick trigger over a node in the Edit mode.
                            var tappedBefore;
                            var tappedTimeout;
                            cy.on('tap', function (event) {

                                var tappedNow = event.cyTarget;
                                if (tappedTimeout && tappedBefore) {
                                    clearTimeout(tappedTimeout);
                                }
                                if (tappedBefore === tappedNow) {
                                    tappedNow.trigger('doubleTap');
                                    tappedBefore = null;
                                } else {
                                    tappedTimeout = setTimeout(function () { tappedBefore = null; }, 300);
                                    tappedBefore = tappedNow;
                                }
                            });

                            // Event listeners
                            // with sample calling to the controller function as passed as an attribute
                            cy.on('unselect', 'node', function (e) {
                                var nodes = cy.elements('node');
                                nodes.css('background-color', 'gray');
                            });

                            cy.on('doubleTap', 'node', function (e) {
                                var nodes = cy.elements('node');
                                nodes.css('background-color', 'gray');
                                var evtTarget = e.cyTarget;
                                var nodeId = evtTarget.id();
                                var edgesFrom = cy.elements('edge[source="' + nodeId + '"]');
                                var edgesTo = cy.elements('edge[target="' + nodeId + '"]');
                                evtTarget.css('background-color', '#C50C44');
                                for (i = 0; i < edgesFrom.length; i++) {
                                    var nodeChild = edgesFrom[i].target();
                                    nodeChild.css('background-color', 'blue');
                                }
                                for (i = 0; i < edgesTo.length; i++) {
                                    var nodeParent = edgesTo[i].source();
                                    nodeParent.css('background-color', 'green');
                                }
                                scope.cyClick({ value: nodeId });
                            });

                            cy.on('mouseup', 'node', function (e) {
                                var evtTarget = e.cyTarget;
                                var nodeId = evtTarget.id();
                                var posX = evtTarget.position("x");
                                var posY = evtTarget.position("y");
                                scope.cyMouseup({
                                    value: nodeId,
                                    x: posX,
                                    y: posY
                                });
                            });

                            //Binding mouseover event
                            cy.on('mouseover', 'node', function (e) {
                                var evtTarget = e.cyTarget;
                                var nodeId = evtTarget.id();
                                var posX = evtTarget.renderedPosition("x") + $('#cy').position().left;
                                var posY = evtTarget.renderedPosition("y") + $('#cy').position().top;
                                scope.cyMouseover({
                                    value: nodeId,
                                    x: posX,
                                    y: posY
                                });
                                console.log(evtTarget.position("y") + '-' + $('#cy').position().top + '-' + posY);
                            });

                            //Binding mouseout event
                            cy.on('mouseout', 'node', function (e) {
                                var evtTarget = e.cyTarget;
                                var nodeId = evtTarget.id();
                                var posX = evtTarget.position("x");
                                var posY = evtTarget.position("y");
                                scope.cyMouseout({
                                    value: nodeId,
                                    x: posX,
                                    y: posY
                                });
                            });

                            cy.on('doubleTap', 'edge', function (e) {
                                var evtTarget = e.cyTarget;
                                var nodeId = evtTarget.id();
                                scope.cyClick({ value: nodeId });
                            });
                            cy.panzoom({
                                // options go here
                            });
                            // load the objects array
                            // use cy.add() / cy.remove() with passed data to add or remove nodes and edges without rebuilding the graph
                            // sample use can be adding a passed variable which will be broadcast on change
                            cy.load(scope.elements);

                            if (scope.elements.nodes.length > 5) {
                                cy.fit(window.defaults.fitPadding);
                            }
                        }
                    });

                }; // end doCy()

                // When the app object changed = redraw the graph
                // you can use it to pass data to be added or removed from the object without redrawing it
                // using cy.remove() / cy.add()
                $rootScope.$on('appChanged', function (e) {
                    scope.doCy();
                });
            }
        };
    });
<|endoftext|>