<commit_before>app.controller('ResponseDataCtrl', function ($scope, $http) {

        $scope.optionsChart1 = {
            chart: {
                type: 'pieChart',
                height: 140,
                donut: false,
                color: ['#ffa500', '#939393'],
                x: function(d){return d.key;},
                y: function(d){return d.y;},
                showLabels: true,
                showLegend: false,
                pie: {
                    startAngle: function(d) { return d.startAngle -Math.PI },
                    endAngle: function(d) { return d.endAngle -Math.PI }
                }
            }
        };

        $scope.dataChart1 = [
            {
                key: "Yes",
                y: 0
            },
            {
                key: "No",
                y: 0
            }
        ];

        $scope.optionsChart2 = {
            chart: {
                type: 'pieChart',
                height: 140,
                donut: false,
                color: ['#ffa500', '#939393'],
                x: function(d){return d.key;},
                y: function(d){return d.y;},
                showLabels: true,
                showLegend: false,
                pie: {
                    startAngle: function(d) { return d.startAngle -Math.PI },
                    endAngle: function(d) { return d.endAngle -Math.PI }
                }
            }
        };

        $scope.dataChart2 = [
            {
                key: "Yes",
                y: 0
            },
            {
                key: "No",
                y: 0
            }
        ];

        $scope.optionsChart3 = {
            chart: {
                type: 'pieChart',
                height: 140,
                donut: false,
                color: ['#ffa500', '#939393'],
                x: function(d){return d.key;},
                y: function(d){return d.y;},
                showLabels: true,
                showLegend: false,
                pie: {
                    startAngle: function(d) { return d.startAngle -Math.PI },
                    endAngle: function(d) { return d.endAngle -Math.PI }
                }
            }
        };

        $scope.dataChart3 = [
            {
                key: "Yes",
                y: 0
            },
            {
                key: "No",
                y: 0
            }
        ];

        $scope.optionsChart4 = {
            chart: {
                type: 'pieChart',
                height: 140,
                donut: false,
                color: ['#ffa500', '#939393'],
                x: function(d){return d.key;},
                y: function(d){return d.y;},
                showLabels: true,
                showLegend: false,
                pie: {
                    startAngle: function(d) { return d.startAngle -Math.PI },
                    endAngle: function(d) { return d.endAngle -Math.PI }
                }
            }
        };

        $scope.dataChart4 = [
            {
                key: "Yes",
                y: 0
            },
            {
                key: "No",
                y: 0
            }
        ];

       $http({
            method: 'GET',
            url: '/results'
        }).then(function successCallback(response) {

            for(i in response.data.results){
                response.data.results[i].responses
                console.log(response.data.results[i].responses[0])
                if(response.data.results[i].responses[0]){
                    $scope.dataChart1[0].y++;
                } else{
                    $scope.dataChart1[1].y++;
                }

                if(response.data.results[i].responses[1]){
                    $scope.dataChart2[0].y++;
                } else{
                    $scope.dataChart2[1].y++;
                }

                 if(response.data.results[i].responses[2]){
                    $scope.dataChart3[0].y++;
                } else{
                    $scope.dataChart3[1].y++;
                }

                if(response.data.results[i].responses[3]){
                    $scope.dataChart4[0].y++;
                } else{
                    $scope.dataChart4[1].y++;
                }
            }

        }, function errorCallback(response) {
             console.log(response);
        });
});
<commit_msg>asdfa<commit_after>app.controller('ResponseDataCtrl', function ($scope, $http) {

        $scope.optionsChart1 = {
            chart: {
                type: 'pieChart',
                height: 140,
                donut: false,
                color: ['#ffa500', '#939393'],
                x: function(d){return d.key;},
                y: function(d){return d.y;},
                showLabels: true,
                showLegend: false,
                pie: {
                    startAngle: function(d) { return d.startAngle -Math.PI },
                    endAngle: function(d) { return d.endAngle -Math.PI }
                }
            }
        };

        $scope.dataChart1 = [
            {
                key: "Yes",
                y: 0
            },
            {
                key: "No",
                y: 0
            }
        ];

        $scope.optionsChart2 = {
            chart: {
                type: 'pieChart',
                height: 140,
                donut: false,
                color: ['#ffa500', '#939393'],
                x: function(d){return d.key;},
                y: function(d){return d.y;},
                showLabels: true,
                showLegend: false,
                pie: {
                    startAngle: function(d) { return d.startAngle -Math.PI },
                    endAngle: function(d) { return d.endAngle -Math.PI }
                }
            }
        };

        $scope.dataChart2 = [
            {
                key: "Yes",
                y: 0
            },
            {
                key: "No",
                y: 0
            }
        ];

        $scope.optionsChart3 = {
            chart: {
                type: 'pieChart',
                height: 140,
                donut: false,
                color: ['#ffa500', '#939393'],
                x: function(d){return d.key;},
                y: function(d){return d.y;},
                showLabels: true,
                showLegend: false,
                pie: {
                    startAngle: function(d) { return d.startAngle -Math.PI },
                    endAngle: function(d) { return d.endAngle -Math.PI }
                }
            }
        };

        $scope.dataChart3 = [
            {
                key: "Yes",
                y: 0
            },
            {
                key: "No",
                y: 0
            }
        ];

        $scope.optionsChart4 = {
            chart: {
                type: 'pieChart',
                height: 140,
                donut: false,
                color: ['#ffa500', '#939393'],
                x: function(d){return d.key;},
                y: function(d){return d.y;},
                showLabels: true,
                showLegend: false,
                pie: {
                    startAngle: function(d) { return d.startAngle -Math.PI },
                    endAngle: function(d) { return d.endAngle -Math.PI }
                }
            }
        };

        $scope.dataChart4 = [
            {
                key: "Yes",
                y: 0
            },
            {
                key: "No",
                y: 0
            }
        ];

       $http({
            method: 'GET',
            url: '/results'
        }).then(function successCallback(response) {

            for(i in response.data.results){

                if(response.data.results[i].responses[0].answer){
                    $scope.dataChart1[0].y++;
                } else{
                    $scope.dataChart1[1].y++;
                }

                if(response.data.results[i].responses[1].answer){
                    $scope.dataChart2[0].y++;
                } else{
                    $scope.dataChart2[1].y++;
                }

                 if(response.data.results[i].responses[2].answer){
                    $scope.dataChart3[0].y++;
                } else{
                    $scope.dataChart3[1].y++;
                }

                if(response.data.results[i].responses[3].answer){
                    $scope.dataChart4[0].y++;
                } else{
                    $scope.dataChart4[1].y++;
                }
            }

        }, function errorCallback(response) {
             console.log(response);
        });
});
<|endoftext|>


<commit_before>var keystone = require('keystone');
var transform = require('model-transform');

var Types = keystone.Field.Types;

var Ballot = new keystone.List('Ballot', {
	defaultSort: '-time',
	nodelete: true,
	nocreate: true
});

Ballot.add({
	time: { type: Types.Datetime, default: Date.now },
	status: {
		type: Types.Select,
		options: ['signing', 'queued', 'pending', 'initialized', 'registered', 'complete', 'error'],
		required: true,
		initial: true
	},
	voter: { type: String, required: true, initial: true },
	vote: { type: Types.Relationship, ref: 'Vote', required: true, initial: true },
	error: { type: String }
});

transform.toJSON(Ballot);

Ballot.defaultColumns = 'time, status, vote';
Ballot.register();
<commit_msg>Mark all the fields of the Ballot model as read-only.<commit_after>var keystone = require('keystone');
var transform = require('model-transform');

var Types = keystone.Field.Types;

var Ballot = new keystone.List('Ballot', {
	defaultSort: '-updatedAt',
	track: { createdAt: true, updatedAt: true },
	nodelete: true,
	nocreate: true
});

Ballot.add({
	status: {
		type: Types.Select,
		options: ['signing', 'queued', 'pending', 'initialized', 'registered', 'complete', 'error'],
		required: true,
		initial: true,
		noedit: true
	},
	voter: { type: String, required: true, initial: true, noedit: true  },
	vote: { type: Types.Relationship, ref: 'Vote', required: true, initial: true, noedit: true  },
	error: { type: String, noedit: true }
});

transform.toJSON(Ballot);

Ballot.defaultColumns = 'time, status, vote';
Ballot.register();
<|endoftext|>


<commit_before>const _ = require('lodash'),
  path = require('path'),
  xmldom = require('xmldom'),
  Promise = require('bluebird'),
  fs = Promise.promisifyAll(require('fs')),
  log = require('../logger');

function FileExtractingError(message, fileName) {
  this.message = message;
  this.fileName = fileName;
  this.name = 'FileExtractingError';
  // Error.captureStackTrace(this, FileExtractingError);
}
FileExtractingError.prototype = Object.create(Error.prototype);
FileExtractingError.prototype.constructor = FileExtractingError;

module.exports = function extractSuffixPaths(xmlFileNames, targetDir) {
  log.info('Extracting suffix paths (root-to-leaf paths) for %d files to %s',
    xmlFileNames.length, targetDir);
  return Promise.map(xmlFileNames, (xmlFile) => {
    return extract(xmlFile, targetDir)
        .then((res) => {
          log.info(res);
        })
        .catch(FileExtractingError, (e) => {
          log.error('FileExtractingError in %s, %s', e.fileName, e.message);
        })
        .catch((e) => {
          log.error(e);
        });
  }, {
    concurrency: 1 })
    .then(() => {
      return Promise.resolve('Done');
    })
    .catch(FileExtractingError, (e) => {
      log.error('Failed to extract suffix paths for %s. %s', e.fileName, e.message);
      return Promise.reject(e);
    });
};

function extract(xmlFile, targetDir) {
  return new Promise((resolve, reject) => {
    const outFile = path.resolve(targetDir,
        `${path.basename(xmlFile, '.xml')}-ui-suffix.txt`),
      writeStream = fs.createWriteStream(outFile, {
        encoding: 'utf8'
      }),
      xmlFileContent = fs.readFileSync(xmlFile, 'utf8'),
      doc = new xmldom.DOMParser()
      .parseFromString(xmlFileContent, 'text/xml'),
      fileElements = doc.getElementsByTagName('File');
    _.forEach(fileElements, (fileElement) => {
      const rootElementList = _.filter(fileElement.childNodes, (child) => {
        return child.nodeType === 1;
      });
      // Each layout file must contain exactly one root element.
      if (rootElementList.length !== 1) {
        fs.unlinkSync(outFile);
        reject(new FileExtractingError(
          `File node ${fileElement.attributes[0].nodeValue} has more than one child. `,
          xmlFile));
      }
      const rootElement = rootElementList[0],
        children = _.filter(rootElement.childNodes, (child) => {
          return child.nodeType === 1;
        });
      _.forEach(children, (child) => {
        doChildren(child, writeStream);
      });
    });

    writeStream.on('finish', () => {
      resolve('Suffix paths have been extracted for %s', xmlFile);
    });
    writeStream.end();
  });
}

function doChildren(element, writeStream) {
  if (element.hasChildNodes()) {
    // writeAncestors(parent, writeStream);
    const children = _.filter(element.childNodes, (child) => {
      return child.nodeType === 1;
    });
    if (children.length === 0) {
      writeAncestors(element, writeStream);
    }
    _.forEach(children, (child) => {
      doChildren(child, writeStream);
    });
  }
  else {
    writeAncestors(element, writeStream);
  }
}
function getAncestorsLine(element) {
  'use strict';
  const ancestors = [],
    childName = element.localName;
  let line = '',
    newElement = element;
  while (newElement.parentNode && newElement.parentNode.localName !== 'File') {
    newElement = newElement.parentNode;
    if (newElement.nodeType === 1) {
      ancestors.push(newElement.localName);
    }
  }
  for (let i = ancestors.length - 1; i > -1; i--) {
    line += `${ancestors[i]}$`;
  }
  return line + childName;
}

function writeAncestors(element, writeStream) {
  const line = getAncestorsLine(element),
    arr = line.split('$');
  writeStream.write(`${line}\n`);
  if (arr.length > 2) {
    arr.forEach((v, k) => {
      if (k !== arr.length - 1) {
        writeStream.write(`${arr[k]}$${arr[k + 1]}\n`);
      }
    });
  }
}
<commit_msg>fix invalid log message<commit_after>const _ = require('lodash'),
  path = require('path'),
  xmldom = require('xmldom'),
  Promise = require('bluebird'),
  fs = Promise.promisifyAll(require('fs')),
  log = require('../logger');

function FileExtractingError(message, fileName) {
  this.message = message;
  this.fileName = fileName;
  this.name = 'FileExtractingError';
  // Error.captureStackTrace(this, FileExtractingError);
}
FileExtractingError.prototype = Object.create(Error.prototype);
FileExtractingError.prototype.constructor = FileExtractingError;

module.exports = function extractSuffixPaths(xmlFileNames, targetDir) {
  log.info('Extracting suffix paths (root-to-leaf paths) for %d files to %s',
    xmlFileNames.length, targetDir);
  return Promise.map(xmlFileNames, (xmlFile) => {
    return extract(xmlFile, targetDir)
        .then((res) => {
          log.info(res);
        })
        .catch(FileExtractingError, (e) => {
          log.error('FileExtractingError in %s, %s', e.fileName, e.message);
        })
        .catch((e) => {
          log.error(e);
        });
  }, {
    concurrency: 1 })
    .then(() => {
      return Promise.resolve('Done');
    })
    .catch(FileExtractingError, (e) => {
      log.error('Failed to extract suffix paths for %s. %s', e.fileName, e.message);
      return Promise.reject(e);
    });
};

function extract(xmlFile, targetDir) {
  return new Promise((resolve, reject) => {
    const outFile = path.resolve(targetDir,
        `${path.basename(xmlFile, '.xml')}-ui-suffix.txt`),
      writeStream = fs.createWriteStream(outFile, {
        encoding: 'utf8'
      }),
      xmlFileContent = fs.readFileSync(xmlFile, 'utf8'),
      doc = new xmldom.DOMParser()
      .parseFromString(xmlFileContent, 'text/xml'),
      fileElements = doc.getElementsByTagName('File');
    _.forEach(fileElements, (fileElement) => {
      const rootElementList = _.filter(fileElement.childNodes, (child) => {
        return child.nodeType === 1;
      });
      // Each layout file must contain exactly one root element.
      if (rootElementList.length !== 1) {
        fs.unlinkSync(outFile);
        reject(new FileExtractingError(
          `File node ${fileElement.attributes[0].nodeValue} has more than one child. `,
          xmlFile));
      }
      const rootElement = rootElementList[0],
        children = _.filter(rootElement.childNodes, (child) => {
          return child.nodeType === 1;
        });
      _.forEach(children, (child) => {
        doChildren(child, writeStream);
      });
    });

    writeStream.on('finish', () => {
      resolve(`Suffix paths have been extracted for ${xmlFile}`);
    });
    writeStream.end();
  });
}

function doChildren(element, writeStream) {
  if (element.hasChildNodes()) {
    // writeAncestors(parent, writeStream);
    const children = _.filter(element.childNodes, (child) => {
      return child.nodeType === 1;
    });
    if (children.length === 0) {
      writeAncestors(element, writeStream);
    }
    _.forEach(children, (child) => {
      doChildren(child, writeStream);
    });
  }
  else {
    writeAncestors(element, writeStream);
  }
}
function getAncestorsLine(element) {
  'use strict';
  const ancestors = [],
    childName = element.localName;
  let line = '',
    newElement = element;
  while (newElement.parentNode && newElement.parentNode.localName !== 'File') {
    newElement = newElement.parentNode;
    if (newElement.nodeType === 1) {
      ancestors.push(newElement.localName);
    }
  }
  for (let i = ancestors.length - 1; i > -1; i--) {
    line += `${ancestors[i]}$`;
  }
  return line + childName;
}

function writeAncestors(element, writeStream) {
  const line = getAncestorsLine(element),
    arr = line.split('$');
  writeStream.write(`${line}\n`);
  if (arr.length > 2) {
    arr.forEach((v, k) => {
      if (k !== arr.length - 1) {
        writeStream.write(`${arr[k]}$${arr[k + 1]}\n`);
      }
    });
  }
}
<|endoftext|>


<commit_before>/*
 * === IdentiHeart ===
 * Author: Schlipak
 *
 * This library generates a canvas-based procedural
 * default profile picture. The generation is based
 * on the user's username, hashed into a unique string
 * to number representation.
 */
 (function() {
	// Hash generator
	var Crusher = function() {
		this.hash = function(s) {
			return s.split("").reduce(function(a, b) {
				a = ((a << 5) - a) + b.charCodeAt(0);
				return a & a
			}, 0);
		}
	}

	// ========================================= //
	// Class Heart
	Heart = function(c, ctx, margin, scale) {
		// Color palette
		var PALETTE = [
		'#F44336', '#E91E63', '#9C27B0', '#673AB7', '#3F51B5', '#2196F3',
		'#03A9F4', '#00BCD4', '#009688', '#4CAF50', '#8BC34A', '#CDDC39',
		'#FFEB3B', '#FFC107', '#FF9800', '#FF5722', '#795548', '#607D8B'
		];

		// Generated colors
		this.primary;
		this.accent;

		// Drawing margin
		this.margin = margin || 5;
		// Drawing scale
		this.scale = scale || 20;
		// Computed cell size
		this.cellSize = c.width - (this.margin * this.scale)  - c.width / 2;
		// Hashed username
		this.hash;
		// Generated blocks
		this.blocks;
		// Generated shape
		this.shape;

		// Hash setter
		this.setUsername = function(string) {
			var crusher = new Crusher();
			this.hash = crusher.hash(string);
		}

		// Main draw function
		this.draw = function() {
			this.init();

			// Rotate the canvas -45deg
			ctx.save();
			ctx.translate(c.width/2, c.height/2);
			ctx.rotate(- Math.PI / 4);
			ctx.translate(-c.width/2, -c.height/2);

			this.generateBlocks();
			this.drawBlocks();
			this.drawOutline();

			this.shape = new Shape(c, ctx, this.hash, this.primary, this.accent, {
				x: (this.margin * this.scale) + 1.5 * this.cellSize,
				y: (this.margin * this.scale) + 0.5 * this.cellSize
			}, this.scale, this.cellSize);
			this.shape.draw();

			// Restore the original matrix
			ctx.restore();
		}

		// Initializes a few parameters and clears the canvas
		this.init = function() {
			// Purge the block array
			this.blocks = new Array();
			// Purge the shape
			this.shape = null;

			// Generate colors
			this.primary = PALETTE[Math.abs(this.hash % PALETTE.length)];
			this.accent = PALETTE[Math.abs((this.hash * this.hash % PALETTE.length) % PALETTE.length)];

			// Clear the canvas
			ctx.globalCompositeOperation = "source-over";
			ctx.clearRect(0, 0, c.width, c.height);
			ctx.globalCompositeOperation = "multiply";
		}

		// Applies an offset to the drawing to visually center it
		this.offset = function() {
			ctx.save();
			ctx.translate(0.6 * this.scale, - 0.6 * this.scale);
		}

		// Resets the offset
		this.resetOffset = function() {
			ctx.restore();
		}

		// Draws the heart outline
		this.drawOutline = function() {
			this.offset();

			// Outer lines
			ctx.beginPath();
			ctx.moveTo(this.margin * this.scale, this.margin * this.scale);
			ctx.lineTo(this.margin * this.scale, c.height - (this.margin * this.scale));
			ctx.lineTo(c.width - (this.margin * this.scale), c.height - (this.margin * this.scale));
			ctx.lineTo(c.width - (this.margin * this.scale), c.height / 2);
			ctx.lineTo(c.width / 2, c.height / 2);
			ctx.lineTo(c.width / 2, this.margin * this.scale);
			ctx.closePath();

			ctx.strokeStyle = 'black';
			ctx.lineWidth = this.scale * (500 / c.width);
			ctx.lineJoin = "round";
			ctx.lineCap = "round";
			ctx.stroke();

			// Inner lines
			ctx.beginPath();
			ctx.moveTo(c.width / 2, c.height / 2);
			ctx.lineTo(this.margin * this.scale, c.height / 2);
			ctx.moveTo(c.width / 2, c.height / 2);
			ctx.lineTo(c.width / 2, c.height - (this.margin * this.scale));

			ctx.stroke();

			this.resetOffset();
		}

		// Generates blocks
		this.generateBlocks = function() {
			var b1 = new Block(c, ctx, BlockType.ONE, this.primary, this.accent);
			b1.setHash(this.hash);
			b1.setPos({
				x: this.margin * this.scale,
				y: this.margin * this.scale
			});
			b1.setSizing(this.cellSize, this.margin, this.scale);
			this.blocks.push(b1);

			var b2 = new Block(c, ctx, BlockType.TWO, this.primary, this.accent);
			b2.setHash(this.hash);
			b2.setPos({
				x: this.margin * this.scale,
				y: c.height / 2
			});
			b2.setSizing(this.cellSize, this.margin, this.scale);
			this.blocks.push(b2);

			var b3 = new Block(c, ctx, BlockType.THREE, this.primary, this.accent);
			b3.setHash(this.hash);
			b3.setPos({
				x: c.width / 2,
				y: c.height / 2
			});
			b3.setSizing(this.cellSize, this.margin, this.scale);
			this.blocks.push(b3);
		}

		// Draws the generated blocks
		this.drawBlocks = function() {
			if (this.blocks.length == 0) {
				return false;
			}

			for (var i = 0; i < this.blocks.length; i++) {
				this.blocks[i].draw();
			}
		}
	};

	// Block type enum
	var BlockType = new function() {
		this.ONE = 1;
		this.TWO = 2;
		this.THREE = 3;
	};

	// Block class
	var Block = function(c, ctx, type, primary, accent) {
		// Type of block
		this.type = type;
		// Primary color
		this.primary = primary;
		// Accent color
		this.accent = accent;

		// Computed cell size
		this.cellSize;
		// Drawing margin
		this.margin;
		// Drawing scale
		this.scale;
		// Block position object
		this.pos;

		// Hashed username
		this.hash;

		// Hash setter
		this.setHash = function(hash) {
			this.hash = hash;
		}

		// Position setter
		this.setPos = function(pos) {
			this.pos = pos;
		}

		// Sizing setter
		this.setSizing = function(cell, marg, sc) {
			this.cellSize = cell;
			this.margin = marg;
			this.scale = sc;
		}

		// Applies an offset to the drawing
		this.offset = function() {
			ctx.save();
			ctx.translate(0.6 * this.scale, -0.6 * this.scale);
		}

		// Resets the offset
		this.resetOffset = function() {
			ctx.restore();
		}

		// Generates a path to draw in the block
		this.makePath = function(hash, offset) {
			var mod = Math.abs(hash + offset) % 4;

			switch(mod) {
				case 0:
					// top
					ctx.beginPath();
					ctx.moveTo(this.pos.x, this.pos.y);
					ctx.lineTo(this.pos.x + this.cellSize, this.pos.y);
					ctx.lineTo(this.pos.x + this.cellSize, this.pos.y + this.cellSize);
					ctx.closePath();
				break;
				case 1:
					// right
					ctx.beginPath();
					ctx.moveTo(this.pos.x + this.cellSize, this.pos.y);
					ctx.lineTo(this.pos.x + this.cellSize, this.pos.y + this.cellSize);
					ctx.lineTo(this.pos.x, this.pos.y + this.cellSize);
					ctx.closePath();
				break;
				case 2:
					// bottom
					ctx.beginPath();
					ctx.moveTo(this.pos.x, this.pos.y);
					ctx.lineTo(this.pos.x, this.pos.y + this.cellSize);
					ctx.lineTo(this.pos.x + this.cellSize, this.pos.y + this.cellSize);
					ctx.closePath();
				break;
				case 3:
					// left
					ctx.beginPath();
					ctx.moveTo(this.pos.x, this.pos.y);
					ctx.lineTo(this.pos.x + this.cellSize, this.pos.y);
					ctx.lineTo(this.pos.x, this.pos.y + this.cellSize);
					ctx.closePath();
				break;
				default:
					// top
					ctx.beginPath();
					ctx.moveTo(this.pos.x, this.pos.y);
					ctx.lineTo(this.pos.x + this.cellSize, this.pos.y);
					ctx.lineTo(this.pos.x, this.pos.y + this.cellSize);
					ctx.closePath();
				}
			}

		// Main draw function
		this.draw = function() {
			this.offset();

			if (this.type === BlockType.ONE) {
				this.makePath(this.hash, this.hash % 3);
				ctx.fillStyle = this.primary;
				ctx.fill();

				this.makePath(this.hash, this.hash % 5);
				ctx.fillStyle = this.accent;
				ctx.fill();
			} else if (this.type === BlockType.TWO) {
				this.makePath(this.hash, this.hash % 4);
				ctx.fillStyle = this.accent;
				ctx.fill();

				this.makePath(this.hash, this.hash % 3);
				ctx.fillStyle = this.primary;
				ctx.fill();
			} else {
				this.makePath(this.hash, this.hash % 7);
				ctx.fillStyle = this.accent;
				ctx.fill();

				this.makePath(this.hash, this.hash % 8);
				ctx.fillStyle = this.primary;
				ctx.fill();
			}

			this.resetOffset();
		}
	};

	// Shape class
	var Shape = function(c, ctx, hash, primary, accent, pos, scale, cellSize) {
		// Hashed username
		this.hash = hash;
		//Primary color
		this.primary = primary;
		// Accent color
		this.accent = accent;
		// Position object
		this.pos = pos;
		// Scale of the drawing
		this.scale = scale;
		// Computed cell size
		this.cellSize = cellSize;

		// Get a color from the hash
		this.getColor = function() {
			return [this.primary, this.accent][Math.abs(this.hash % 2)];
		}

		this.makePath = function() {
			var mod = Math.abs(this.hash + 1) % 4;

			switch(mod) {
				case 0:
					// square
					ctx.beginPath();
					ctx.moveTo(this.pos.x, this.pos.y);
					ctx.lineTo(this.pos.x + (this.cellSize / 2), this.pos.y);
					ctx.lineTo(this.pos.x + (this.cellSize / 2), this.pos.y - (this.cellSize / 2));
					ctx.lineTo(this.pos.x, this.pos.y - (this.cellSize / 2));
					ctx.closePath();
				break;
				case 1:
					//circle
					ctx.beginPath();
					ctx.arc(
						this.pos.x + (this.cellSize / Math.PI) - 5,
						this.pos.y - (this.cellSize / Math.PI) + 5,
						this.cellSize / 3,
						0,
						Math.PI * 2,
						true
					);
				break;
				case 2:
					// triangle
					ctx.beginPath();
					ctx.moveTo(this.pos.x, this.pos.y);
					ctx.lineTo(this.pos.x + (this.cellSize * 0.65), this.pos.y);
					ctx.lineTo(this.pos.x, this.pos.y - (this.cellSize * 0.65));
					ctx.closePath();
				break;
				case 3:
					// oval
					ctx.beginPath();
					ctx.moveTo(this.pos.x - (this.cellSize * 0.2), this.pos.y + (this.cellSize * 0.2));
					ctx.quadraticCurveTo(this.pos.x + (this.cellSize * 0.4), this.pos.y, this.pos.x + (this.cellSize * 0.5), this.pos.y - (this.cellSize * 0.5));
					ctx.moveTo(this.pos.x + (this.cellSize * 0.5), this.pos.y - (this.cellSize * 0.5));
					ctx.quadraticCurveTo(this.pos.x , this.pos.y - (this.cellSize * 0.4), this.pos.x - (this.cellSize * 0.2), this.pos.y + (this.cellSize * 0.2));
				break;
				default:
					//square
					ctx.beginPath();
					ctx.moveTo(this.pos.x, this.pos.y);
					ctx.lineTo(this.pos.x + (this.cellSize / 2), this.pos.y);
					ctx.lineTo(this.pos.x + (this.cellSize / 2), this.pos.y - (this.cellSize / 2));
					ctx.lineTo(this.pos.x, this.pos.y - (this.cellSize / 2));
					ctx.closePath();
				}
			}

		// Main draw function
		this.draw = function() {
			var color = this.getColor();

			this.makePath();
			ctx.fillStyle = color;
			ctx.strokeStyle = 'black';
			ctx.lineWidth = this.scale * (400 / c.width);
			ctx.lineJoin = "round";
			ctx.lineCap = "round";
			ctx.fill();
			ctx.stroke();
		}

	}
}());
<commit_msg>Added the possibility to specify a custom palette<commit_after>/*
 * === IdentiHeart ===
 * Author: Schlipak
 *
 * This library generates a canvas-based procedural
 * default profile picture. The generation is based
 * on the user's username, hashed into a unique string
 * to number representation.
 */
 (function() {
	// Hash generator
	var Crusher = function() {
		this.hash = function(s) {
			return s.split("").reduce(function(a, b) {
				a = ((a << 5) - a) + b.charCodeAt(0);
				return a & a
			}, 0);
		}
	}

	// ========================================= //
	// Class Heart
	Heart = function(c, ctx, margin, scale) {
		// Color palette
		var PALETTE = [
		'#F44336', '#E91E63', '#9C27B0', '#673AB7', '#3F51B5', '#2196F3',
		'#03A9F4', '#00BCD4', '#009688', '#4CAF50', '#8BC34A', '#CDDC39',
		'#FFEB3B', '#FFC107', '#FF9800', '#FF5722', '#795548', '#607D8B'
		];

		// Generated colors
		this.primary;
		this.accent;

		// Drawing margin
		this.margin = margin || 5;
		// Drawing scale
		this.scale = scale || 20;
		// Computed cell size
		this.cellSize = c.width - (this.margin * this.scale)  - c.width / 2;
		// Hashed username
		this.hash;
		// Generated blocks
		this.blocks;
		// Generated shape
		this.shape;

		// Hash setter
		this.setUsername = function(string) {
			var crusher = new Crusher();
			this.hash = crusher.hash(string);
		}

		this.setPalette = function(palette) {
			if (typeof palette !== typeof [] || palette.length === undefined) {
				console.warn('The palette must be an array of color values!');
			};

			if (palette.length > 2) {
				console.warn('The palette must contain at least two values!');
			};

			PALETTE = palette;
		}

		// Main draw function
		this.draw = function() {
			this.init();

			// Rotate the canvas -45deg
			ctx.save();
			ctx.translate(c.width/2, c.height/2);
			ctx.rotate(- Math.PI / 4);
			ctx.translate(-c.width/2, -c.height/2);

			this.generateBlocks();
			this.drawBlocks();
			this.drawOutline();

			this.shape = new Shape(c, ctx, this.hash, this.primary, this.accent, {
				x: (this.margin * this.scale) + 1.5 * this.cellSize,
				y: (this.margin * this.scale) + 0.5 * this.cellSize
			}, this.scale, this.cellSize);
			this.shape.draw();

			// Restore the original matrix
			ctx.restore();
		}

		// Initializes a few parameters and clears the canvas
		this.init = function() {
			// Purge the block array
			this.blocks = new Array();
			// Purge the shape
			this.shape = null;

			// Generate colors
			this.primary = PALETTE[Math.abs(this.hash % PALETTE.length)];
			this.accent = PALETTE[Math.abs((this.hash * this.hash % PALETTE.length) % PALETTE.length)];

			// Clear the canvas
			ctx.globalCompositeOperation = "source-over";
			ctx.clearRect(0, 0, c.width, c.height);
			ctx.globalCompositeOperation = "multiply";
		}

		// Applies an offset to the drawing to visually center it
		this.offset = function() {
			ctx.save();
			ctx.translate(0.6 * this.scale, - 0.6 * this.scale);
		}

		// Resets the offset
		this.resetOffset = function() {
			ctx.restore();
		}

		// Draws the heart outline
		this.drawOutline = function() {
			this.offset();

			// Outer lines
			ctx.beginPath();
			ctx.moveTo(this.margin * this.scale, this.margin * this.scale);
			ctx.lineTo(this.margin * this.scale, c.height - (this.margin * this.scale));
			ctx.lineTo(c.width - (this.margin * this.scale), c.height - (this.margin * this.scale));
			ctx.lineTo(c.width - (this.margin * this.scale), c.height / 2);
			ctx.lineTo(c.width / 2, c.height / 2);
			ctx.lineTo(c.width / 2, this.margin * this.scale);
			ctx.closePath();

			ctx.strokeStyle = 'black';
			ctx.lineWidth = this.scale * (500 / c.width);
			ctx.lineJoin = "round";
			ctx.lineCap = "round";
			ctx.stroke();

			// Inner lines
			ctx.beginPath();
			ctx.moveTo(c.width / 2, c.height / 2);
			ctx.lineTo(this.margin * this.scale, c.height / 2);
			ctx.moveTo(c.width / 2, c.height / 2);
			ctx.lineTo(c.width / 2, c.height - (this.margin * this.scale));

			ctx.stroke();

			this.resetOffset();
		}

		// Generates blocks
		this.generateBlocks = function() {
			var b1 = new Block(c, ctx, BlockType.ONE, this.primary, this.accent);
			b1.setHash(this.hash);
			b1.setPos({
				x: this.margin * this.scale,
				y: this.margin * this.scale
			});
			b1.setSizing(this.cellSize, this.margin, this.scale);
			this.blocks.push(b1);

			var b2 = new Block(c, ctx, BlockType.TWO, this.primary, this.accent);
			b2.setHash(this.hash);
			b2.setPos({
				x: this.margin * this.scale,
				y: c.height / 2
			});
			b2.setSizing(this.cellSize, this.margin, this.scale);
			this.blocks.push(b2);

			var b3 = new Block(c, ctx, BlockType.THREE, this.primary, this.accent);
			b3.setHash(this.hash);
			b3.setPos({
				x: c.width / 2,
				y: c.height / 2
			});
			b3.setSizing(this.cellSize, this.margin, this.scale);
			this.blocks.push(b3);
		}

		// Draws the generated blocks
		this.drawBlocks = function() {
			if (this.blocks.length == 0) {
				return false;
			}

			for (var i = 0; i < this.blocks.length; i++) {
				this.blocks[i].draw();
			}
		}
	};

	// Block type enum
	var BlockType = new function() {
		this.ONE = 1;
		this.TWO = 2;
		this.THREE = 3;
	};

	// Block class
	var Block = function(c, ctx, type, primary, accent) {
		// Type of block
		this.type = type;
		// Primary color
		this.primary = primary;
		// Accent color
		this.accent = accent;

		// Computed cell size
		this.cellSize;
		// Drawing margin
		this.margin;
		// Drawing scale
		this.scale;
		// Block position object
		this.pos;

		// Hashed username
		this.hash;

		// Hash setter
		this.setHash = function(hash) {
			this.hash = hash;
		}

		// Position setter
		this.setPos = function(pos) {
			this.pos = pos;
		}

		// Sizing setter
		this.setSizing = function(cell, marg, sc) {
			this.cellSize = cell;
			this.margin = marg;
			this.scale = sc;
		}

		// Applies an offset to the drawing
		this.offset = function() {
			ctx.save();
			ctx.translate(0.6 * this.scale, -0.6 * this.scale);
		}

		// Resets the offset
		this.resetOffset = function() {
			ctx.restore();
		}

		// Generates a path to draw in the block
		this.makePath = function(hash, offset) {
			var mod = Math.abs(hash + offset) % 4;

			switch(mod) {
				case 0:
					// top
					ctx.beginPath();
					ctx.moveTo(this.pos.x, this.pos.y);
					ctx.lineTo(this.pos.x + this.cellSize, this.pos.y);
					ctx.lineTo(this.pos.x + this.cellSize, this.pos.y + this.cellSize);
					ctx.closePath();
				break;
				case 1:
					// right
					ctx.beginPath();
					ctx.moveTo(this.pos.x + this.cellSize, this.pos.y);
					ctx.lineTo(this.pos.x + this.cellSize, this.pos.y + this.cellSize);
					ctx.lineTo(this.pos.x, this.pos.y + this.cellSize);
					ctx.closePath();
				break;
				case 2:
					// bottom
					ctx.beginPath();
					ctx.moveTo(this.pos.x, this.pos.y);
					ctx.lineTo(this.pos.x, this.pos.y + this.cellSize);
					ctx.lineTo(this.pos.x + this.cellSize, this.pos.y + this.cellSize);
					ctx.closePath();
				break;
				case 3:
					// left
					ctx.beginPath();
					ctx.moveTo(this.pos.x, this.pos.y);
					ctx.lineTo(this.pos.x + this.cellSize, this.pos.y);
					ctx.lineTo(this.pos.x, this.pos.y + this.cellSize);
					ctx.closePath();
				break;
				default:
					// top
					ctx.beginPath();
					ctx.moveTo(this.pos.x, this.pos.y);
					ctx.lineTo(this.pos.x + this.cellSize, this.pos.y);
					ctx.lineTo(this.pos.x, this.pos.y + this.cellSize);
					ctx.closePath();
				}
			}

		// Main draw function
		this.draw = function() {
			this.offset();

			if (this.type === BlockType.ONE) {
				this.makePath(this.hash, this.hash % 3);
				ctx.fillStyle = this.primary;
				ctx.fill();

				this.makePath(this.hash, this.hash % 5);
				ctx.fillStyle = this.accent;
				ctx.fill();
			} else if (this.type === BlockType.TWO) {
				this.makePath(this.hash, this.hash % 4);
				ctx.fillStyle = this.accent;
				ctx.fill();

				this.makePath(this.hash, this.hash % 3);
				ctx.fillStyle = this.primary;
				ctx.fill();
			} else {
				this.makePath(this.hash, this.hash % 7);
				ctx.fillStyle = this.accent;
				ctx.fill();

				this.makePath(this.hash, this.hash % 8);
				ctx.fillStyle = this.primary;
				ctx.fill();
			}

			this.resetOffset();
		}
	};

	// Shape class
	var Shape = function(c, ctx, hash, primary, accent, pos, scale, cellSize) {
		// Hashed username
		this.hash = hash;
		//Primary color
		this.primary = primary;
		// Accent color
		this.accent = accent;
		// Position object
		this.pos = pos;
		// Scale of the drawing
		this.scale = scale;
		// Computed cell size
		this.cellSize = cellSize;

		// Get a color from the hash
		this.getColor = function() {
			return [this.primary, this.accent][Math.abs(this.hash % 2)];
		}

		this.makePath = function() {
			var mod = Math.abs(this.hash + 1) % 4;

			switch(mod) {
				case 0:
					// square
					ctx.beginPath();
					ctx.moveTo(this.pos.x, this.pos.y);
					ctx.lineTo(this.pos.x + (this.cellSize / 2), this.pos.y);
					ctx.lineTo(this.pos.x + (this.cellSize / 2), this.pos.y - (this.cellSize / 2));
					ctx.lineTo(this.pos.x, this.pos.y - (this.cellSize / 2));
					ctx.closePath();
				break;
				case 1:
					//circle
					ctx.beginPath();
					ctx.arc(
						this.pos.x + (this.cellSize / Math.PI) - 5,
						this.pos.y - (this.cellSize / Math.PI) + 5,
						this.cellSize / 3,
						0,
						Math.PI * 2,
						true
					);
				break;
				case 2:
					// triangle
					ctx.beginPath();
					ctx.moveTo(this.pos.x, this.pos.y);
					ctx.lineTo(this.pos.x + (this.cellSize * 0.65), this.pos.y);
					ctx.lineTo(this.pos.x, this.pos.y - (this.cellSize * 0.65));
					ctx.closePath();
				break;
				case 3:
					// oval
					ctx.beginPath();
					ctx.moveTo(this.pos.x - (this.cellSize * 0.2), this.pos.y + (this.cellSize * 0.2));
					ctx.quadraticCurveTo(this.pos.x + (this.cellSize * 0.4), this.pos.y, this.pos.x + (this.cellSize * 0.5), this.pos.y - (this.cellSize * 0.5));
					ctx.moveTo(this.pos.x + (this.cellSize * 0.5), this.pos.y - (this.cellSize * 0.5));
					ctx.quadraticCurveTo(this.pos.x , this.pos.y - (this.cellSize * 0.4), this.pos.x - (this.cellSize * 0.2), this.pos.y + (this.cellSize * 0.2));
				break;
				default:
					//square
					ctx.beginPath();
					ctx.moveTo(this.pos.x, this.pos.y);
					ctx.lineTo(this.pos.x + (this.cellSize / 2), this.pos.y);
					ctx.lineTo(this.pos.x + (this.cellSize / 2), this.pos.y - (this.cellSize / 2));
					ctx.lineTo(this.pos.x, this.pos.y - (this.cellSize / 2));
					ctx.closePath();
				}
			}

		// Main draw function
		this.draw = function() {
			var color = this.getColor();

			this.makePath();
			ctx.fillStyle = color;
			ctx.strokeStyle = 'black';
			ctx.lineWidth = this.scale * (400 / c.width);
			ctx.lineJoin = "round";
			ctx.lineCap = "round";
			ctx.fill();
			ctx.stroke();
		}

	}
}());
<|endoftext|>


<commit_before>
// require local dependencies
const bar         = require ('nanobar');
const riot        = require ('riot');
const socket      = require ('socket/public/js/bootstrap');
const history     = require ('history').createBrowserHistory;
const riotcontrol = require ('riotcontrol');

// get local dependencies
const store = require ('./store');

// require tags
require ('app/cache/tags.min');

/**
 * build bootstrap class
 */
class router {
  /**
   * construct bootstrap class
   */
  constructor () {
    // set mount
    this._bar   = false;
    this._mount = false;
    this._store = store;

    // add store to riotcontrol
    riotcontrol.addStore (this._store);

    // set store values
    for (var key in window.eden) {
      // set to store
      this._store.set (key, window.eden[key]);
    }

    // create history
    this.history = history ();

    // bind methods
    this.go         = this.go.bind (this);
    this.load       = this.load.bind (this);
    this.submit     = this.submit.bind (this);
    this.update     = this.update.bind (this);
    this.initialize = this.initialize.bind (this);

    // bind private methods
    this._tags   = this._tags.bind (this);
    this._form   = this._form.bind (this);
    this._route  = this._route.bind (this);
    this._layout = this._layout.bind (this);

    // on state
    socket.on ('state', this.update);

    // run on document ready
    window.addEventListener ('load', () => {
      // push state
      this.history.replace ({
        'state' : {
          'page'  : this._store.get ('page'),
          'state' : this._store.get ('state'),
          'mount' : this._store.get ('mount')
        },
        'pathname' : this._store.get ('page').url
      });

      // initialize
      this.initialize ();
    });
  }

  /**
   * initialize functionality
   */
  initialize () {
    // set that
    let that = this;

    // mount bar
    this._bar = new bar ();

    // mount riot tag
    this._mount = riot.mount (document.querySelector ('body').children[0], window.eden)[0];

    // listen to go
    this._store.on ('navigate', this.go);

    // run on document ready
    jQuery (document).on ('click', 'a[href^="/"]', function (e) {
      // check target
      if (this.getAttribute ('target') && this.getAttribute ('target').toLowerCase () === '_blank') return true;

      // check link
      if (that._route (this.getAttribute ('href'))) {
        // prevent default
        e.preventDefault  ();
        e.stopPropagation ();
      }
    });

    // run on form submit
    jQuery (document).on ('submit', 'form', function (e) {
      // check form
      if (that._form (this)) {
        // prevent default
        e.preventDefault  ();
        e.stopPropagation ();
      }
    });

    // on state change
    this.history.listen ((location) => {
      // scroll to top
      window.scrollTo (0, 0);

      // check state
      if (location.state && Object.keys (location.state).length > 0) {
        // set progress go
        this._bar.go (100);

        // set title
        document.title = (location.state.page.title ? location.state.page.title + ' | ' : '') + this._store.get ('config').title;

        // trigger
        for (var key in location.state) {
          // set data
          this._store.set (key, location.state[key]);
        }

        // check layout
        this._layout (location.state);

        // check tags
        this._tags (location.state.page);

        // do route
        // we do this as a seperate trigger to prevent double rendering
        // the riot layout (seperate mount and state events still fired)
        this._store.trigger ('route', {
          'mount' : location.state.mount,
          'state' : location.state.state
        });
      }
    });
  }

  /**
   * loads url
   *
   * @param  {String} url
   */
  async go (url) {
    // progress bar
    this._bar.go (50);

    // check route
    if (url.indexOf ('//') > -1 || url.indexOf ('#') === 0) {
      // timeout bar go
      setTimeout (() => this._bar.go (50), 2000);

      // return url
      return window.location = url;
    }

    // create location
    this.history.push ({
      'state'    : {},
      'pathname' : url
    });

    // check if ajax
    if (url.indexOf ('/ajx') !== 0) {
      url = '/ajx' + url;
    }

    // load json from url
    let res = await fetch (url, {
      'credentials' : 'same-origin'
    });

    // load json
    this.load (await res.json ());
  }

  /**
   * load data
   *
   * @param {Object} data
   */
  load (data) {
    // check if redirect
    if (data.redirect) {
      // do next route
      if (this._route (data.redirect)) return;

      // redirect
      window.location = data.redirect;
    }

    // push state
    this.history.replace ({
      'state'    : data,
      'pathname' : data.mount.url
    });
  }

  /**
   * submits form via ajax
   *
   * @param {HTMLElement} form
   */
  async submit (form) {
    // get url
    let url = form.getAttribute ('action') || window.location.href.split (this._store.get ('config').domain)[1];

    // set request
    let opts = {
      'method'      : form.getAttribute ('method') || 'POST',
      'credentials' : 'same-origin'
    };

    // set body
    if (opts.method.toUpperCase () === 'POST') {
      // set to body
      opts.body = new FormData (form);
    } else {
      // add to url
      url += '?' + jQuery (form).serialize ();
    }

    // create location
    this.history.push ({
      'state'    : {},
      'pathname' : url
    });

    // check if ajax
    if (url.indexOf ('/ajx') !== 0) {
      url = '/ajx' + url;
    }

    // run fetch
    let res = await fetch (url, opts);

    // run json
    this.load (await res.json ());
  }

  /**
   * updates page state
   *
   * @param  {Object} state
   */
  update (state) {
    // let old
    let old = {
      'state' : {
        'page'  : this._store.get ('page'),
        'state' : this._store.get ('state'),
        'mount' : this._store.get ('mount')
      },
      'pathname' : this._store.get ('mount').url
    };

    // check pathname
    if (old.pathname === state.url) {
      // check url
      if (state.opts.mount && state.opts.mount.url) old.pathname = state.opts.mount.url;

      // replace state object
      ['page', 'state', 'mount'].forEach ((type) => {
        // skip type
        if (!state.opts[type]) return;

        // set in store
        for (var key in state.opts[type]) {
          // update state
          old.state[type][key] = state.opts[type][key];
        }

        // set state
        this._store.set ('type', old.state[type]);
      });

      // push state
      this.history.replace (old);
    }
  }

  /**
   * replace head tags from state
   *
   * @param {Object} state
   *
   * @private
   */
  _tags (page) {
    // check head
    if (!page.head) return;

    // set header information
    let found   = false;
    let newHead = jQuery (page.head);
    let nowHead = jQuery ('[data-eden="head"]').nextAll ('*');

    // loop all elements
    for (var a = 0; a < nowHead.length; a++) {
      // check now head
      found = false;

      // loop now head
      for (var b = 0; b < newHead.length; b++) {
        // check if found
        if (nowHead[a].outerHTML === newHead[b].outerHTML) {
          // set found
          found = true;
        }
      }

      // remove if not found
      if (!found) jQuery (nowHead[a]).remove ();
    }

    // loop all new elements
    for (var c = 0; c < newHead.length; c++) {
      // check now head
      found = false;

      // loop now head
      for (var d = 0; d < nowHead.length; d++) {
        // check if found
        if (newHead[c].outerHTML === nowHead[d].outerHTML) {
          // set found
          found = true;
        }
      }

      // remove if not found
      if (!found) jQuery ('head').append (newHead[c]);
    }
  }

  /**
   * submits form via ajax
   *
   * @param {HTMLElement} form
   *
   * @private
   * @return {Boolean}
   */
  _form (form) {
    // get form url
    let url = form.getAttribute ('action') || window.location.href.split (this._store.get ('config').domain)[1];

    // check if actual redirect
    if (url.indexOf ('//') > -1 || url.indexOf ('#') === 0) {
      // return
      return false;
    }

    // submit form
    this.submit (form);

    // return true
    return true;
  }

  /**
   * redirects to url
   *
   * @param  {String} url
   *
   * @private
   * @return {Boolean}
   */
  _route (url) {
    // check if actual redirect
    if (url.indexOf ('//') > -1 || url.indexOf ('#') === 0) return false;

    // check file
    if (url.split ('/').pop ().split ('.').length > 1) return false;

    // load next redirect
    this.go (url);

    // return true
    return true;
  }

  /**
   * checks for correct layout
   *
   * @param  {Object} state
   *
   * @private
   * @return {Boolean}
   */
  _layout (state) {
    // set layout variable
    let layout = (state.mount.layout || 'main-layout');

    // get current layout
    let current = document.querySelector ('body').children[0];

    // check if layout needs replacing
    if (current.tagName.toLowerCase () === layout.toLowerCase ()) {
      return false;
    }

    // unmount tag
    this._mount.unmount (true);

    // replace with
    jQuery (current).replaceWith (document.createElement (layout));

    // mount new tag
    this._mount = riot.mount (document.querySelector ('body').children[0], state)[0];

    // return true
    return true;
  }
}

/**
 * export new bootstrap function
 *
 * @return {bootstrap}
 */
exports = module.exports = window.eden.router = new router ();
<commit_msg>add timeout for bar to go to 100% when no page is loaded<commit_after>
// require local dependencies
const bar         = require ('nanobar');
const riot        = require ('riot');
const socket      = require ('socket/public/js/bootstrap');
const history     = require ('history').createBrowserHistory;
const riotcontrol = require ('riotcontrol');

// get local dependencies
const store = require ('./store');

// require tags
require ('app/cache/tags.min');

/**
 * build bootstrap class
 */
class router {
  /**
   * construct bootstrap class
   */
  constructor () {
    // set mount
    this._bar   = false;
    this._mount = false;
    this._store = store;

    // add store to riotcontrol
    riotcontrol.addStore (this._store);

    // set store values
    for (var key in window.eden) {
      // set to store
      this._store.set (key, window.eden[key]);
    }

    // create history
    this.history = history ();

    // bind methods
    this.go         = this.go.bind (this);
    this.load       = this.load.bind (this);
    this.submit     = this.submit.bind (this);
    this.update     = this.update.bind (this);
    this.initialize = this.initialize.bind (this);

    // bind private methods
    this._tags   = this._tags.bind (this);
    this._form   = this._form.bind (this);
    this._route  = this._route.bind (this);
    this._layout = this._layout.bind (this);

    // on state
    socket.on ('state', this.update);

    // run on document ready
    window.addEventListener ('load', () => {
      // push state
      this.history.replace ({
        'state' : {
          'page'  : this._store.get ('page'),
          'state' : this._store.get ('state'),
          'mount' : this._store.get ('mount')
        },
        'pathname' : this._store.get ('page').url
      });

      // initialize
      this.initialize ();
    });
  }

  /**
   * initialize functionality
   */
  initialize () {
    // set that
    let that = this;

    // mount bar
    this._bar = new bar ();

    // mount riot tag
    this._mount = riot.mount (document.querySelector ('body').children[0], window.eden)[0];

    // listen to go
    this._store.on ('navigate', this.go);

    // run on document ready
    jQuery (document).on ('click', 'a[href^="/"]', function (e) {
      // check target
      if (this.getAttribute ('target') && this.getAttribute ('target').toLowerCase () === '_blank') return true;

      // check link
      if (that._route (this.getAttribute ('href'))) {
        // prevent default
        e.preventDefault  ();
        e.stopPropagation ();
      }
    });

    // run on form submit
    jQuery (document).on ('submit', 'form', function (e) {
      // check form
      if (that._form (this)) {
        // prevent default
        e.preventDefault  ();
        e.stopPropagation ();
      }
    });

    // on state change
    this.history.listen ((location) => {
      // scroll to top
      window.scrollTo (0, 0);

      // check state
      if (location.state && Object.keys (location.state).length > 0) {
        // set progress go
        this._bar.go (100);

        // set title
        document.title = (location.state.page.title ? location.state.page.title + ' | ' : '') + this._store.get ('config').title;

        // trigger
        for (var key in location.state) {
          // set data
          this._store.set (key, location.state[key]);
        }

        // check layout
        this._layout (location.state);

        // check tags
        this._tags (location.state.page);

        // do route
        // we do this as a seperate trigger to prevent double rendering
        // the riot layout (seperate mount and state events still fired)
        this._store.trigger ('route', {
          'mount' : location.state.mount,
          'state' : location.state.state
        });
      }
    });
  }

  /**
   * loads url
   *
   * @param  {String} url
   */
  async go (url) {
    // progress bar
    this._bar.go (50);

    // check route
    if (url.indexOf ('//') > -1 || url.indexOf ('#') === 0) {
      // timeout bar go
      setTimeout (() => {
        // complete bar after 1 second
        this._bar.go (100);
      }, 1000);

      // return url
      return window.location = url;
    }

    // create location
    this.history.push ({
      'state'    : {},
      'pathname' : url
    });

    // check if ajax
    if (url.indexOf ('/ajx') !== 0) {
      url = '/ajx' + url;
    }

    // load json from url
    let res = await fetch (url, {
      'credentials' : 'same-origin'
    });

    // load json
    this.load (await res.json ());
  }

  /**
   * load data
   *
   * @param {Object} data
   */
  load (data) {
    // check if redirect
    if (data.redirect) {
      // do next route
      if (this._route (data.redirect)) return;

      // redirect
      window.location = data.redirect;
    }

    // push state
    this.history.replace ({
      'state'    : data,
      'pathname' : data.mount.url
    });
  }

  /**
   * submits form via ajax
   *
   * @param {HTMLElement} form
   */
  async submit (form) {
    // get url
    let url = form.getAttribute ('action') || window.location.href.split (this._store.get ('config').domain)[1];

    // set request
    let opts = {
      'method'      : form.getAttribute ('method') || 'POST',
      'credentials' : 'same-origin'
    };

    // set body
    if (opts.method.toUpperCase () === 'POST') {
      // set to body
      opts.body = new FormData (form);
    } else {
      // add to url
      url += '?' + jQuery (form).serialize ();
    }

    // create location
    this.history.push ({
      'state'    : {},
      'pathname' : url
    });

    // check if ajax
    if (url.indexOf ('/ajx') !== 0) {
      url = '/ajx' + url;
    }

    // run fetch
    let res = await fetch (url, opts);

    // run json
    this.load (await res.json ());
  }

  /**
   * updates page state
   *
   * @param  {Object} state
   */
  update (state) {
    // let old
    let old = {
      'state' : {
        'page'  : this._store.get ('page'),
        'state' : this._store.get ('state'),
        'mount' : this._store.get ('mount')
      },
      'pathname' : this._store.get ('mount').url
    };

    // check pathname
    if (old.pathname === state.url) {
      // check url
      if (state.opts.mount && state.opts.mount.url) old.pathname = state.opts.mount.url;

      // replace state object
      ['page', 'state', 'mount'].forEach ((type) => {
        // skip type
        if (!state.opts[type]) return;

        // set in store
        for (var key in state.opts[type]) {
          // update state
          old.state[type][key] = state.opts[type][key];
        }

        // set state
        this._store.set ('type', old.state[type]);
      });

      // push state
      this.history.replace (old);
    }
  }

  /**
   * replace head tags from state
   *
   * @param {Object} state
   *
   * @private
   */
  _tags (page) {
    // check head
    if (!page.head) return;

    // set header information
    let found   = false;
    let newHead = jQuery (page.head);
    let nowHead = jQuery ('[data-eden="head"]').nextAll ('*');

    // loop all elements
    for (var a = 0; a < nowHead.length; a++) {
      // check now head
      found = false;

      // loop now head
      for (var b = 0; b < newHead.length; b++) {
        // check if found
        if (nowHead[a].outerHTML === newHead[b].outerHTML) {
          // set found
          found = true;
        }
      }

      // remove if not found
      if (!found) jQuery (nowHead[a]).remove ();
    }

    // loop all new elements
    for (var c = 0; c < newHead.length; c++) {
      // check now head
      found = false;

      // loop now head
      for (var d = 0; d < nowHead.length; d++) {
        // check if found
        if (newHead[c].outerHTML === nowHead[d].outerHTML) {
          // set found
          found = true;
        }
      }

      // remove if not found
      if (!found) jQuery ('head').append (newHead[c]);
    }
  }

  /**
   * submits form via ajax
   *
   * @param {HTMLElement} form
   *
   * @private
   * @return {Boolean}
   */
  _form (form) {
    // get form url
    let url = form.getAttribute ('action') || window.location.href.split (this._store.get ('config').domain)[1];

    // check if actual redirect
    if (url.indexOf ('//') > -1 || url.indexOf ('#') === 0) {
      // return
      return false;
    }

    // submit form
    this.submit (form);

    // return true
    return true;
  }

  /**
   * redirects to url
   *
   * @param  {String} url
   *
   * @private
   * @return {Boolean}
   */
  _route (url) {
    // check if actual redirect
    if (url.indexOf ('//') > -1 || url.indexOf ('#') === 0) return false;

    // check file
    if (url.split ('/').pop ().split ('.').length > 1) return false;

    // load next redirect
    this.go (url);

    // return true
    return true;
  }

  /**
   * checks for correct layout
   *
   * @param  {Object} state
   *
   * @private
   * @return {Boolean}
   */
  _layout (state) {
    // set layout variable
    let layout = (state.mount.layout || 'main-layout');

    // get current layout
    let current = document.querySelector ('body').children[0];

    // check if layout needs replacing
    if (current.tagName.toLowerCase () === layout.toLowerCase ()) {
      return false;
    }

    // unmount tag
    this._mount.unmount (true);

    // replace with
    jQuery (current).replaceWith (document.createElement (layout));

    // mount new tag
    this._mount = riot.mount (document.querySelector ('body').children[0], state)[0];

    // return true
    return true;
  }
}

/**
 * export new bootstrap function
 *
 * @return {bootstrap}
 */
exports = module.exports = window.eden.router = new router ();
<|endoftext|>


<commit_before>/*
 * Copyright 2014, Gregg Tavares.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Gregg Tavares. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
"use strict";

define(function() {
  console.log(
    [ "%c",
      "---------------------------------------------------------------------------------------------",
      "If you'd like to know more about this code check out http://greggman.github.io/HappyFunTimes/",
      "---------------------------------------------------------------------------------------------",
      "",
    ].join("\n"), "color:blue; font-weight: bold;");

  return {
  };
});

<commit_msg>update link in console<commit_after>/*
 * Copyright 2014, Gregg Tavares.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Gregg Tavares. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
"use strict";

define(function() {
  console.log(
    [ "%c",
      "---------------------------------------------------------------------------------------------",
      "If you'd like to know more about this sytem check out http://docs.happyfuntimes.net/docs",
      "---------------------------------------------------------------------------------------------",
      "",
    ].join("\n"), "color:blue; font-weight: bold;");

  return {
  };
});

<|endoftext|>


<commit_before>var os = require('os');
var path = require('path');
var programFiles = os.arch() === "x64" ? process.env["ProgramFiles(x86)"] : process.env.ProgramFiles;
var cwd = path.dirname(programFiles);
var appData = appData || process.env.APPDATA;

module.exports = {
  chrome: {
    defaultLocation: path.join(appData, 'Google', 'Chrome', 'Application', 'chrome.exe') ,
    pathQuery: 'dir /s /b chrome.exe',
    cwd: cwd,
    opensTab: true
  },
  canary: {
    defaultLocation: path.join(appData, 'Google', 'Chrome SxS', 'Application', 'chrome.exe')
  },
  firefox: {
    defaultLocation: path.join(programFiles, 'Mozilla Firefox', 'firefox.exe'),
    pathQuery: 'dir /s /b firefox.exe',
    cwd: cwd,
    opensTab: true
  },
  aurora: {
    defaultLocation: path.join(programFiles, 'Aurora', 'firefox.exe'),
    opensTab: true
  },
  opera: {
    defaultLocation: path.join(programFiles, 'Opera', 'launcher.exe'),
    pathQuery: 'dir /s /b opera.exe',
    cwd: cwd,
    imageName: 'opera.exe',
    opensTab: true
  },
  ie: {
    defaultLocation: path.join(programFiles, 'Internet Explorer', 'iexplore.exe'),
    pathQuery: 'dir /s /b iexplore.exe',
    cwd: cwd
  },
  phantomjs: {
    pathQuery: 'dir /s /b phantomjs.exe',
    args: [path.join(__dirname, '..', '..', '..', 'resources/phantom.js')],
    multi: true,
    cwd: cwd
  },
  nodeWebkit: {
    pathQuery: 'dir /s /b nw.exe',
    multi: true,
    cwd: cwd,
    imageName: 'nw.exe',
    getCommand: function(browser, url) {
      var app = process.cwd();
      return '"' + browser.command + '" ' + app + ' --url="' + url + '"';
    }
  }
};
<commit_msg>Fixing PhantomJS name and setting default location for Windows.<commit_after>var os = require('os');
var path = require('path');
var programFiles = os.arch() === "x64" ? process.env["ProgramFiles(x86)"] : process.env.ProgramFiles;
var cwd = path.dirname(programFiles);
var appData = appData || process.env.APPDATA;

module.exports = {
  chrome: {
    defaultLocation: path.join(appData, 'Google', 'Chrome', 'Application', 'chrome.exe') ,
    pathQuery: 'dir /s /b chrome.exe',
    cwd: cwd,
    opensTab: true
  },
  canary: {
    defaultLocation: path.join(appData, 'Google', 'Chrome SxS', 'Application', 'chrome.exe')
  },
  firefox: {
    defaultLocation: path.join(programFiles, 'Mozilla Firefox', 'firefox.exe'),
    pathQuery: 'dir /s /b firefox.exe',
    cwd: cwd,
    opensTab: true
  },
  aurora: {
    defaultLocation: path.join(programFiles, 'Aurora', 'firefox.exe'),
    opensTab: true
  },
  opera: {
    defaultLocation: path.join(programFiles, 'Opera', 'launcher.exe'),
    pathQuery: 'dir /s /b opera.exe',
    cwd: cwd,
    imageName: 'opera.exe',
    opensTab: true
  },
  ie: {
    defaultLocation: path.join(programFiles, 'Internet Explorer', 'iexplore.exe'),
    pathQuery: 'dir /s /b iexplore.exe',
    cwd: cwd
  },
  phantom: {
    defaultLocation: path.join(programFiles, 'phantomjs', 'phantomjs.exe'),
    pathQuery: 'dir /s /b phantomjs.exe',
    args: [path.join(__dirname, '..', '..', '..', 'resources/phantom.js')],
    multi: true,
    cwd: cwd
  },
  nodeWebkit: {
    pathQuery: 'dir /s /b nw.exe',
    multi: true,
    cwd: cwd,
    imageName: 'nw.exe',
    getCommand: function(browser, url) {
      var app = process.cwd();
      return '"' + browser.command + '" ' + app + ' --url="' + url + '"';
    }
  }
};
<|endoftext|>


<commit_before>/* @flow */

import 'babel-polyfill'
import path from 'path'

import DiCy from '../../src/DiCy'
import MakeIndex from '../../src/Rules/MakeIndex'

describe('MakeIndex', () => {
  const fixturesPath = path.resolve(__dirname, '..', 'fixtures')
  let builder: DiCy
  let rule: MakeIndex

  async function initialize (parameterPaths: Array<string>, options: Object = {}) {
    options.ignoreHomeOptions = true
    builder = await DiCy.create(path.resolve(fixturesPath, 'file-types', 'LaTeX_article.tex'), options)
    const parameters = await builder.getFiles(parameterPaths)
    rule = new MakeIndex(builder.state, 'build', 'execute', null, ...parameters)
  }

  describe('constructCommand', () => {
    it('returns correct arguments and command options for index file.', async (done) => {
      await initialize(['IndexControlFile.idx'])

      expect(rule.constructCommand()).toEqual({
        args: [
          'makeindex',
          '-t',
          '$DIR_0/$NAME_0.ilg',
          '-o',
          '$DIR_0/$NAME_0.ind',
          '$DIR_0/$BASE_0'
        ],
        cd: '$ROOTDIR',
        severity: 'error',
        inputs: ['$DIR_0/$NAME_0.ilg-ParsedMakeIndexLog'],
        outputs: ['$DIR_0/$NAME_0.ind', '$DIR_0/$NAME_0.ilg']
      })

      done()
    })

    it('returns correct arguments and command options for nomenclature file.', async (done) => {
      await initialize(['NomenclatureControlFile.nlo'])

      expect(rule.constructCommand()).toEqual({
        args: [
          'makeindex',
          '-t',
          '$DIR_0/$NAME_0.nlg',
          '-o',
          '$DIR_0/$NAME_0.nls',
          '-s',
          'nomencl.ist',
          '$DIR_0/$BASE_0'
        ],
        cd: '$ROOTDIR',
        severity: 'error',
        inputs: ['$DIR_0/$NAME_0.nlg-ParsedMakeIndexLog'],
        outputs: ['$DIR_0/$NAME_0.nls', '$DIR_0/$NAME_0.nlg']
      })

      done()
    })

    it('returns correct arguments and command options for bibref file.', async (done) => {
      await initialize(['BibRefControlFile.bdx'])

      expect(rule.constructCommand()).toEqual({
        args: [
          'makeindex',
          '-t',
          '$DIR_0/$NAME_0.brlg',
          '-o',
          '$DIR_0/$NAME_0.bnd',
          '-s',
          'bibref.ist',
          '$DIR_0/$BASE_0'
        ],
        cd: '$ROOTDIR',
        severity: 'error',
        inputs: ['$DIR_0/$NAME_0.brlg-ParsedMakeIndexLog'],
        outputs: ['$DIR_0/$NAME_0.bnd', '$DIR_0/$NAME_0.brlg']
      })

      done()
    })

    it('add -c to command line when MakeIndex_compressBlanks is enabled.', async (done) => {
      await initialize(['IndexControlFile.idx'], { MakeIndex_compressBlanks: true })

      expect(rule.constructCommand().args).toContain('-c')

      done()
    })

    it('add -l to command line when MakeIndex_ordering is set to \'letter\'.', async (done) => {
      await initialize(['IndexControlFile.idx'], { MakeIndex_ordering: 'letter' })

      expect(rule.constructCommand().args).toContain('-l')

      done()
    })

    it('add -g to command line when MakeIndex_sorting is set to \'german\'.', async (done) => {
      await initialize(['IndexControlFile.idx'], { MakeIndex_sorting: 'german' })

      expect(rule.constructCommand().args).toContain('-g')

      done()
    })

    it('add -T to command line when MakeIndex_sorting is set to \'thai\'.', async (done) => {
      await initialize(['IndexControlFile.idx'], { MakeIndex_sorting: 'thai' })

      expect(rule.constructCommand().args).toContain('-T')

      done()
    })

    it('add -L to command line when MakeIndex_sorting is set to \'locale\'.', async (done) => {
      await initialize(['IndexControlFile.idx'], { MakeIndex_sorting: 'locale' })

      expect(rule.constructCommand().args).toContain('-L')

      done()
    })

    it('add -r to command line when MakeIndex_automaticRanges is disabled.', async (done) => {
      await initialize(['IndexControlFile.idx'], { MakeIndex_automaticRanges: false })

      expect(rule.constructCommand().args).toContain('-r')

      done()
    })

    it('add -p to command line when MakeIndex_startPage is set.', async (done) => {
      await initialize(['IndexControlFile.idx'], { MakeIndex_startPage: 'odd' })

      expect(rule.constructCommand().args).toEqual(jasmine.arrayContaining(['-p', 'odd']))

      done()
    })

    it('add -s to command line when MakeIndex_style is set.', async (done) => {
      await initialize(['IndexControlFile.idx'], { MakeIndex_style: 'foo.ist' })

      expect(rule.constructCommand().args).toEqual(jasmine.arrayContaining(['-s', 'foo.ist']))

      done()
    })
  })
})
<commit_msg>Add more specs<commit_after>/* @flow */

import 'babel-polyfill'
import path from 'path'

import DiCy from '../../src/DiCy'
import MakeIndex from '../../src/Rules/MakeIndex'

describe('MakeIndex', () => {
  const fixturesPath = path.resolve(__dirname, '..', 'fixtures')
  let builder: DiCy
  let rule: MakeIndex

  async function initialize (parameterPaths: Array<string>, options: Object = {}) {
    options.ignoreHomeOptions = true
    builder = await DiCy.create(path.resolve(fixturesPath, 'file-types', 'LaTeX_article.tex'), options)
    const parameters = await builder.getFiles(parameterPaths)
    rule = new MakeIndex(builder.state, 'build', 'execute', null, ...parameters)
  }

  describe('appliesToParameters', () => {
    beforeEach(async (done) => {
      await initialize(['IndexControlFile.idx', 'LaTeX.log-ParsedLaTeXLog'])
      done()
    })

    it('returns true if there are no splitindex notices in the log.', async (done) => {
      rule.secondParameter.value = {
        inputs: [],
        outputs: [],
        messages: [],
        calls: []
      }

      expect(await MakeIndex.appliesToParameters(builder.state, 'build', 'execute', null, ...rule.parameters)).toBe(true)

      done()
    })

    it('returns false if there are splitindex notices in the log.', async (done) => {
      rule.secondParameter.value = {
        inputs: [],
        outputs: [],
        messages: [{
          severity: 'info',
          text: 'Using splitted index at IndexControlFile.idx'
        }],
        calls: []
      }

      expect(await MakeIndex.appliesToParameters(builder.state, 'build', 'execute', null, ...rule.parameters)).toBe(false)

      done()
    })

    it('returns false if there are splitindex calls in the log.', async (done) => {
      rule.secondParameter.value = {
        inputs: [],
        outputs: [],
        messages: [],
        calls: [{
          command: 'splitindex -m \'\' IndexControlFile.idx',
          status: 'executed (allowed)'
        }]
      }

      expect(await MakeIndex.appliesToParameters(builder.state, 'build', 'execute', null, ...rule.parameters)).toBe(false)

      done()
    })
  })

  describe('getFileActions', () => {
    beforeEach(async (done) => {
      await initialize(['IndexControlFile.idx', 'LaTeX.log-ParsedLaTeXLog'])
      done()
    })

    it('returns a run action for a index control file.', async (done) => {
      const file = await builder.getFile('IndexControlFile.idx')
      if (file) {
        const actions = await rule.getFileActions(file)
        expect(actions).toEqual(['run'])
      }

      done()
    })

    it('returns a updateDependencies action for a makeindex log file.', async (done) => {
      const file = await builder.getFile('IndexControlFile.ilg-ParsedMakeIndexLog')
      if (file) {
        const actions = await rule.getFileActions(file)
        expect(actions).toEqual(['updateDependencies'])
      }

      done()
    })

    it('returns a no actions for a latex log file.', async (done) => {
      const file = await builder.getFile('LaTeX.log-ParsedLaTeXLog')
      if (file) {
        const actions = await rule.getFileActions(file)
        expect(actions).toEqual([])
      }

      done()
    })
  })

  describe('constructCommand', () => {
    it('returns correct arguments and command options for index file.', async (done) => {
      await initialize(['IndexControlFile.idx', 'LaTeX.log-ParsedLaTeXLog'])

      expect(rule.constructCommand()).toEqual({
        args: [
          'makeindex',
          '-t',
          '$DIR_0/$NAME_0.ilg',
          '-o',
          '$DIR_0/$NAME_0.ind',
          '$DIR_0/$BASE_0'
        ],
        cd: '$ROOTDIR',
        severity: 'error',
        inputs: ['$DIR_0/$NAME_0.ilg-ParsedMakeIndexLog'],
        outputs: ['$DIR_0/$NAME_0.ind', '$DIR_0/$NAME_0.ilg']
      })

      done()
    })

    it('returns correct arguments and command options for nomenclature file.', async (done) => {
      await initialize(['NomenclatureControlFile.nlo', 'LaTeX.log-ParsedLaTeXLog'])

      expect(rule.constructCommand()).toEqual({
        args: [
          'makeindex',
          '-t',
          '$DIR_0/$NAME_0.nlg',
          '-o',
          '$DIR_0/$NAME_0.nls',
          '-s',
          'nomencl.ist',
          '$DIR_0/$BASE_0'
        ],
        cd: '$ROOTDIR',
        severity: 'error',
        inputs: ['$DIR_0/$NAME_0.nlg-ParsedMakeIndexLog'],
        outputs: ['$DIR_0/$NAME_0.nls', '$DIR_0/$NAME_0.nlg']
      })

      done()
    })

    it('returns correct arguments and command options for bibref file.', async (done) => {
      await initialize(['BibRefControlFile.bdx', 'LaTeX.log-ParsedLaTeXLog'])

      expect(rule.constructCommand()).toEqual({
        args: [
          'makeindex',
          '-t',
          '$DIR_0/$NAME_0.brlg',
          '-o',
          '$DIR_0/$NAME_0.bnd',
          '-s',
          'bibref.ist',
          '$DIR_0/$BASE_0'
        ],
        cd: '$ROOTDIR',
        severity: 'error',
        inputs: ['$DIR_0/$NAME_0.brlg-ParsedMakeIndexLog'],
        outputs: ['$DIR_0/$NAME_0.bnd', '$DIR_0/$NAME_0.brlg']
      })

      done()
    })

    it('add -c to command line when MakeIndex_compressBlanks is enabled.', async (done) => {
      await initialize(['IndexControlFile.idx', 'LaTeX.log-ParsedLaTeXLog'], { MakeIndex_compressBlanks: true })

      expect(rule.constructCommand().args).toContain('-c')

      done()
    })

    it('add -l to command line when MakeIndex_ordering is set to \'letter\'.', async (done) => {
      await initialize(['IndexControlFile.idx', 'LaTeX.log-ParsedLaTeXLog'], { MakeIndex_ordering: 'letter' })

      expect(rule.constructCommand().args).toContain('-l')

      done()
    })

    it('add -g to command line when MakeIndex_sorting is set to \'german\'.', async (done) => {
      await initialize(['IndexControlFile.idx', 'LaTeX.log-ParsedLaTeXLog'], { MakeIndex_sorting: 'german' })

      expect(rule.constructCommand().args).toContain('-g')

      done()
    })

    it('add -T to command line when MakeIndex_sorting is set to \'thai\'.', async (done) => {
      await initialize(['IndexControlFile.idx', 'LaTeX.log-ParsedLaTeXLog'], { MakeIndex_sorting: 'thai' })

      expect(rule.constructCommand().args).toContain('-T')

      done()
    })

    it('add -L to command line when MakeIndex_sorting is set to \'locale\'.', async (done) => {
      await initialize(['IndexControlFile.idx', 'LaTeX.log-ParsedLaTeXLog'], { MakeIndex_sorting: 'locale' })

      expect(rule.constructCommand().args).toContain('-L')

      done()
    })

    it('add -r to command line when MakeIndex_automaticRanges is disabled.', async (done) => {
      await initialize(['IndexControlFile.idx'], { MakeIndex_automaticRanges: false })

      expect(rule.constructCommand().args).toContain('-r')

      done()
    })

    it('add -p to command line when MakeIndex_startPage is set.', async (done) => {
      await initialize(['IndexControlFile.idx'], { MakeIndex_startPage: 'odd' })

      expect(rule.constructCommand().args).toEqual(jasmine.arrayContaining(['-p', 'odd']))

      done()
    })

    it('add -s to command line when MakeIndex_style is set.', async (done) => {
      await initialize(['IndexControlFile.idx'], { MakeIndex_style: 'foo.ist' })

      expect(rule.constructCommand().args).toEqual(jasmine.arrayContaining(['-s', 'foo.ist']))

      done()
    })
  })
})
<|endoftext|>


<commit_before>'use strict';

var browserSync = require('browser-sync').create();
var colorguard  = require('gulp-colorguard');
var csscomb     = require('gulp-csscomb');
var dateTime    = require('@radioactivehamster/date-time');
var fs          = require('fs');
var gulp        = require('gulp');
var htmltidy    = require('gulp-htmltidy');
var yaml        = require('js-yaml');
var less        = require('gulp-less');
var pkg         = require('./package.json');
var stachio     = require('gulp-stachio');

gulp.task('serve', ['style', 'template'], () => {
    browserSync.init({
        open: false,
        server: { baseDir: './' }
    });
    gulp.watch('./src/**/*.*', ['style', 'template']).on('change', browserSync.reload);
});

gulp.task('style', () => {
    return gulp.src('./src/style/main.less')
        .pipe(less())
        .pipe(csscomb())
        /**
         * @todo Correct the color conflict with "links.css."
         */
        .pipe(colorguard().on('error', e => console.warn(e.message)))
        .pipe(gulp.dest('./'));
});

gulp.task('template', () => {
    /**
     * Remove angle bracket enclosed email addresses.
     * @todo Look into potential "safe string" encoding issues in `stachio`.
     */
    let author     = pkg.author.replace(/ <.+>/i, '');
    let cname      = fs.readFileSync('./CNAME').toString().trim();
    let htmltidyrc = yaml.load(fs.readFileSync('./.htmltidyrc').toString());
    let vcard      = fs.readFileSync('./data/me/vcard.jsonld').toString().trim();

    return gulp.src('./src/template/**/*.hbs')
        .pipe(stachio({ author: author, cname: cname, timestamp: dateTime(), vcard: vcard }))
        .pipe(htmltidy(htmltidyrc))
        .pipe(gulp.dest('./'));
});

gulp.task('default', ['style', 'template']);
<commit_msg>Changed the package includes to constants.<commit_after>'use strict';

const browserSync = require('browser-sync').create();
const colorguard  = require('gulp-colorguard');
const csscomb     = require('gulp-csscomb');
const dateTime    = require('@radioactivehamster/date-time');
const fs          = require('fs');
const gulp        = require('gulp');
const htmltidy    = require('gulp-htmltidy');
const yaml        = require('js-yaml');
const less        = require('gulp-less');
const pkg         = require('./package.json');
const stachio     = require('gulp-stachio');

gulp.task('serve', ['style', 'template'], () => {
    browserSync.init({
        open: false,
        server: { baseDir: './' }
    });
    gulp.watch('./src/**/*.*', ['style', 'template']).on('change', browserSync.reload);
});

gulp.task('style', () => {
    return gulp.src('./src/style/main.less')
        .pipe(less())
        .pipe(csscomb())
        /**
         * @todo Correct the color conflict with "links.css."
         */
        .pipe(colorguard().on('error', e => console.error(e.message)))
        .pipe(gulp.dest('./'));
});

gulp.task('template', () => {
    /**
     * Remove angle bracket enclosed email addresses.
     * @todo Look into potential "safe string" encoding issues in `stachio`.
     */
    let author     = pkg.author.replace(/ <.+>/i, '');
    let cname      = fs.readFileSync('./CNAME').toString().trim();
    let htmltidyrc = yaml.load(fs.readFileSync('./.htmltidyrc').toString());
    let vcard      = fs.readFileSync('./data/me/vcard.jsonld').toString().trim();

    return gulp.src('./src/template/**/*.hbs')
        .pipe(stachio({ author: author, cname: cname, timestamp: dateTime(), vcard: vcard }))
        .pipe(htmltidy(htmltidyrc))
        .pipe(gulp.dest('./'));
});

gulp.task('default', ['style', 'template']);
<|endoftext|>


<commit_before>document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady(){}

$(document).ready(function(){

    //---------------------------------------------------------------------------------------------------------

    // initialize ol

    var view = new ol.View({
    	center: ol.proj.transform([73.241, 61.143], 'EPSG:4326', 'EPSG:3857'),
    	zoom: 16
    });

    var map = new ol.Map({
      layers: [
        new ol.layer.Tile({
          source: new ol.source.XYZ({
            url: 'http://tiles.{a-z}.st.vmp.ru/{z}/{x}/{y}.png',
            tilePixelRatio: 1,
            minZoom: 12,
            maxZoom: 18
          }),
        })
      ],
      target: 'map',
      view: view,
      interactions: ol.interaction.defaults({
          keyboard: false,
          DragAndDrop: false,
          altShiftDragRotate:false,
          pinchRotate:true
      })
    });

    //---------------------------------------------------------------------------------------------------------

    // marker

    var markerEl = document.getElementById('location-marker');
    var marker = new ol.Overlay({
      positioning: 'center-center',
      element: markerEl,
      stopEvent: false
    });
    map.addOverlay(marker);

    var positions = new ol.geom.LineString([],
        /** @type {ol.geom.GeometryLayout} */ ('XYZM'));

    // activate fuck
    var geolocation = new ol.Geolocation(/** @type {olx.GeolocationOptions} */ ({
      projection: view.getProjection(),
      trackingOptions: {
        maximumAge: 10000,
        enableHighAccuracy: true,
        timeout: 600000
      }
    }));

    var speed = '';

    var deltaMean = 500;

    // listener
    geolocation.on('change', function(evt) {
      var position = geolocation.getPosition();
      var accuracy = geolocation.getAccuracy();
      var heading = geolocation.getHeading() || 0;
      var speed = geolocation.getSpeed() || 0;
      var m = Date.now();

      console.log(speed);

      addPosition(position, heading, m, speed);

      var coords = positions.getCoordinates();
      var len = coords.length;
      if (len >= 2) {
        deltaMean = (coords[len - 1][3] - coords[0][3]) / (len - 1);
      }

    });

    geolocation.on('error', function() {
      alert('geolocation error');
    });

    function radToDeg(rad) {
      return rad * 360 / (Math.PI * 2);
    }
    function degToRad(deg) {
      return deg * Math.PI * 2 / 360;
    }
    // invert negative
    function mod(n) {
      return ((n % (2 * Math.PI)) + (2 * Math.PI)) % (2 * Math.PI);
    }

    function addPosition(position, heading, m, speed) {
      var x = position[0];
      var y = position[1];
      var fCoords = positions.getCoordinates();
      var previous = fCoords[fCoords.length - 1];
      var prevHeading = previous && previous[2];
      if (prevHeading) {
        var headingDiff = heading - mod(prevHeading);

        if (Math.abs(headingDiff) > Math.PI) {      // < 180 ok da
          var sign = (headingDiff >= 0) ? 1 : -1;
          headingDiff = - sign * (2 * Math.PI - Math.abs(headingDiff));
        }
        heading = prevHeading + headingDiff;
      }
      positions.appendCoordinate([x, y, heading, m]);

      positions.setCoordinates(positions.getCoordinates().slice(-20));

      if (heading && speed) {
        markerEl.src = 'img/location.png';
      } else {
        markerEl.src = 'img/location-static.png';
      }
    }

    var previousM = 0;

    // set center
    map.beforeRender(function(map, frameState) {
      if (frameState !== null) {
        var m = frameState.time - deltaMean * 1.5;      // get out smoother than ever!
        m = Math.max(m, previousM);
        previousM = m;
        var c = positions.getCoordinateAtM(m, true);    // stackoverflow magic!
        var view = frameState.viewState;
        if (c) {
          view.center = getCenterWithHeading(c, -c[2], view.resolution);
          view.rotation = -c[2];
          marker.setPosition(c);
        }
      }
      return true;
    });

    function getCenterWithHeading(position, rotation, resolution) {
      var size = map.getSize();
      var height = size[1];

      return [
        position[0] - Math.sin(rotation) * height * resolution * 1 / 4,
        position[1] + Math.cos(rotation) * height * resolution * 1 / 4
      ];
    }

    // callback
    function render() {
      map.render();
    }

    // TADA
    function geolocate() {

      if(speed > 2) {
            geolocation.setTracking(true); // Start position tracking
      }
        else {
            geolocation.setTracking(false);
        }
      map.on('postcompose', render);
      map.render();
    }

    geolocate();

    //---------------------------------------------------------------------------------------------------------

    // timer

    var hours = 0, mins = 0, secs = 0;
    function resetTimer(){
    	secs = 0, mins = 0, hours = 0;
    }
    function startTimer(){
    	tick = setInterval(function(){
    		secs += 1;
    		if(secs < 10){
    			hsecs = ':0' + secs;
    		} else if(secs == 60){
    			mins += 1;
    			secs = 0;
    			hsecs = ':0' + secs;
    		}
    		else
    			hsecs = ':' + secs;

    		if(mins < 10)
    			hmins = '0' + mins;
    		else if(mins == 60){
    			hours += 1;
    			mins = 0;
    			hmins = '0' + mins;
    		}
    		else
    			hmins = mins

    		if(hours == 0)
    			hhours = '';
    		else {
    			hhours = hours + ':';
    			hsecs = "" + hsecs + "";

    		}

    		$("#timer").html(hhours + hmins + hsecs);
    	}, 1000);
    }
    function stopTimer(){
    	clearInterval(tick);
    }
    startTimer();

    //---------------------------------------------------------------------------------------------------------

    // parse json and get routes

    $.getJSON( "json/routes.json", function( data ) {
      // for loop. parsing all routes.
      for(var i=0; i < data.routes.length; i++){
        var item = data.routes[i][i+1][0];

        var kind = {
          'dist': {
            css: "dist",
            header: "На дистанцию"
          },
          'time': {
            css: "time",
            header: "На время"
          }
        }
        $("#routes").append("\

\

"+ kind[item.kind].header +"
\

"+ item.name +"
\

" + item.length +" км
\
          <button>Начать</button>\
          ");

        console.log(i+1 + " route serializing");
        // parsing
        var routesArr = new Array();
        for(var e=0; e < item.latlngs.length; e++){
          routesArr.push(item.latlngs[e]);
        }
        var rend = {}
        rend.latlngs = routesArr;
        addRoutes(rend);

        // $("#routes").append("\
        //
\
        //
На время
\
        //
Кедровый лог
\
        //
17 мин
\
        //     <button>Начать</button>\
        //
");
      }
    });

    var countLineRoutes = 0;
    var vectorLayerLineFirst = new ol.layer.Vector({});

    function addRoutes(coord) {
      if (countLineRoutes == 0) {
        var comp = new Array();

        for (var i = 0; i < coord.latlngs.length; i++) {
          var xandy = ol.proj.transform([coord.latlngs[i].lng, coord.latlngs[i].lat], 'EPSG:4326', 'EPSG:3857');
          comp.push(xandy);
        }

        var firstroutesF = new ol.Feature({
          geometry: new ol.geom.LineString(comp)
        });

        var vectorLineFirst = new ol.source.Vector({});
        vectorLineFirst.addFeature(firstroutesF);

        vectorLayerLineFirst = new ol.layer.Vector({
          source: vectorLineFirst
        });

        map.addLayer(vectorLayerLineFirst);
        countLineRoutes++;
        console.log(comp);
      }
    }

});

setTimeout(function(){
  frameNumb = 0;
  $(function () {

      $('.fotorama')
      .on('fotorama:showend ',
              function (e, fotorama) {
                  var frameNumb = fotorama.activeIndex + 1;
                  console.log(frameNumb);
              }
          )
          .fotorama();
    });
}, 500);
<commit_msg>zapyataya<commit_after>document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady(){}

$(document).ready(function(){

    //---------------------------------------------------------------------------------------------------------

    // initialize ol

    var view = new ol.View({
    	center: ol.proj.transform([73.241, 61.143], 'EPSG:4326', 'EPSG:3857'),
    	zoom: 16
    });

    var map = new ol.Map({
      layers: [
        new ol.layer.Tile({
          source: new ol.source.XYZ({
            url: 'http://tiles.{a-z}.st.vmp.ru/{z}/{x}/{y}.png',
            tilePixelRatio: 1,
            minZoom: 12,
            maxZoom: 18
          }),
        })
      ],
      target: 'map',
      view: view,
      interactions: ol.interaction.defaults({
          keyboard: false,
          DragAndDrop: false,
          altShiftDragRotate:false,
          pinchRotate:true
      })
    });

    //---------------------------------------------------------------------------------------------------------

    // marker

    var markerEl = document.getElementById('location-marker');
    var marker = new ol.Overlay({
      positioning: 'center-center',
      element: markerEl,
      stopEvent: false
    });
    map.addOverlay(marker);

    var positions = new ol.geom.LineString([],
        /** @type {ol.geom.GeometryLayout} */ ('XYZM'));

    // activate fuck
    var geolocation = new ol.Geolocation(/** @type {olx.GeolocationOptions} */ ({
      projection: view.getProjection(),
      trackingOptions: {
        maximumAge: 10000,
        enableHighAccuracy: true,
        timeout: 600000
      }
    }));

    var speed = '';

    var deltaMean = 500;

    // listener
    geolocation.on('change', function(evt) {
      var position = geolocation.getPosition();
      var accuracy = geolocation.getAccuracy();
      var heading = geolocation.getHeading() || 0;
      var speed = geolocation.getSpeed() || 0;

      if(speed > 2) {
            geolocation.setTracking(true); // Start position tracking
      }
      else {
          geolocation.setTracking(false);
      }

      var m = Date.now();

      console.log(speed);

      addPosition(position, heading, m, speed);

      var coords = positions.getCoordinates();
      var len = coords.length;
      if (len >= 2) {
        deltaMean = (coords[len - 1][3] - coords[0][3]) / (len - 1);
      }

    });

    geolocation.on('error', function() {
      alert('geolocation error');
    });

    function radToDeg(rad) {
      return rad * 360 / (Math.PI * 2);
    }
    function degToRad(deg) {
      return deg * Math.PI * 2 / 360;
    }
    // invert negative
    function mod(n) {
      return ((n % (2 * Math.PI)) + (2 * Math.PI)) % (2 * Math.PI);
    }

    function addPosition(position, heading, m, speed) {
      var x = position[0];
      var y = position[1];
      var fCoords = positions.getCoordinates();
      var previous = fCoords[fCoords.length - 1];
      var prevHeading = previous && previous[2];
      if (prevHeading) {
        var headingDiff = heading - mod(prevHeading);

        if (Math.abs(headingDiff) > Math.PI) {      // < 180 ok da
          var sign = (headingDiff >= 0) ? 1 : -1;
          headingDiff = - sign * (2 * Math.PI - Math.abs(headingDiff));
        }
        heading = prevHeading + headingDiff;
      }
      positions.appendCoordinate([x, y, heading, m]);

      positions.setCoordinates(positions.getCoordinates().slice(-20));

      if (heading && speed) {
        markerEl.src = 'img/location.png';
      } else {
        markerEl.src = 'img/location-static.png';
      }
    }

    var previousM = 0;

    // set center
    map.beforeRender(function(map, frameState) {
      if (frameState !== null) {
        var m = frameState.time - deltaMean * 1.5;      // get out smoother than ever!
        m = Math.max(m, previousM);
        previousM = m;
        var c = positions.getCoordinateAtM(m, true);    // stackoverflow magic!
        var view = frameState.viewState;
        if (c) {
          view.center = getCenterWithHeading(c, -c[2], view.resolution);
          view.rotation = -c[2];
          marker.setPosition(c);
        }
      }
      return true;
    });

    function getCenterWithHeading(position, rotation, resolution) {
      var size = map.getSize();
      var height = size[1];

      return [
        position[0] - Math.sin(rotation) * height * resolution * 1 / 4,
        position[1] + Math.cos(rotation) * height * resolution * 1 / 4
      ];
    }

    // callback
    function render() {
      map.render();
    }

    // TADA
    function geolocate() {
      geolocation.setTracking(true); // Start position tracking
      map.on('postcompose', render);
      map.render();
    }

    geolocate();

    //---------------------------------------------------------------------------------------------------------

    // timer

    var hours = 0, mins = 0, secs = 0;
    function resetTimer(){
    	secs = 0, mins = 0, hours = 0;
    }
    function startTimer(){
    	tick = setInterval(function(){
    		secs += 1;
    		if(secs < 10){
    			hsecs = ':0' + secs;
    		} else if(secs == 60){
    			mins += 1;
    			secs = 0;
    			hsecs = ':0' + secs;
    		}
    		else
    			hsecs = ':' + secs;

    		if(mins < 10)
    			hmins = '0' + mins;
    		else if(mins == 60){
    			hours += 1;
    			mins = 0;
    			hmins = '0' + mins;
    		}
    		else
    			hmins = mins

    		if(hours == 0)
    			hhours = '';
    		else {
    			hhours = hours + ':';
    			hsecs = "" + hsecs + "";

    		}

    		$("#timer").html(hhours + hmins + hsecs);
    	}, 1000);
    }
    function stopTimer(){
    	clearInterval(tick);
    }
    startTimer();

    //---------------------------------------------------------------------------------------------------------

    // parse json and get routes

    $.getJSON( "json/routes.json", function( data ) {
      // for loop. parsing all routes.
      for(var i=0; i < data.routes.length; i++){
        var item = data.routes[i][i+1][0];

        var kind = {
          'dist': {
            css: "dist",
            header: "На дистанцию"
          },
          'time': {
            css: "time",
            header: "На время"
          }
        }
        item.length = item.length.toString().slice(0, -1);
        item.length = item.length.replace(".", ",");
        $("#routes").append("\

\

"+ kind[item.kind].header +"
\

"+ item.name +"
\

" + item.length +" км
\
          <button>Начать</button>\
          ");

        console.log(i+1 + " route serializing");
        // parsing
        var routesArr = new Array();
        for(var e=0; e < item.latlngs.length; e++){
          routesArr.push(item.latlngs[e]);
        }
        var rend = {}
        rend.latlngs = routesArr;
        addRoutes(rend);

        // $("#routes").append("\
        //
\
        //
На время
\
        //
Кедровый лог
\
        //
17 мин
\
        //     <button>Начать</button>\
        //
");
      }
    });

    var countLineRoutes = 0;
    var vectorLayerLineFirst = new ol.layer.Vector({});

    function addRoutes(coord) {
      if (countLineRoutes == 0) {
        var comp = new Array();

        for (var i = 0; i < coord.latlngs.length; i++) {
          var xandy = ol.proj.transform([coord.latlngs[i].lng, coord.latlngs[i].lat], 'EPSG:4326', 'EPSG:3857');
          comp.push(xandy);
        }

        var firstroutesF = new ol.Feature({
          geometry: new ol.geom.LineString(comp)
        });

        var vectorLineFirst = new ol.source.Vector({});
        vectorLineFirst.addFeature(firstroutesF);

        vectorLayerLineFirst = new ol.layer.Vector({
          source: vectorLineFirst
        });

        map.addLayer(vectorLayerLineFirst);
        countLineRoutes++;
        console.log(comp);
      }
    }

});

setTimeout(function(){
  frameNumb = 0;
  $(function () {

      $('.fotorama')
      .on('fotorama:showend ',
              function (e, fotorama) {
                  var frameNumb = fotorama.activeIndex + 1;
                  console.log(frameNumb);
              }
          )
          .fotorama();
    });
}, 500);
<|endoftext|>