<commit_before>var MemoryLogger = require("../memorylogger");
var CommandRunner = require("../commandrunner");
var fs = require("fs");
var path = require("path");
var assert = require("assert");
var Server = require("../server");
var Reporter = require("../reporter");
var sandbox = require("../sandbox");
var log = console.log;

describe("Repeated compilation of contracts with inheritance", function() {
  var config;
  var sources;
  var sourcePaths;
  var artifactPaths;
  var initialTimes;
  var finalTimes;
  var output;
  var mapping = {};

  var project = path.join(__dirname, '../../sources/inheritance');
  var names = ["Root", "Branch", "LeafA", "LeafB", "LeafC", "SameFile1", "SameFile2", "LibraryA"];
  var logger = new MemoryLogger();

  // ----------------------- Utils -----------------------------
  function processErr(err, output){
    if (err){
      log(output);
      throw new Error(err);
    }
  }

  function waitSecond() {
    return new Promise((resolve, reject) => setTimeout(() => resolve(), 1250));
  }

  function getSource(key) {
    return fs.readFileSync(mapping[key].sourcePath);
  }

  function getArtifact(key) {
    return fs.readFileSync(mapping[key].artifactPath);
  }

  function getArtifactStats() {
    const stats = {};
    names.forEach(key => {
      const mDate = fs.statSync(mapping[key].artifactPath).mtime.getTime();
      stats[key] = mDate;
    });
    return stats;
  }

  function touchSource(key) {
    const source = getSource(key);
    fs.writeFileSync(mapping[key].sourcePath, source);
  }

  // ----------------------- Setup -----------------------------

  before("set up the server", function(done) {
    Server.start(done);
  });

  after("stop server", function(done) {
    Server.stop(done);
  });

  beforeEach("set up sandbox and do initial compile", function(done) {
    this.timeout(10000);

    sandbox.create(project).then(conf => {
      config = conf;
      config.network = "development";
      config.logger = logger;
      config.mocha = {
        reporter: new Reporter(logger),
      }

      sources = names.map(name => name + '.sol');
      artifactPaths = names.map(name => path.join(config.contracts_build_directory, name + '.json'));
      sourcePaths = sources.map(source => path.join(config.contracts_directory, source));

      names.forEach((name, i) => {
        mapping[name] = {};
        mapping[name].source = sources[i];
        mapping[name].artifactPath = artifactPaths[i];
        mapping[name].sourcePath = sourcePaths[i];
      })

      CommandRunner.run("compile", config, function(err) {
        output = logger.contents();
        processErr(err, output);

        initialTimes = getArtifactStats();

        // mTime resolution on 6.9.1 is 1 sec.
        waitSecond().then(done);
      })
    });
  });

  // -------------Inheritance Graph -----------------------------
  //                                      |
  //      LibA         LeafA              |    SameFile1 - LeafC
  //     /           /       \            |
  // Root* - Branch -           - LeafC   |    SameFile2
  //                 \       /            |
  //                   LeafB              |
  // ------------------------------------------------------------

  it("Updates only Root when Root is touched", function(done) {
    this.timeout(30000);

    touchSource('Root');

    CommandRunner.run("compile", config, function(err) {
      output = logger.contents();
      processErr(err, output);

      finalTimes = getArtifactStats();

      try {
        assert(initialTimes['Root'] < finalTimes['Root'], 'Should update root');
        assert(initialTimes['Branch'] === finalTimes['Branch'], 'Should not update Branch');
        assert(initialTimes['LeafA'] === finalTimes['LeafA'], 'Should not update LeafA');
        assert(initialTimes['LeafB'] === finalTimes['LeafB'], 'Should not update LeafB');
        assert(initialTimes['LeafC'] === finalTimes['LeafC'], 'Should not update LeafC');
        assert(initialTimes['LibraryA'] === finalTimes['LibraryA'], 'Should not update LibraryA');
        assert(initialTimes['SameFile1'] === finalTimes['SameFile1'], 'Should not update SameFile1');
        assert(initialTimes['SameFile2'] === finalTimes['SameFile2'], 'Should not update SameFile2');
        done();
      } catch(err) {
        err.message += '\n\n' + output;
        throw new Error(err);
      }
    });
  });

  // -------------Inheritance Graph -----------------------------
  //                                      |
  //      LibA*        LeafA              |    SameFile1 - LeafC
  //     /           /       \            |
  // Root* - Branch -           - LeafC   |    SameFile2
  //                 \       /            |
  //                   LeafB              |
  // ------------------------------------------------------------

  it("Updates Root and Library when Library is touched", function(done) {
    this.timeout(30000);

    touchSource('LibraryA');

    CommandRunner.run("compile", config, function(err) {
      output = logger.contents();
      processErr(err, output);

      finalTimes = getArtifactStats();

      try {
        assert(initialTimes['Root'] < finalTimes['Root'], 'Should update root');
        assert(initialTimes['Branch'] === finalTimes['Branch'], 'Should not update Branch');
        assert(initialTimes['LeafA'] === finalTimes['LeafA'], 'Should not update LeafA');
        assert(initialTimes['LeafB'] === finalTimes['LeafB'], 'Should not update LeafB');
        assert(initialTimes['LeafC'] === finalTimes['LeafC'], 'Should not update LeafC');
        assert(initialTimes['LibraryA'] < finalTimes['LibraryA'], 'Should update LibraryA');
        assert(initialTimes['SameFile1'] === finalTimes['SameFile1'], 'Should not update SameFile1');
        assert(initialTimes['SameFile2'] === finalTimes['SameFile2'], 'Should not update SameFile2');
        done();
      } catch(err) {
        err.message += '\n\n' + output;
        throw new Error(err);
      }
    });
  });

  // -------------Inheritance Graph -----------------------------
  //                                      |
  //      LibA         LeafA              |    SameFile1 - LeafC
  //     /           /       \            |
  // Root* - Branch* -           - LeafC  |    SameFile2
  //                 \       /            |
  //                   LeafB              |
  // ------------------------------------------------------------

  it("Updates Branch and Root when Branch is touched", function(done) {
    this.timeout(30000);

    touchSource('Branch');

    CommandRunner.run("compile", config, function(err) {
      output = logger.contents();
      processErr(err, output);

      finalTimes = getArtifactStats();

      try {
        assert(initialTimes['Root'] < finalTimes['Root'], 'Should update root');
        assert(initialTimes['Branch'] < finalTimes['Branch'], 'Should update Branch');
        assert(initialTimes['LeafA'] === finalTimes['LeafA'], 'Should not update LeafA');
        assert(initialTimes['LeafB'] === finalTimes['LeafB'], 'Should not update LeafB');
        assert(initialTimes['LeafC'] === finalTimes['LeafC'], 'Should not update LeafC');
        assert(initialTimes['LibraryA'] === finalTimes['LibraryA'], 'Should not update LibraryA');
        assert(initialTimes['SameFile1'] === finalTimes['SameFile1'], 'Should not update SameFile1');
        assert(initialTimes['SameFile2'] === finalTimes['SameFile2'], 'Should not update SameFile2');
        done();
      } catch(err) {
        err.message += '\n\n' + output;
        throw new Error(err);
      }
    });
  });

  // -------------Inheritance Graph -----------------------------
  //                                       |
  //      LibA          LeafA*             |    SameFile1 - LeafC
  //     /            /       \            |
  // Root* - Branch* -           - LeafC   |    SameFile2
  //                  \       /            |
  //                    LeafB              |
  // ------------------------------------------------------------

  it("Updates LeafA, Branch and Root when LeafA is touched", function(done) {
    this.timeout(30000);

    touchSource('LeafA');

    CommandRunner.run("compile", config, function(err) {
      output = logger.contents();
      processErr(err, output);

      finalTimes = getArtifactStats();

      try {
        assert(initialTimes['Root'] < finalTimes['Root'], 'Should update root');
        assert(initialTimes['Branch'] < finalTimes['Branch'], 'Should update Branch');
        assert(initialTimes['LeafA'] < finalTimes['LeafA'], 'Should update LeafA');
        assert(initialTimes['LeafB'] === finalTimes['LeafB'], 'Should not update LeafB');
        assert(initialTimes['LeafC'] === finalTimes['LeafC'], 'Should not update LeafC');
        assert(initialTimes['LibraryA'] === finalTimes['LibraryA'], 'Should not update LibraryA');
        assert(initialTimes['SameFile1'] === finalTimes['SameFile1'], 'Should not update SameFile1');
        assert(initialTimes['SameFile2'] === finalTimes['SameFile2'], 'Should not update SameFile2');
        done();
      } catch(err) {
        err.message += '\n\n' + output;
        throw new Error(err);
      }
    });
  });

  // -------------Inheritance Graph -----------------------------
  //                                       |
  //      LibA         LeafA*              |  SameFile1* - LeafC*
  //     /           /        \            |
  // Root* - Branch* -           - LeafC*  |  SameFile2*
  //                 \        /            |
  //                   LeafB*              |
  // ------------------------------------------------------------

  it("Updates everything except LibraryA when LeafC is touched", function(done) {
    this.timeout(30000);

    touchSource('LeafC');

    CommandRunner.run("compile", config, function(err) {
      output = logger.contents();
      processErr(err, output);

      finalTimes = getArtifactStats();

      try {
        assert(initialTimes['Root'] < finalTimes['Root'], 'Should update root');
        assert(initialTimes['Branch'] < finalTimes['Branch'], 'Should update Branch');
        assert(initialTimes['LeafA'] < finalTimes['LeafA'], 'Should update LeafA');
        assert(initialTimes['LeafB'] < finalTimes['LeafB'], 'Should update LeafB');
        assert(initialTimes['LeafC'] < finalTimes['LeafC'], 'Should update LeafC');
        assert(initialTimes['LibraryA'] === finalTimes['LibraryA'], 'Should not update LibraryA');
        assert(initialTimes['SameFile1'] < finalTimes['SameFile1'], 'Should update SameFile1');
        assert(initialTimes['SameFile2'] < finalTimes['SameFile2'], 'Should update SameFile2');
        done();
      } catch(err) {
        err.message += '\n\n' + output;
        throw new Error(err);
      }
    });
  });
});
<commit_msg>Lengthen compile test timeout<commit_after>var MemoryLogger = require("../memorylogger");
var CommandRunner = require("../commandrunner");
var fs = require("fs");
var path = require("path");
var assert = require("assert");
var Server = require("../server");
var Reporter = require("../reporter");
var sandbox = require("../sandbox");
var log = console.log;

describe("Repeated compilation of contracts with inheritance", function() {
  var config;
  var sources;
  var sourcePaths;
  var artifactPaths;
  var initialTimes;
  var finalTimes;
  var output;
  var mapping = {};

  var project = path.join(__dirname, '../../sources/inheritance');
  var names = ["Root", "Branch", "LeafA", "LeafB", "LeafC", "SameFile1", "SameFile2", "LibraryA"];
  var logger = new MemoryLogger();

  // ----------------------- Utils -----------------------------
  function processErr(err, output){
    if (err){
      log(output);
      throw new Error(err);
    }
  }

  function waitSecond() {
    return new Promise((resolve, reject) => setTimeout(() => resolve(), 1250));
  }

  function getSource(key) {
    return fs.readFileSync(mapping[key].sourcePath);
  }

  function getArtifact(key) {
    return fs.readFileSync(mapping[key].artifactPath);
  }

  function getArtifactStats() {
    const stats = {};
    names.forEach(key => {
      const mDate = fs.statSync(mapping[key].artifactPath).mtime.getTime();
      stats[key] = mDate;
    });
    return stats;
  }

  function touchSource(key) {
    const source = getSource(key);
    fs.writeFileSync(mapping[key].sourcePath, source);
  }

  // ----------------------- Setup -----------------------------

  before("set up the server", function(done) {
    Server.start(done);
  });

  after("stop server", function(done) {
    Server.stop(done);
  });

  beforeEach("set up sandbox and do initial compile", function(done) {
    this.timeout(30000);

    sandbox.create(project).then(conf => {
      config = conf;
      config.network = "development";
      config.logger = logger;
      config.mocha = {
        reporter: new Reporter(logger),
      }

      sources = names.map(name => name + '.sol');
      artifactPaths = names.map(name => path.join(config.contracts_build_directory, name + '.json'));
      sourcePaths = sources.map(source => path.join(config.contracts_directory, source));

      names.forEach((name, i) => {
        mapping[name] = {};
        mapping[name].source = sources[i];
        mapping[name].artifactPath = artifactPaths[i];
        mapping[name].sourcePath = sourcePaths[i];
      })

      CommandRunner.run("compile", config, function(err) {
        output = logger.contents();
        processErr(err, output);

        initialTimes = getArtifactStats();

        // mTime resolution on 6.9.1 is 1 sec.
        waitSecond().then(done);
      })
    });
  });

  // -------------Inheritance Graph -----------------------------
  //                                      |
  //      LibA         LeafA              |    SameFile1 - LeafC
  //     /           /       \            |
  // Root* - Branch -           - LeafC   |    SameFile2
  //                 \       /            |
  //                   LeafB              |
  // ------------------------------------------------------------

  it("Updates only Root when Root is touched", function(done) {
    this.timeout(30000);

    touchSource('Root');

    CommandRunner.run("compile", config, function(err) {
      output = logger.contents();
      processErr(err, output);

      finalTimes = getArtifactStats();

      try {
        assert(initialTimes['Root'] < finalTimes['Root'], 'Should update root');
        assert(initialTimes['Branch'] === finalTimes['Branch'], 'Should not update Branch');
        assert(initialTimes['LeafA'] === finalTimes['LeafA'], 'Should not update LeafA');
        assert(initialTimes['LeafB'] === finalTimes['LeafB'], 'Should not update LeafB');
        assert(initialTimes['LeafC'] === finalTimes['LeafC'], 'Should not update LeafC');
        assert(initialTimes['LibraryA'] === finalTimes['LibraryA'], 'Should not update LibraryA');
        assert(initialTimes['SameFile1'] === finalTimes['SameFile1'], 'Should not update SameFile1');
        assert(initialTimes['SameFile2'] === finalTimes['SameFile2'], 'Should not update SameFile2');
        done();
      } catch(err) {
        err.message += '\n\n' + output;
        throw new Error(err);
      }
    });
  });

  // -------------Inheritance Graph -----------------------------
  //                                      |
  //      LibA*        LeafA              |    SameFile1 - LeafC
  //     /           /       \            |
  // Root* - Branch -           - LeafC   |    SameFile2
  //                 \       /            |
  //                   LeafB              |
  // ------------------------------------------------------------

  it("Updates Root and Library when Library is touched", function(done) {
    this.timeout(30000);

    touchSource('LibraryA');

    CommandRunner.run("compile", config, function(err) {
      output = logger.contents();
      processErr(err, output);

      finalTimes = getArtifactStats();

      try {
        assert(initialTimes['Root'] < finalTimes['Root'], 'Should update root');
        assert(initialTimes['Branch'] === finalTimes['Branch'], 'Should not update Branch');
        assert(initialTimes['LeafA'] === finalTimes['LeafA'], 'Should not update LeafA');
        assert(initialTimes['LeafB'] === finalTimes['LeafB'], 'Should not update LeafB');
        assert(initialTimes['LeafC'] === finalTimes['LeafC'], 'Should not update LeafC');
        assert(initialTimes['LibraryA'] < finalTimes['LibraryA'], 'Should update LibraryA');
        assert(initialTimes['SameFile1'] === finalTimes['SameFile1'], 'Should not update SameFile1');
        assert(initialTimes['SameFile2'] === finalTimes['SameFile2'], 'Should not update SameFile2');
        done();
      } catch(err) {
        err.message += '\n\n' + output;
        throw new Error(err);
      }
    });
  });

  // -------------Inheritance Graph -----------------------------
  //                                      |
  //      LibA         LeafA              |    SameFile1 - LeafC
  //     /           /       \            |
  // Root* - Branch* -           - LeafC  |    SameFile2
  //                 \       /            |
  //                   LeafB              |
  // ------------------------------------------------------------

  it("Updates Branch and Root when Branch is touched", function(done) {
    this.timeout(30000);

    touchSource('Branch');

    CommandRunner.run("compile", config, function(err) {
      output = logger.contents();
      processErr(err, output);

      finalTimes = getArtifactStats();

      try {
        assert(initialTimes['Root'] < finalTimes['Root'], 'Should update root');
        assert(initialTimes['Branch'] < finalTimes['Branch'], 'Should update Branch');
        assert(initialTimes['LeafA'] === finalTimes['LeafA'], 'Should not update LeafA');
        assert(initialTimes['LeafB'] === finalTimes['LeafB'], 'Should not update LeafB');
        assert(initialTimes['LeafC'] === finalTimes['LeafC'], 'Should not update LeafC');
        assert(initialTimes['LibraryA'] === finalTimes['LibraryA'], 'Should not update LibraryA');
        assert(initialTimes['SameFile1'] === finalTimes['SameFile1'], 'Should not update SameFile1');
        assert(initialTimes['SameFile2'] === finalTimes['SameFile2'], 'Should not update SameFile2');
        done();
      } catch(err) {
        err.message += '\n\n' + output;
        throw new Error(err);
      }
    });
  });

  // -------------Inheritance Graph -----------------------------
  //                                       |
  //      LibA          LeafA*             |    SameFile1 - LeafC
  //     /            /       \            |
  // Root* - Branch* -           - LeafC   |    SameFile2
  //                  \       /            |
  //                    LeafB              |
  // ------------------------------------------------------------

  it("Updates LeafA, Branch and Root when LeafA is touched", function(done) {
    this.timeout(30000);

    touchSource('LeafA');

    CommandRunner.run("compile", config, function(err) {
      output = logger.contents();
      processErr(err, output);

      finalTimes = getArtifactStats();

      try {
        assert(initialTimes['Root'] < finalTimes['Root'], 'Should update root');
        assert(initialTimes['Branch'] < finalTimes['Branch'], 'Should update Branch');
        assert(initialTimes['LeafA'] < finalTimes['LeafA'], 'Should update LeafA');
        assert(initialTimes['LeafB'] === finalTimes['LeafB'], 'Should not update LeafB');
        assert(initialTimes['LeafC'] === finalTimes['LeafC'], 'Should not update LeafC');
        assert(initialTimes['LibraryA'] === finalTimes['LibraryA'], 'Should not update LibraryA');
        assert(initialTimes['SameFile1'] === finalTimes['SameFile1'], 'Should not update SameFile1');
        assert(initialTimes['SameFile2'] === finalTimes['SameFile2'], 'Should not update SameFile2');
        done();
      } catch(err) {
        err.message += '\n\n' + output;
        throw new Error(err);
      }
    });
  });

  // -------------Inheritance Graph -----------------------------
  //                                       |
  //      LibA         LeafA*              |  SameFile1* - LeafC*
  //     /           /        \            |
  // Root* - Branch* -           - LeafC*  |  SameFile2*
  //                 \        /            |
  //                   LeafB*              |
  // ------------------------------------------------------------

  it("Updates everything except LibraryA when LeafC is touched", function(done) {
    this.timeout(30000);

    touchSource('LeafC');

    CommandRunner.run("compile", config, function(err) {
      output = logger.contents();
      processErr(err, output);

      finalTimes = getArtifactStats();

      try {
        assert(initialTimes['Root'] < finalTimes['Root'], 'Should update root');
        assert(initialTimes['Branch'] < finalTimes['Branch'], 'Should update Branch');
        assert(initialTimes['LeafA'] < finalTimes['LeafA'], 'Should update LeafA');
        assert(initialTimes['LeafB'] < finalTimes['LeafB'], 'Should update LeafB');
        assert(initialTimes['LeafC'] < finalTimes['LeafC'], 'Should update LeafC');
        assert(initialTimes['LibraryA'] === finalTimes['LibraryA'], 'Should not update LibraryA');
        assert(initialTimes['SameFile1'] < finalTimes['SameFile1'], 'Should update SameFile1');
        assert(initialTimes['SameFile2'] < finalTimes['SameFile2'], 'Should update SameFile2');
        done();
      } catch(err) {
        err.message += '\n\n' + output;
        throw new Error(err);
      }
    });
  });
});
<|endoftext|>


<commit_before>
/**
 * BoardLayer :: This class represents a layer on the board and is the base class for all board
 * layers. Each layer can contain it's own objects on a grid with coordinates and is responsible
 * for drawing itself as well as its objects onto the canvas.
 */

/**
 * Module definition and dependencies
 */
angular.module('ngGo.Board.Layer.Service', [
  'ngGo',
  'ngGo.Board.Grid.Service'
])

/**
 * Factory definition
 */
.factory('BoardLayer', function(BoardGrid) {

  /**
   * Constructor
   */
  function BoardLayer(board, context) {

    //Remember board reference and 2d canvas context
    this.board = board;
    this.context = context;

    //Initialize grid for board objects
    this.grid = new BoardGrid();
  }

  /*****************************************************************************
   * Generic grid and object handling
   ***/

  /**
   * Set grid size
   */
  BoardLayer.prototype.setSize = function(width, height) {

    //Note: since this method is usually only called upon a global board resize,
    //which also triggers the redraw method for layers, the layer is not cleared
    //here, as it will happen anyway during the redraw cycle.

    //Set it in the grid (removing all objects in the process)
    this.grid.setSize(width, height);
  };

  /**
   * Get all items
   */
  BoardLayer.prototype.getAll = function() {
    return this.grid.clone();
  };

  /**
   * Set all items at once
   */
  BoardLayer.prototype.setAll = function(grid) {
    this.grid = grid.clone();
  };

  /**
   * Remove all (clear layer and empty grid)
   */
  BoardLayer.prototype.removeAll = function() {
    this.clear();
    this.grid.empty();
  };

  /**
   * Add a single item
   */
  BoardLayer.prototype.add = function(x, y, value) {
    this.clearCell(x, y);
    this.grid.set(x, y, value);
    this.drawCell(x, y);
  };

  /**
   * Remove a single item
   */
  BoardLayer.prototype.remove = function(x, y) {
    this.clearCell(x, y);
    this.grid.unset(x, y);
  };

  /**
   * Get an item
   */
  BoardLayer.prototype.get = function(x, y) {
    return this.grid.get(x, y);
  };

  /**
   * Check if there is an item
   */
  BoardLayer.prototype.has = function(x, y) {
    return this.grid.has(x, y);
  };

  /*****************************************************************************
   * Generic drawing methods
   ***/

  /**
   * Draw layer
   */
  BoardLayer.prototype.draw = function() {
    //Drawing method to be implemented in specific layer class
  };

  /**
   * Clear layer (this method doesn't clear objects, as the canvas wipe clears the entire canvas)
   */
  BoardLayer.prototype.clear = function() {
    if (this.context) {
      this.context.clearRect(
        0, 0, this.context.canvas.clientWidth, this.context.canvas.clientHeight
      );
    }
  };

  /**
   * Redraw layer
   */
  BoardLayer.prototype.redraw = function() {
    this.clear();
    this.draw();
  };

  /**
   * Draw cell
   */
  BoardLayer.prototype.drawCell = function(/*x, y*/) {
    //Drawing method to be implemented in specific layer class
  };

  /**
   * Clear cell
   */
  BoardLayer.prototype.clearCell = function(/*x, y*/) {
    //Clearing method to be implemented in specific layer class
  };

  /**
   * Redraw cell
   */
  BoardLayer.prototype.redrawCell = function(x, y) {
    this.clearCell(x, y);
    this.drawCell(x, y);
  };

  /**
   * Set the canvas2d context
   */
  BoardLayer.prototype.setContext = function(context) {
    this.context = context;
  };

  /**
   * Get the canvas2d context
   */
  BoardLayer.prototype.getContext = function() {
    return this.context;
  };

  //Return
  return BoardLayer;
});
<commit_msg>Fix clear method in board layer.<commit_after>
/**
 * BoardLayer :: This class represents a layer on the board and is the base class for all board
 * layers. Each layer can contain it's own objects on a grid with coordinates and is responsible
 * for drawing itself as well as its objects onto the canvas.
 */

/**
 * Module definition and dependencies
 */
angular.module('ngGo.Board.Layer.Service', [
  'ngGo',
  'ngGo.Board.Grid.Service'
])

/**
 * Factory definition
 */
.factory('BoardLayer', function(BoardGrid) {

  /**
   * Constructor
   */
  function BoardLayer(board, context) {

    //Remember board reference and 2d canvas context
    this.board = board;
    this.context = context;

    //Initialize grid for board objects
    this.grid = new BoardGrid();
  }

  /*****************************************************************************
   * Generic grid and object handling
   ***/

  /**
   * Set grid size
   */
  BoardLayer.prototype.setSize = function(width, height) {

    //Note: since this method is usually only called upon a global board resize,
    //which also triggers the redraw method for layers, the layer is not cleared
    //here, as it will happen anyway during the redraw cycle.

    //Set it in the grid (removing all objects in the process)
    this.grid.setSize(width, height);
  };

  /**
   * Get all items
   */
  BoardLayer.prototype.getAll = function() {
    return this.grid.clone();
  };

  /**
   * Set all items at once
   */
  BoardLayer.prototype.setAll = function(grid) {
    this.grid = grid.clone();
  };

  /**
   * Remove all (clear layer and empty grid)
   */
  BoardLayer.prototype.removeAll = function() {
    this.clear();
    this.grid.empty();
  };

  /**
   * Add a single item
   */
  BoardLayer.prototype.add = function(x, y, value) {
    this.clearCell(x, y);
    this.grid.set(x, y, value);
    this.drawCell(x, y);
  };

  /**
   * Remove a single item
   */
  BoardLayer.prototype.remove = function(x, y) {
    this.clearCell(x, y);
    this.grid.unset(x, y);
  };

  /**
   * Get an item
   */
  BoardLayer.prototype.get = function(x, y) {
    return this.grid.get(x, y);
  };

  /**
   * Check if there is an item
   */
  BoardLayer.prototype.has = function(x, y) {
    return this.grid.has(x, y);
  };

  /*****************************************************************************
   * Generic drawing methods
   ***/

  /**
   * Draw layer
   */
  BoardLayer.prototype.draw = function() {
    //Drawing method to be implemented in specific layer class
  };

  /**
   * Clear layer (this method doesn't clear objects, as the canvas wipe clears the entire canvas)
   */
  BoardLayer.prototype.clear = function() {
    if (this.context) {
      var pixelRatio = window.devicePixelRatio || 1;
      var width = this.context.canvas.clientWidth * pixelRatio;
      var height = this.context.canvas.clientHeight * pixelRatio;
      this.context.clearRect(0, 0, width, height);
    }
  };

  /**
   * Redraw layer
   */
  BoardLayer.prototype.redraw = function() {
    this.clear();
    this.draw();
  };

  /**
   * Draw cell
   */
  BoardLayer.prototype.drawCell = function(/*x, y*/) {
    //Drawing method to be implemented in specific layer class
  };

  /**
   * Clear cell
   */
  BoardLayer.prototype.clearCell = function(/*x, y*/) {
    //Clearing method to be implemented in specific layer class
  };

  /**
   * Redraw cell
   */
  BoardLayer.prototype.redrawCell = function(x, y) {
    this.clearCell(x, y);
    this.drawCell(x, y);
  };

  /**
   * Set the canvas2d context
   */
  BoardLayer.prototype.setContext = function(context) {
    this.context = context;
  };

  /**
   * Get the canvas2d context
   */
  BoardLayer.prototype.getContext = function() {
    return this.context;
  };

  //Return
  return BoardLayer;
});
<|endoftext|>


<commit_before>require('jquery');
require('jquery-mobile');
require('jquery.cookie');

// for flat-ui
require('jquery-ui');
require('jquery-ui-touch-punch');
require('../bower_components/bootstrap/dist/js/bootstrap.js');
require('bootstrap-switch');
require('bootstrap-tagsinput');
// require('holderjs');
// require('typeahead.js');
require('select2');
require('../bower_components/flat-ui/js/radiocheck.js');

import * as shiren4 from '../es6/model/shiren4.js';

$(() => {
  // alert(shiren4.data[0].name)
  $(':checkbox').checkboxradio();

  $('a.reset-checkboxes').click(() => {
    if(window.confirm('リセットしますか？'))
      clearCheckboxes();
  });

  loadFromCookie();
  $(':checkbox').change(() => saveToCookie());
});

// Clear CheckBoxes "{{{1

var clearCheckboxes = () => {
  $(':checkbox')
  .prop('checked', false)
  .checkboxradio('refresh');

  saveToCookie();
};

// Save/Load Cookie Data "{{{1

var loadFromCookie = () => {
  if (typeof getCookie() === "undefined") return;

  var cookieData = JSON.parse(getCookie());
  Object.keys(cookieData)
  .forEach((key) => {
    $(`#${key} :checkbox`)
    .each((index, elem) =>
      $(elem)
      .prop('checked', cookieData[key][$(elem).data('id')])
      .checkboxradio('refresh')
    );
  });
};

var saveToCookie = () => {
  var ary = {};
    $(':checkbox')
    .each((index, val) => {
      var t = $(val).data('type');
      if (!(t in ary))
        ary[t] = {};
      ary[t][$(val).data('id')] = $(val).prop('checked');
    });
  var json = JSON.stringify(ary);
  setCookie(json);
};

var setCookie = (data) => {
  var thirtyDaysLater = new Date(Date.now() + 30 * 24 * 60 * 60 * 1000);
  document.cookie = `data=${encodeURIComponent(data)};path=${location.pathname};expires=${thirtyDaysLater.toGMTString()}`;
}

var getCookie = () => {
	if (!document.cookie) return;

  var targetCookie =
    document.cookie
    .split("; ")
    .map((elem) => {
      var str = elem.split('=');
      return {key: str[0], value: str[1]};
    })
    .filter((cookie) => cookie.key == 'data');

  if (!targetCookie.some((cookie) => cookie.key == 'data')) return;

  return decodeURIComponent(targetCookie[0].value);
}

// __END__  "{{{1
// vim: expandtab softtabstop=2 shiftwidth=2
// vim: foldmethod=marker
<commit_msg>main.js: Remove unnecessary comment<commit_after>require('jquery');
require('jquery-mobile');
require('jquery.cookie');

// for flat-ui
require('jquery-ui');
require('jquery-ui-touch-punch');
require('../bower_components/bootstrap/dist/js/bootstrap.js');
require('bootstrap-switch');
require('bootstrap-tagsinput');
// require('holderjs');
// require('typeahead.js');
require('select2');
require('../bower_components/flat-ui/js/radiocheck.js');

import * as shiren4 from '../es6/model/shiren4.js';

$(() => {
  $(':checkbox').checkboxradio();

  $('a.reset-checkboxes').click(() => {
    if(window.confirm('リセットしますか？'))
      clearCheckboxes();
  });

  loadFromCookie();
  $(':checkbox').change(() => saveToCookie());
});

// Clear CheckBoxes "{{{1

var clearCheckboxes = () => {
  $(':checkbox')
  .prop('checked', false)
  .checkboxradio('refresh');

  saveToCookie();
};

// Save/Load Cookie Data "{{{1

var loadFromCookie = () => {
  if (typeof getCookie() === "undefined") return;

  var cookieData = JSON.parse(getCookie());
  Object.keys(cookieData)
  .forEach((key) => {
    $(`#${key} :checkbox`)
    .each((index, elem) =>
      $(elem)
      .prop('checked', cookieData[key][$(elem).data('id')])
      .checkboxradio('refresh')
    );
  });
};

var saveToCookie = () => {
  var ary = {};
    $(':checkbox')
    .each((index, val) => {
      var t = $(val).data('type');
      if (!(t in ary))
        ary[t] = {};
      ary[t][$(val).data('id')] = $(val).prop('checked');
    });
  var json = JSON.stringify(ary);
  setCookie(json);
};

var setCookie = (data) => {
  var thirtyDaysLater = new Date(Date.now() + 30 * 24 * 60 * 60 * 1000);
  document.cookie = `data=${encodeURIComponent(data)};path=${location.pathname};expires=${thirtyDaysLater.toGMTString()}`;
}

var getCookie = () => {
	if (!document.cookie) return;

  var targetCookie =
    document.cookie
    .split("; ")
    .map((elem) => {
      var str = elem.split('=');
      return {key: str[0], value: str[1]};
    })
    .filter((cookie) => cookie.key == 'data');

  if (!targetCookie.some((cookie) => cookie.key == 'data')) return;

  return decodeURIComponent(targetCookie[0].value);
}

// __END__  "{{{1
// vim: expandtab softtabstop=2 shiftwidth=2
// vim: foldmethod=marker
<|endoftext|>


<commit_before>#!/usr/bin/env node

import { install } from 'source-map-support';
install();

import 'babel-polyfill';
// Libs
import chalk from 'chalk';
import program from 'commander';
import fs from 'fs-extra';
import moment from 'moment';
import co from 'co';
import prompt from 'co-prompt';
import templateJSON from '../templates/default.json';

function makeNote(jsonObj) {
  var dir = getDateDir();
  var toMd = `${dir}/note.md`;
  var noteMd = fs.createWriteStream(toMd);

  Object.keys(jsonObj).map(function(title) {
    noteMd.write("# " + title + "\n");
    Object.keys(jsonObj[title]['items']).map(function(items, index){
      var status = jsonObj[title]['items'][items]['status'];
      var checkBox = '- [ ]';
      var itemIndex = ` ${index}.) `;
      if (status === 'complete') {
        checkBox = '- [x]';
      } else if (status === 'failed') {
        checkBox = '- [-]';
      }
      noteMd.write(checkBox + itemIndex + jsonObj[title]['items'][items]['description'] + "\n");
    });
    noteMd.write("\n");
  });
  // console.log(`note for ${dir} modified!`);
}

function addNote(noteObj, key) {
  var dir = getDateDir();
  var toData = `${dir}/data.json`;
  var dataJSON = fs.readJsonSync(toData);
  var noteString = noteObj.reduce(function(memo, word){
    return memo + ' ' + word;
  });

  var descriptionObj = {
    description: noteString,
    status: 'incomplete',
  };

  // modify toData
  Object.keys(dataJSON).map(function(note){
    if (dataJSON[note]['cli-ref'] === key) {
      dataJSON[note]['items'].push(descriptionObj);
      fs.writeJsonSync(toData, dataJSON);
    }
  });
  makeNote(dataJSON);
}

function changeStatus(index, key, cb) {
  var dir = getDateDir();
  var toData = `${dir}/data.json`;
  var dataJSON = fs.readJsonSync(`${dir}/data.json`);
  var cliFound = false;
  Object.keys(dataJSON).map(function(note, noteIndex){
    if (dataJSON[note]['cli-ref'] === key) {
      cliFound = true;
      if (!dataJSON[note]['items'][index]) {
        throw new Error(`index ${index} in "${key}" object does not exist`);
      }
      cb(dataJSON[note]['items'], index);
      fs.writeJsonSync(toData, dataJSON);
    } else if (Object.keys(dataJSON).length === (noteIndex + 1) && !cliFound) {
      throw new Error(`"${key}" <cli-ref> does not exist`);
    }
  });
  makeNote(dataJSON);
}

function removeNote(arry, index) {
  arry.splice(index, 1);
}

function completeNote(arry, index) {
  arry[index]['status'] = 'complete';
}

function incompleteNote(arry, index) {
  arry[index]['status'] = 'incomplete';
}

function failNote(arry, index) {
  arry[index]['status'] = 'failed';
}

function initializeNotes(userDir) {
  // TODO: if you create a note with out a `/` trailing slash
  // "/Users/georgemichael/notes/"
  //  vs.
  // "/Users/georgemichael/notes"

  // the latter will get us in trouble with `nonote new`
  // need to ensure one or the other at init and create time

  var rcFile = `${process.env.HOME}/.nonoterc.json`;
  fs.closeSync(fs.openSync(rcFile, 'w'));

  var dotFileJSON = {}
  dotFileJSON.notesDirectory = userDir;

  fs.writeJsonSync(rcFile, dotFileJSON);
  console.log(chalk.green('Success!'));
  console.log(' ');
  console.log('dotfile `.nonoterc.json` created at $HOME' );
  console.log(' ');
  console.log('Notes will be made in this directory: ')
  console.log(chalk.cyan(dotFileJSON.notesDirectory));
  console.log(' ');
}
function getRootDir() {
  var config = `${process.env.HOME}/.nonoterc.json`;
  // TODO: handle the case of `nonote new` when `nonote init` has not been run
  return fs.readJsonSync(config).notesDirectory;
}

function getDateDir(type) {
  var today = moment().format("DD-MM-YYYY");
  var notesDir = getRootDir();
  var days = `${notesDir}days/`;
  var toDir = days + today;
  return toDir;
}

function createDir(create, path) {
  var templateDest = path + '/templates/';
  var templateFile = path + '/templates/default.json';
  if (create) {
    fs.mkdirsSync(path);
    fs.mkdirsSync(templateDest);
    fs.closeSync(fs.openSync(templateFile, 'w'));
    fs.writeJsonSync(templateFile, templateJSON);
    console.log(' ');
    console.log(chalk.green('Success!'));
  } else {
    console.log(' ');
    console.log('Make sure that dir exists and has a templates dir in it with a note config!');
  }
}

program
  .version('0.0.1')
  .command('new [template]')
  .alias('n')
  .description('create a new note for the day')
  .action(function(template, cmd) {
    if(!template) {
      template = 'default';
    }
    var notePath = getDateDir();
    var noteJSON = `${notePath}/data.json`;
    var rootDir = getRootDir();
    var templateData = `${rootDir}/templates/${template}.json`;

    console.log(chalk.cyan(`creating new note from the ${template} template!`));

    fs.mkdirsSync(notePath);
    fs.copySync(templateData, noteJSON);
    makeNote(fs.readJsonSync(noteJSON));

    console.log(chalk.white('new note created'));
  });

program
  .command('init')
  .description('initializes notes')
  .action(function() {
    co(function *() {

      var notesDirPath = yield prompt('notes directory path (from $HOME): ');
      var homePath = `${process.env.HOME}/${notesDirPath}`;
      initializeNotes(homePath);

      var shouldCreate = yield prompt.confirm(`Would you like me to create "${homePath}" for you?(Recommended) [y/N] `);
      createDir(shouldCreate, homePath);
      console.log('Start taking notes with', chalk.cyan('nonote new!'));
      // TODO: create a readme
      process.exit();
    })
  });

program
  .command('add [cli-ref] <notes...>')
  .alias('a')
  .description('add note to object')
  .action(function(ref, note, cmd) {
    try {
      addNote(note, ref);
      console.log(chalk.green('note added!'));
    } catch (e) {
      console.log(chalk.red(e));
    }
  });

program
  .command('remove [cli-ref] <index>')
  .alias('r')
  .description('remove note from note object')
  .action(function(ref, note, cmd) {
    try {
      changeStatus(note, ref, removeNote);
      console.log(chalk.green(`note at index[${note}] was removed!`));
    } catch (e) {
      console.log(chalk.red(e));
    }
  });

program
  .command('complete [cli-ref] <index>')
  .alias('c')
  .description('mark item as complete')
  .action(function(ref, note, cmd) {
    try {
      changeStatus(note, ref, completeNote);
      console.log(chalk.green(`note at index[${note}] was marked as complete!`));
    } catch (e) {
      console.log(chalk.red(e));
    }
  });

program
  .command('incomplete [cli-ref] <index>')
  .alias('i')
  .description('mark item as incomplete')
  .action(function(ref, note, cmd) {
    try {
      changeStatus(note, ref, incompleteNote);
      console.log(chalk.green(`note at index[${note}] was marked as incomplete!`));
    } catch (e) {
      console.log(chalk.red(e));
    }
  });

program
  .command('failed [cli-ref] <index>')
  .alias('f')
  .description('mark item as failed')
  .action(function(ref, note, cmd) {
    try {
      changeStatus(note, ref, failNote);
      console.log(chalk.green(`note at index[${note}] was marked as failed :(`));
    } catch (e) {
      console.log(chalk.red(e));
    }
  });

  program.parse(process.argv);

<commit_msg>Fix // and trailing / bugs on `nono init`<commit_after>#!/usr/bin/env node

import { install } from 'source-map-support';
install();

import 'babel-polyfill';
// Libs
import chalk from 'chalk';
import program from 'commander';
import fs from 'fs-extra';
import moment from 'moment';
import co from 'co';
import prompt from 'co-prompt';
import templateJSON from '../templates/default.json';

function makeNote(jsonObj) {
  var dir = getDateDir();
  var toMd = `${dir}/note.md`;
  var noteMd = fs.createWriteStream(toMd);

  Object.keys(jsonObj).map(function(title) {
    var cliRef = jsonObj[title]['cli-ref'];
    noteMd.write(`# ${title} --> ${cliRef}\n`);
    Object.keys(jsonObj[title]['items']).map(function(items, index){
      var status = jsonObj[title]['items'][items]['status'];
      var checkBox = '- [ ]';
      var itemIndex = ` ${index}.) `;
      if (status === 'complete') {
        checkBox = '- [x]';
      } else if (status === 'failed') {
        checkBox = '- [-]';
      }
      noteMd.write(checkBox + itemIndex + jsonObj[title]['items'][items]['description'] + "\n");
    });
    noteMd.write("\n");
  });
  // console.log(`note for ${dir} modified!`);
}

function addNote(noteObj, key) {
  var dir = getDateDir();
  var toData = `${dir}/data.json`;
  var dataJSON = fs.readJsonSync(toData);
  var noteString = noteObj.reduce(function(memo, word){
    return memo + ' ' + word;
  });

  var descriptionObj = {
    description: noteString,
    status: 'incomplete',
  };

  // modify toData
  Object.keys(dataJSON).map(function(note){
    if (dataJSON[note]['cli-ref'] === key) {
      dataJSON[note]['items'].push(descriptionObj);
      fs.writeJsonSync(toData, dataJSON);
    }
  });
  makeNote(dataJSON);
}

function changeStatus(index, key, cb) {
  var dir = getDateDir();
  var toData = `${dir}/data.json`;
  var dataJSON = fs.readJsonSync(`${dir}/data.json`);
  var cliFound = false;
  Object.keys(dataJSON).map(function(note, noteIndex){
    if (dataJSON[note]['cli-ref'] === key) {
      cliFound = true;
      if (!dataJSON[note]['items'][index]) {
        throw new Error(`index ${index} in "${key}" object does not exist`);
      }
      cb(dataJSON[note]['items'], index);
      fs.writeJsonSync(toData, dataJSON);
    } else if (Object.keys(dataJSON).length === (noteIndex + 1) && !cliFound) {
      throw new Error(`"${key}" <cli-ref> does not exist`);
    }
  });
  makeNote(dataJSON);
}

function removeNote(arry, index) {
  arry.splice(index, 1);
}

function completeNote(arry, index) {
  arry[index]['status'] = 'complete';
}

function incompleteNote(arry, index) {
  arry[index]['status'] = 'incomplete';
}

function failNote(arry, index) {
  arry[index]['status'] = 'failed';
}

function initializeNotes(userDir) {
  var lastChar = userDir.substr(userDir.length - 1);
  if ( lastChar === "/" ) {
    userDir = userDir.slice(0, -1);
  }

  var doubleIndex = userDir.indexOf("//");
  if ( doubleIndex > -1 ) {
    userDir = userDir.slice(0, doubleIndex) + userDir.slice(doubleIndex + 1);
  }

  var rcFile = `${process.env.HOME}/.nonoterc.json`;
  fs.closeSync(fs.openSync(rcFile, 'w'));

  var dotFileJSON = {}
  dotFileJSON.notesDirectory = userDir;

  fs.writeJsonSync(rcFile, dotFileJSON);
  console.log(chalk.green('Success!'));
  console.log(' ');
  console.log('dotfile `.nonoterc.json` created at $HOME' );
  console.log(' ');
  console.log('Notes will be made in this directory: ')
  console.log(chalk.cyan(dotFileJSON.notesDirectory));
  console.log(' ');
}
function getRootDir() {
  var config = `${process.env.HOME}/.nonoterc.json`;
  // TODO: handle the case of `nonote new` when `nonote init` has not been run
  return fs.readJsonSync(config).notesDirectory;
}

function getDateDir(type) {
  var today = moment().format("DD-MM-YYYY");
  var notesDir = getRootDir();
  var days = `${notesDir}/days/`;
  var toDir = days + today;
  return toDir;
}

function createDir(create, path) {
  var templateDest = path + '/templates/';
  var templateFile = path + '/templates/default.json';
  if (create) {
    fs.mkdirsSync(path);
    fs.mkdirsSync(templateDest);
    fs.closeSync(fs.openSync(templateFile, 'w'));
    fs.writeJsonSync(templateFile, templateJSON);
    console.log(' ');
    console.log(chalk.green('Success!'));
  } else {
    console.log(' ');
    console.log('Make sure that dir exists and has a templates dir in it with a note config!');
  }
}

program
  .version('0.0.1')
  .command('new [template]')
  .alias('n')
  .description('create a new note for the day')
  .action(function(template, cmd) {
    if(!template) {
      template = 'default';
    }
    var notePath = getDateDir();
    var noteJSON = `${notePath}/data.json`;
    var rootDir = getRootDir();
    var templateData = `${rootDir}/templates/${template}.json`;

    console.log(chalk.cyan(`creating new note from the ${template} template!`));

    fs.mkdirsSync(notePath);
    fs.copySync(templateData, noteJSON);
    makeNote(fs.readJsonSync(noteJSON));

    console.log(chalk.white('new note created'));
  });

program
  .command('init')
  .description('initializes notes')
  .action(function() {
    co(function *() {

      var notesDirPath = yield prompt('notes directory path (from $HOME): ');
      var homePath = `${process.env.HOME}/${notesDirPath}`;
      initializeNotes(homePath);

      var shouldCreate = yield prompt.confirm(`Would you like me to create "${homePath}" for you?(Recommended) [y/N] `);
      createDir(shouldCreate, homePath);
      console.log('Start taking notes with', chalk.cyan('nonote new!'));
      // TODO: create a readme
      process.exit();
    })
  });

program
  .command('add [cli-ref] <notes...>')
  .alias('a')
  .description('add note to object')
  .action(function(ref, note, cmd) {
    try {
      addNote(note, ref);
      console.log(chalk.green('note added!'));
    } catch (e) {
      console.log(chalk.red(e));
    }
  });

program
  .command('remove [cli-ref] <index>')
  .alias('r')
  .description('remove note from note object')
  .action(function(ref, note, cmd) {
    try {
      changeStatus(note, ref, removeNote);
      console.log(chalk.green(`note at index[${note}] was removed!`));
    } catch (e) {
      console.log(chalk.red(e));
    }
  });

program
  .command('complete [cli-ref] <index>')
  .alias('c')
  .description('mark item as complete')
  .action(function(ref, note, cmd) {
    try {
      changeStatus(note, ref, completeNote);
      console.log(chalk.green(`note at index[${note}] was marked as complete!`));
    } catch (e) {
      console.log(chalk.red(e));
    }
  });

program
  .command('incomplete [cli-ref] <index>')
  .alias('i')
  .description('mark item as incomplete')
  .action(function(ref, note, cmd) {
    try {
      changeStatus(note, ref, incompleteNote);
      console.log(chalk.green(`note at index[${note}] was marked as incomplete!`));
    } catch (e) {
      console.log(chalk.red(e));
    }
  });

program
  .command('failed [cli-ref] <index>')
  .alias('f')
  .description('mark item as failed')
  .action(function(ref, note, cmd) {
    try {
      changeStatus(note, ref, failNote);
      console.log(chalk.green(`note at index[${note}] was marked as failed :(`));
    } catch (e) {
      console.log(chalk.red(e));
    }
  });

  program.parse(process.argv);

<|endoftext|>


<commit_before>var essaygen = {
    generate: function(quotes,options) {
        // set option defaults
        var litType = "short story";
        var protagonist = "the protagonist";
        var techniques = ["alliteration", "simile", "metaphor", "personification", "listing", "anthropomorphism", "assonance", "euphemism", "pathetic fallacy"];
        var writerName = "the writer";
        var outputType = "default";
        var adjectives = ["lively", "realistic", "cheerful", "dramatic", "happy", "joyous", "carefree", "radiant", "lighthearted"];

        var lineBreaker = "\n";

        if (options) {
            if ("type" in options) {
                litType = options.type;
            }
            if ("protagonist" in options) {
                protagonist = options.protagonist;
            }
            if ("techniques" in options) {
                techniques = options.techniques;
            }
            if ("writer" in options) {
                writerName = options.writer;
            }
            if ("output" in options) {
                outputType = options.output;
            }
            if ("adjectives" in options) {
                adjectives = options.adjectives;
            }
        }

        if (outputType == "html") {
            lineBreaker = "
";
        }

        var randomInArray = function(array){
            return array[Math.round(Math.random()*(array.length-1))];
        }

        var points = [
            [
                "The writer skilfully uses language and techniques like " + randomInArray(techniques) + " and " + randomInArray(techniques) + " to effectively convey his message.",
                "In this " + litType + ", " + writerName + " tries to emphasize " + protagonist + "'s personality.",
                "The writer uses a combination of " + randomInArray(techniques) + " and " + randomInArray(techniques) + " to bring out " + protagonist + "'s " + randomInArray(adjectives) + " thoughts and feelings to the reader."
            ],[
                "An example of this can be found in this quote:",
                "This makes the " + litType + " seem more " + randomInArray(adjectives) + " and " + randomInArray(adjectives) + ", as shown in the following quote:"
            ]
        ];
        var explanations = [
            [
                "This suggests that " + writerName + " feels very strongly about the situation, as shown in the " + randomInArray(techniques) + " in the above quote. It causes the reader to associate the two things, which adds to the " + randomInArray(adjectives) + " atmosphere of the " + litType +"."
            ],[
                "Also, the writer effectively uses " + randomInArray(techniques) + " in his " + litType + ", to let the reader experience " + protagonist + "'s " + randomInArray(adjectives) + " feelings."
            ]
        ];
        var finalEssay = [];

        while (quotes.length > 0) {
            var point = randomInArray(points[0]) + " " + randomInArray(points[1]);
            var quote = quotes.shift();
            var explanation = randomInArray(explanations[0]) + " " + randomInArray(explanations[1]);
            var paragraph = point + " " + "\"" + quote + "\"" + ". " + explanation;
            finalEssay.push(paragraph);
        }

        return finalEssay.join(lineBreaker);
    }
};<commit_msg>Fixed variable substitution<commit_after>var essaygen = {
    generate: function(quotes,options) {
        // set option defaults
        var litType = "short story";
        var protagonist = "the protagonist";
        var techniques = ["alliteration", "simile", "metaphor", "personification", "listing", "anthropomorphism", "assonance", "euphemism", "pathetic fallacy"];
        var writerName = "the writer";
        var outputType = "default";
        var adjectives = ["lively", "realistic", "cheerful", "dramatic", "happy", "joyous", "carefree", "radiant", "lighthearted"];

        var lineBreaker = "\n";

        if (options) {
            if ("type" in options) {
                litType = options.type;
            }
            if ("protagonist" in options) {
                protagonist = options.protagonist;
            }
            if ("techniques" in options) {
                techniques = options.techniques;
            }
            if ("writer" in options) {
                writerName = options.writer;
            }
            if ("output" in options) {
                outputType = options.output;
            }
            if ("adjectives" in options) {
                adjectives = options.adjectives;
            }
        }

        if (outputType == "html") {
            lineBreaker = "
";
        }

        var randomInArray = function(array){
            return array[Math.round(Math.random()*(array.length-1))];
        }

        var points = [
            [
                "The writer skilfully uses language and techniques like %t% and %t% to effectively convey his message.",
                "In this %l%, %w% tries to emphasize %p%'s personality.",
                "The writer uses a combination of %t% and %t% to bring out %p%'s %a% thoughts and feelings to the reader."
            ],[
                "An example of this can be found in this quote: '%q%'",
                "This makes the %l% seem more %a% and %a%, as shown in the following quote: '%q%'"
            ]
        ];
        var explanations = [
            [
                "This suggests that %w% feels very strongly about the situation, as shown in the %t% in the above quote. It causes the reader to associate the two things, which adds to the %a% atmosphere of the %l%."
            ],[
                "Also, the writer effectively uses %t% in his %l%, to let the reader experience %p%'s %a% feelings."
            ]
        ];
        var finalEssay = [];

        for (i=0;i<quotes.length;i++) {
            /*var point = randomInArray(points[0]) + " " + randomInArray(points[1]);
            var quote = quotes.shift();
            var explanation = randomInArray(explanations[0]) + " " + randomInArray(explanations[1]);
            var paragraph = point + " " + "\"" + quote + "\"" + ". " + explanation;
            finalEssay.push(paragraph);*/

            var point = randomInArray(points[0]) + " " + randomInArray(points[1]);
            while (point.indexOf("%t%") != -1 || point.indexOf("%l%") != -1 || point.indexOf("%w%") != -1 || point.indexOf("%p%") != -1 || point.indexOf("%a%") != -1 || point.indexOf("%q%") != -1) {
                point = point.replace("%t%",randomInArray(techniques)).replace("%l%",litType).replace("%w%",writerName).replace("%p%",protagonist).replace("%a%",randomInArray(adjectives)).replace("%q%",quotes[i]);
            }

            var explanation = randomInArray(explanations[0]) + " " + randomInArray(explanations[1]);
            while (explanation.indexOf("%t%") != -1 || explanation.indexOf("%l%") != -1 || explanation.indexOf("%w%") != -1 || explanation.indexOf("%p%") != -1 || explanation.indexOf("%a%") != -1 || explanation.indexOf("%q%") != -1) {
                explanation = explanation.replace("%t%",randomInArray(techniques)).replace("%l%",litType).replace("%w%",writerName).replace("%p%",protagonist).replace("%a%",randomInArray(adjectives)).replace("%q%",quotes[i]);
            }

            var paragraph = point + ". " + explanation;
            finalEssay.push(paragraph);
        }

        return finalEssay.join(lineBreaker);
    }
};<|endoftext|>


<commit_before>// eventSky.js - Event Aggregate utility/tool for front-end apps
// https://github.com/crobinson42/event-sky
// Cory Robinson

(function () {
	// local use error logger
	var error = function(msg,options) {
		throw new Error('eventSky.js: ' + msg, options || null);
	};

	var init = function () {
		alert('Event Sky Initialized!');
		console.dir(this);
	};

	// event constructor
	function Event(name,triggerPoints) {
		this.name = {
			before 	: [],
			on 		: [],
			after 	: []
		};

		return this;
	}

	// The main object that houses event on/off & handlers
	var eventStack = {
		/*
		'eventName' : {
		}
		'id' 	: {
			'eventId' : eventName,
		}
		mailAlert = event.on('newMessage',null, function (data) {
			// do work
		});
		event.trigger('newMessage', function (data) {

		});
		event.off(mailAlert)
		*/
	};

	var generateEventId = function () {
		return new Date().getTime() + Math.floor(Math.random() * 100);
	};

	var on = function (event, options, handler) {
		// README
		// 'event', 'handler' == required
		// 'options' == optional
		// this method tests if event is an object and if it is
		// 	it assumes a structure like so:
		//		.on({ event : 'click',
		//			options : {opt1:null, opt2:null},
		//			handler : function() });
		//
		// If event is a string, it tests if the 2nd arg is a function
		// 	or an options object
		var eventType,
			optionsObj,
			handlerMethod,
			eventListenerId = generateEventId();

		if (event && typeof event == 'object') {
			eventType = (event.event)
				? event.event
				: error('No event specified.');
			optionsObj = event.options || null;
			handlerMethod = event.handler || event.handlerMethod || null;
		}
		else {
			eventType = event
					? event
					: error('No event specified.');
			optionsObj = options && typeof options != 'function'
					? options
					: null;
			handlerMethod = (!optionsObj)
					? optionsObj
					: (handlerMethod)
						? handlerMethod
						: null;
		}

		eventStack[event] = handler;

		return eventListenerId;
	};

	var before = function (event, options, handler) {

	};

	var after = function (event, options, handler) {

	};

	var off = function (eventOrId, options) {

	};

	var trigger = function (event) {

	};

	var getEventList = function () {

	};

	// Exposed methods
	window.eventSky = {
		init : init,
		// subscribe to an event
		on 			: on,
		// subscribe to be triggered before other
		before 		: before,
		// subscribe to be triggered after other
		after 		: after,
		// unsubscribe to an event
		off 		: off,
		// trigger an event
		trigger 	: trigger,
		//
		// list of events
		events 		: getEventList
	};
})();

<commit_msg>first working version<commit_after>// eventSky.js - Event Aggregate utility/tool for front-end apps
// https://github.com/crobinson42/event-sky
// Cory Robinson

// TODO:
/*
	-readme about window.eventSky
	-write readme info for init() & firehose

*/

(function () {
	// local use error logger
	var error = function(msg,options) {
		throw new Error('eventSky.js: ' + msg, options || null);
	};

	var firehose = function (input,options) {
		if (firehose.active) {
			console.log(input,options);
		}
	};
	firehose.active = false;

	var init = function (options) {
		if (options) {
			firehose.active = (options.firehose) ? true : false;
		}
	};

	// The main object that houses event on/off & handlers
	var eventStack = {
		/*
		newMail : {
			before : {},
			on :	{
				'12345' : function(){}
			},
			after : {}
		}
		*/
	};
	// a map of event id's for eventStack
	var eventStackIdMap = {
		/*
			12345 = {
				event:'eventName',
				when:'on/before/after'
			}
		*/
	};

	//  eventStackIdMap constructor
	var EventStackIdMap = function(when,event) {
		this.event 	= event;
		this.when 	= when;
		return this;
	};

	// event constructor
	var Event = function() {
		this.before 	= {};
		this.on 			= {};
		this.after	 	= {};
		return this;
	};

	var generateEventId = function () {
		return new Date().getTime() + Math.floor(Math.random() * 100);
	};

	// ensures the event is listed as a key in eventStack
	var ensureEventExists = function(event) {
		if (!event) {
			error('ensureEventExists was not passed an event.');
	 		return false;
		}
		// return if event key already exists
		if (eventStack && eventStack[event]) { return true; }
		// create event key & event obj
		eventStack[event] = new Event();
		return true;
	};

	// This is called/used by .on(), .after(), .before()
	addEventListenerAction = function (when,event,options,handler) {
		console.log(when,event,options,handler);
		var eventType,
			optionsObj,
			handlerMethod,
			eventListenerId = generateEventId();

		eventType = (event)
				? event
				: error('No event specified.');
		optionsObj = (options && typeof options != 'function')
				? options
				: null;
		handlerMethod = (optionsObj)
				? optionsObj
				: (!handler)
					? options
					: null;

		// now verify all vars are set to proceed
		console.log(when,eventType,optionsObj,handlerMethod);
		if (!when || !eventType || !handlerMethod) {
			return error(when + '() cannot be set due to invalid arguments.')
		}

		ensureEventExists(eventType);

		// add to event stack
		eventStack[eventType][when][eventListenerId] = handlerMethod;
		// add to eventStackIdMap
		eventStackIdMap[eventListenerId] = new EventStackIdMap(when,eventType);

		return eventListenerId;
	};

	var on = function (event, options, handler) {
		// README
		// * see addEventListenerAction() for argument requirements
		return addEventListenerAction('on',event,options,handler);
	};

	var before = function (event, options, handler) {
		// README
		// * see addEventListenerAction() for argument requirements
		return addEventListenerAction('before',event,options,handler);
	};

	var after = function (event, options, handler) {
		// README
		// * see addEventListenerAction() for argument requirements
		return addEventListenerAction('after',event,options,handler);
	};

	var off = function (eventOrId, options) {
		// if event, overwrite key w/ new event in eventStack
		if (eventOrId && eventStack[eventOrId]) {
			// delete  eventStack[eventOrId];
			eventStack[eventOrId] = new Event();
		}
		else { // if id, only remove key:val
			var map = eventStackIdMap[eventOrId];
			// lookup id
			if (!map) { return error('off() cannot map event ID.'); }
			delete eventStackIdMap[eventOrId];
			delete eventStack[map.event][map.when][eventOrId];
		}
	};

	var trigger = function (eventOrId,data) {
			var map = eventStackIdMap[eventOrId];
			if (typeof map == 'object') { // eventOrId is an ID..
				// only trigger method assigned to this id
				firehose('Trigger:'+map.event +':'+map.when+':'+eventOrId);
				eventStack[map.event][map.when][eventOrId](data);
			} else { // eventOrId is an event
				// trigger event in sequences
				if (eventStack[eventOrId]) {
					Object.keys(eventStack[eventOrId].before).forEach(function(i) {
						firehose('Trigger:'+eventOrId +':before:*');
						eventStack[eventOrId].before[i](data);
					});
					Object.keys(eventStack[eventOrId].on).forEach(function(i) {
						firehose('Trigger:'+eventOrId +':on:*');
						eventStack[eventOrId].on[i](data);
					});
					Object.keys(eventStack[eventOrId].after).forEach(function(i) {
						firehose('Trigger:'+eventOrId +':after:*');
						eventStack[eventOrId].after[i](data);
					});
				}
			}
	};

	var getEventList = function () {
		return Object.keys(eventStack);
	};

	// Exposed methods
	window.eventSky = {
		init : init,
		// subscribe to an event
		on 			: on,
		// subscribe to be triggered before other
		before 		: before,
		// subscribe to be triggered after other
		after 		: after,
		// unsubscribe to an event
		off 		: off,
		// trigger an event
		trigger 	: trigger,
		// list of events
		events 		: getEventList,
		// dev
		dev				:	{ eventStack : eventStack, eventMap : eventStackIdMap }
	};
})();
<|endoftext|>


<commit_before>const path = require('path')

const webpack = require('webpack')
const CopyPlugin = require('copy-webpack-plugin')

const HandlerPlugin = require('@hap-toolkit/packager/lib/plugin/handler-plugin')
const ZipPlugin = require('@hap-toolkit/packager/lib/plugin/zip-plugin')
const NotifyPlugin = require('@hap-toolkit/packager/lib/plugin/notify-plugin')

const Css2jsonPlugin = require('@hap-toolkit/dsl-vue/lib/plugin/css2json-plugin')

const InstVuePlugin = require('./plugin/instvue-plugin')

const parseManifest = require('./manifest/index')
const validate = require('./validate')

parseManifest(process.UNI_PAGES, process.UNI_MANIFEST)

validate()

const env = {
  // 平台：native
  NODE_PLATFORM: 'native',
  // 阶段: dev|test|release
  NODE_PHASE: process.env.NODE_PHASE
}

const dslFilename = ('vue.' + (process.env.NODE_ENV === 'production' ? 'prod' : 'dev') + '.js')

const manifest = global.framework.manifest

function genPriorities (entryPagePath) {
  const o = [/^i18n\/.+\.json$/i, 'manifest.json', 'app.js', /^common\//i]
  if (entryPagePath) {
    o.splice(3, 0, new RegExp(`^${entryPagePath}/$`), new RegExp(`^${entryPagePath}/.+`))
  } else console.error('未配置入口页面')
  return o
}

module.exports = {
  devtool: false,
  entry () {
    return process.UNI_ENTRY
  },
  output: {
    filename: '[name].js',
    chunkFilename: '[name].js'
  },
  optimization: {
    splitChunks: false,
    runtimeChunk: false
  },
  externals: {
    vue: 'Vue'
  },
  module: {
    rules: [{
      // 暂不考虑ts
      test: path.resolve(process.env.UNI_INPUT_DIR, 'main.js'),
      use: [{
        loader: path.resolve(__dirname, 'loader/main-loader')
      }]
    }]
  },
  plugins: [
    new webpack.DefinePlugin({
      // 平台：na
      ENV_PLATFORM: JSON.stringify(env.NODE_PLATFORM),
      // 阶段: dev|test|release
      ENV_PHASE: JSON.stringify(env.NODE_PHASE),
      ENV_PHASE_DV: env.NODE_PHASE === 'dev',
      ENV_PHASE_QA: env.NODE_PHASE === 'test',
      ENV_PHASE_OL: env.NODE_PHASE === 'prod'
    }),
    new CopyPlugin([{
      from: path.resolve(__dirname, '../dist/' + dslFilename),
      to: 'dsl.js'
    }]),
    new HandlerPlugin({}),
    new Css2jsonPlugin(),
    new InstVuePlugin(),
    new ZipPlugin({
      name: manifest.package,
      icon: manifest.icon,
      versionCode: manifest.versionCode,
      output: path.resolve(process.env.UNI_OUTPUT_DIR, '..'),
      pathBuild: process.env.UNI_OUTPUT_DIR,
      pathSignFolder: './sign',
      sign: process.env.NODE_ENV === 'production' ? 'release' : 'debug',
      priorities: genPriorities(manifest.router.entry),
      subpackages: undefined,
      comment: '',
      cwd: process.env.UNI_INPUT_DIR,
      disableStreamPack: undefined,
      disableSubpackages: undefined
    }),
    new NotifyPlugin()
  ]
}
<commit_msg>feat(qa): uniCloud<commit_after>const path = require('path')

const webpack = require('webpack')
const CopyPlugin = require('copy-webpack-plugin')

const HandlerPlugin = require('@hap-toolkit/packager/lib/plugin/handler-plugin')
const ZipPlugin = require('@hap-toolkit/packager/lib/plugin/zip-plugin')
const NotifyPlugin = require('@hap-toolkit/packager/lib/plugin/notify-plugin')

const Css2jsonPlugin = require('@hap-toolkit/dsl-vue/lib/plugin/css2json-plugin')

const InstVuePlugin = require('./plugin/instvue-plugin')

const parseManifest = require('./manifest/index')
const validate = require('./validate')

parseManifest(process.UNI_PAGES, process.UNI_MANIFEST)

validate()

const env = {
  // 平台：native
  NODE_PLATFORM: 'native',
  // 阶段: dev|test|release
  NODE_PHASE: process.env.NODE_PHASE
}

const dslFilename = ('vue.' + (process.env.NODE_ENV === 'production' ? 'prod' : 'dev') + '.js')

const manifest = global.framework.manifest

function genPriorities (entryPagePath) {
  const o = [/^i18n\/.+\.json$/i, 'manifest.json', 'app.js', /^common\//i]
  if (entryPagePath) {
    o.splice(3, 0, new RegExp(`^${entryPagePath}/$`), new RegExp(`^${entryPagePath}/.+`))
  } else console.error('未配置入口页面')
  return o
}

const uniCloudPath = require.resolve('@dcloudio/vue-cli-plugin-uni/packages/uni-cloud/dist/index.js')

module.exports = {
  devtool: false,
  entry () {
    return process.UNI_ENTRY
  },
  output: {
    filename: '[name].js',
    chunkFilename: '[name].js'
  },
  optimization: {
    splitChunks: false,
    runtimeChunk: false
  },
  externals: {
    vue: 'Vue'
  },
  module: {
    rules: [{
      // 暂不考虑ts
      test: path.resolve(process.env.UNI_INPUT_DIR, 'main.js'),
      use: [{
        loader: path.resolve(__dirname, 'loader/main-loader')
      }]
    }]
  },
  plugins: [
    new webpack.DefinePlugin({
      // 平台：na
      ENV_PLATFORM: JSON.stringify(env.NODE_PLATFORM),
      // 阶段: dev|test|release
      ENV_PHASE: JSON.stringify(env.NODE_PHASE),
      ENV_PHASE_DV: env.NODE_PHASE === 'dev',
      ENV_PHASE_QA: env.NODE_PHASE === 'test',
      ENV_PHASE_OL: env.NODE_PHASE === 'prod'
    }),
    new webpack.ProvidePlugin({
      uniCloud: [uniCloudPath, 'default']
    }),
    new CopyPlugin([{
      from: path.resolve(__dirname, '../dist/' + dslFilename),
      to: 'dsl.js'
    }]),
    new HandlerPlugin({}),
    new Css2jsonPlugin(),
    new InstVuePlugin(),
    new ZipPlugin({
      name: manifest.package,
      icon: manifest.icon,
      versionCode: manifest.versionCode,
      output: path.resolve(process.env.UNI_OUTPUT_DIR, '..'),
      pathBuild: process.env.UNI_OUTPUT_DIR,
      pathSignFolder: './sign',
      sign: process.env.NODE_ENV === 'production' ? 'release' : 'debug',
      priorities: genPriorities(manifest.router.entry),
      subpackages: undefined,
      comment: '',
      cwd: process.env.UNI_INPUT_DIR,
      disableStreamPack: undefined,
      disableSubpackages: undefined
    }),
    new NotifyPlugin()
  ]
}
<|endoftext|>


<commit_before>import React, { PropTypes } from 'react';

import RJSForm from 'react-jsonschema-form/lib/index';

import Button from 'react-bootstrap/lib/Button';

import BooleanField from './fields/BooleanField';
import ObjectField from './fields/ObjectField';
import StringField from './fields/StringField';
import FieldTemplate from './templates/FieldTemplate';
import SwitchWidget from './widgets/SwitchWidget';
import TabsWidget from './widgets/TabsWidget';
import KeyValueWidget from './widgets/KeyValueWidget';
import MultiSelectTagWidget from './widgets/MultiSelectTagWidget/MultiSelectTagWidget';

/**
 * @type {string} After trigger name for field value has changed
 */
const TRIGGER_AFTER = 'after';

const customWidgets = {
	toggle: SwitchWidget,
	tabs: TabsWidget,
	keyValue: KeyValueWidget,
	multiSelectTag: MultiSelectTagWidget,
};

const customUiSchema = {
	'ui:widget': ['toggle', 'tabs', 'keyValue', 'multiSelectTag'],
};

export function renderActionIcon(icon) {
	if (icon) {
		return ;
	}
	return null;
}

export function renderActions(actions, handleActionClick) {
	if (actions) {
		return actions.map((action, index) => (
			<Button
				key={index}
				bsStyle={action.style}
				type={action.type}
				onClick={handleActionClick(action.onClick)}
				title={action.title}
				name={action.name}
			>
				{renderActionIcon(action.icon)}
				{action.label}
			</Button>),
		);
	}
	return <Button bsStyle="primary" type="submit">Submit</Button>;
}

class Form extends React.Component {

	constructor(props) {
		super(props);
		this.handleSchemaChange = this.handleSchemaChange.bind(this);
		this.handleSchemaSubmit = this.handleSchemaSubmit.bind(this);
		this.handleActionClick = this.handleActionClick.bind(this);
	}

	handleSchemaSubmit(changes) {
		if (this.props.onSubmit) {
			this.props.onSubmit(changes);
		}
	}

	/**
	 * Handle changes only if modified field has "ui:trigger" option
	 * @param changes New formData
	 * @param id Form id is provided
	 * @param name Name of the modified field
	 * @param value New value of the field
	 * @param options Options from uiSchema for this field
	 */
	handleSchemaChange(changes, id, name, value, options) {
		const triggers = options && options.trigger;
		if (triggers && triggers.indexOf(TRIGGER_AFTER) !== -1) {
			if (this.props.onChange) {
				this.props.onChange(changes, id, name, value);
			}
		}
	}

	handleActionClick(onClick) {
		return event => onClick(event, this.form.state);
	}

	render() {
		const schema = this.props.data && this.props.data.jsonSchema;
		if (!schema) {
			throw Error('You must provide data with valid JSON Schema');
		}

		const uiSchema = {
			...(this.props.data && this.props.data.uiSchema),
			...customUiSchema,
		};

		const formData = this.props.data && this.props.data.properties;

		const customFields = {
			BooleanField,
			ObjectField,
			StringField,
		};

		const customFormContext = {
			handleSchemaChange: this.handleSchemaChange,
		};

		return (
			<RJSForm
				{...this.props}
				schema={schema}
				uiSchema={uiSchema}
				formData={formData}
				formContext={customFormContext}
				fields={customFields}
				FieldTemplate={FieldTemplate}
				widgets={customWidgets}
				onChange={undefined}
				onSubmit={this.handleSchemaSubmit}
				ref={(c) => { this.form = c; }}
			>

					{renderActions(this.props.actions, this.handleActionClick)}

			</RJSForm>
		);
	}
}

export const DataPropTypes = PropTypes.shape({
	jsonSchema: PropTypes.object.isRequired,
	uiSchema: PropTypes.object,
	properties: PropTypes.oneOfType([
		PropTypes.object,
		PropTypes.string,
	]),
});

export const ActionsPropTypes = PropTypes.arrayOf(PropTypes.shape({
	style: PropTypes.string,
	type: PropTypes.oneOf(['submit', 'reset', 'button']),
	onClick: PropTypes.func,
	label: PropTypes.string,
	icon: PropTypes.string,
	title: PropTypes.string,
}));

Form.propTypes = {
	data: DataPropTypes.isRequired,
	onChange: PropTypes.func,
	onSubmit: PropTypes.func,
	actions: ActionsPropTypes,
	buttonBlockClass: PropTypes.string,
};

Form.defaultProps = {
	buttonBlockClass: 'form-actions',
};

export default Form;
<commit_msg>fix(forms): Fixes onClick error on submit action (#158)<commit_after>import React, { PropTypes } from 'react';

import RJSForm from 'react-jsonschema-form/lib/index';

import Button from 'react-bootstrap/lib/Button';

import BooleanField from './fields/BooleanField';
import ObjectField from './fields/ObjectField';
import StringField from './fields/StringField';
import FieldTemplate from './templates/FieldTemplate';
import SwitchWidget from './widgets/SwitchWidget';
import TabsWidget from './widgets/TabsWidget';
import KeyValueWidget from './widgets/KeyValueWidget';
import MultiSelectTagWidget from './widgets/MultiSelectTagWidget/MultiSelectTagWidget';

/**
 * @type {string} After trigger name for field value has changed
 */
const TRIGGER_AFTER = 'after';

const customWidgets = {
	toggle: SwitchWidget,
	tabs: TabsWidget,
	keyValue: KeyValueWidget,
	multiSelectTag: MultiSelectTagWidget,
};

const customUiSchema = {
	'ui:widget': ['toggle', 'tabs', 'keyValue', 'multiSelectTag'],
};

export function renderActionIcon(icon) {
	if (icon) {
		return ;
	}
	return null;
}

export function renderActions(actions, handleActionClick) {
	if (actions) {
		return actions.map((action, index) => (
			<Button
				key={index}
				bsStyle={action.style}
				type={action.type}
				onClick={handleActionClick(action.onClick)}
				title={action.title}
				name={action.name}
			>
				{renderActionIcon(action.icon)}
				{action.label}
			</Button>),
		);
	}
	return <Button bsStyle="primary" type="submit">Submit</Button>;
}

class Form extends React.Component {

	constructor(props) {
		super(props);
		this.handleSchemaChange = this.handleSchemaChange.bind(this);
		this.handleSchemaSubmit = this.handleSchemaSubmit.bind(this);
		this.handleActionClick = this.handleActionClick.bind(this);
	}

	handleSchemaSubmit(changes) {
		if (this.props.onSubmit) {
			this.props.onSubmit(changes);
		}
	}

	/**
	 * Handle changes only if modified field has "ui:trigger" option
	 * @param changes New formData
	 * @param id Form id is provided
	 * @param name Name of the modified field
	 * @param value New value of the field
	 * @param options Options from uiSchema for this field
	 */
	handleSchemaChange(changes, id, name, value, options) {
		const triggers = options && options.trigger;
		if (triggers && triggers.indexOf(TRIGGER_AFTER) !== -1) {
			if (this.props.onChange) {
				this.props.onChange(changes, id, name, value);
			}
		}
	}

	handleActionClick(onClick) {
		if (onClick) {
			return event => onClick(event, this.form.state);
		}
		return null;
	}

	render() {
		const schema = this.props.data && this.props.data.jsonSchema;
		if (!schema) {
			throw Error('You must provide data with valid JSON Schema');
		}

		const uiSchema = {
			...(this.props.data && this.props.data.uiSchema),
			...customUiSchema,
		};

		const formData = this.props.data && this.props.data.properties;

		const customFields = {
			BooleanField,
			ObjectField,
			StringField,
		};

		const customFormContext = {
			handleSchemaChange: this.handleSchemaChange,
		};

		return (
			<RJSForm
				{...this.props}
				schema={schema}
				uiSchema={uiSchema}
				formData={formData}
				formContext={customFormContext}
				fields={customFields}
				FieldTemplate={FieldTemplate}
				widgets={customWidgets}
				onChange={undefined}
				onSubmit={this.handleSchemaSubmit}
				ref={(c) => { this.form = c; }}
			>

					{renderActions(this.props.actions, this.handleActionClick)}

			</RJSForm>
		);
	}
}

export const DataPropTypes = PropTypes.shape({
	jsonSchema: PropTypes.object.isRequired,
	uiSchema: PropTypes.object,
	properties: PropTypes.oneOfType([
		PropTypes.object,
		PropTypes.string,
	]),
});

export const ActionsPropTypes = PropTypes.arrayOf(PropTypes.shape({
	style: PropTypes.string,
	type: PropTypes.oneOf(['submit', 'reset', 'button']),
	onClick: PropTypes.func,
	label: PropTypes.string,
	icon: PropTypes.string,
	title: PropTypes.string,
}));

Form.propTypes = {
	data: DataPropTypes.isRequired,
	onChange: PropTypes.func,
	onSubmit: PropTypes.func,
	actions: ActionsPropTypes,
	buttonBlockClass: PropTypes.string,
};

Form.defaultProps = {
	buttonBlockClass: 'form-actions',
};

export default Form;
<|endoftext|>


<commit_before>const _ = require('lodash');
const sha1File = require('sha1-file');

const FileUtils = require('../utils/file');

const frackinJson = FileUtils.frackinJson;
const frackinFile = FileUtils.frackinFile;
const starboundFile = FileUtils.starboundFile;

const getImageOrPlaceholder = (image, size, images, usedImages, thumb) => {
  const path = image;
  const sha1 = sha1File(path);
  thumb = thumb !== undefined ? thumb : true;
  if (images[sha1]) {
    return `[[${images[sha1].title}|${thumb ? 'thumb|' : ''}${size}]]`;
  } else {
    // Add the image to the list of used images
    usedImages.push(path);
    return `[[File:${path.replace(/\//g,"")}|${thumb ? 'thumb|' : ''}${size}]]`;
  }
}

const generateRecipe = (images, items, armors) => (item, usedImages) => {
  if (item.recipe) {
    return item.recipe.map((i) => {
      let icon = ""
      let description = ""

      if (items[i.item]) {
        icon = items[i.item].inventoryIcon.slice(1);
        description = items[i.item].shortdescription;
      } else {
        item = _.flatten(armors.map((a) => [
          Object.assign({}, a.head, {imagesPath: a.imagesPath}),
          Object.assign({}, a.chest, {imagesPath: a.imagesPath}),
          Object.assign({}, a.pants, {imagesPath: a.imagesPath}),
        ])).find((a) => a.id === i.item)

        // Turn icon.png:head into iconhead.png

        icon = item.imagesPath + item.icon.replace(".png","").replace("s:","") + ".png";
        description = item.name;
      }
      return `<p>${getImageOrPlaceholder(icon, "16x16px", images, usedImages)}${i.count} x ${description.replace(/(\^.*?\;)/g, "")}</p>`;
      //return `[[File:Cotton.png|thumb|16x16px]]${i.count} x ${description.replace(/(\^.*?\;)/g, "")}`;
    }).join(`\n`);
  } else{
    return "";
  }
}

const genMaxStat = (armor, stat) => (getStat(armor.chest, stat) + getStat(armor.head, stat) + getStat(armor.pants, stat)).toFixed(2);

const getStat = (json, stat) => {
  const eff = json.leveledStatusEffects.find((x) => x.stat === stat);
  return eff ? Number(eff.value.toFixed(2)) : 0;
}
const genTemplate = (data, items, images) => {
  const usedImages = [];
  const recipeFun = generateRecipe(images, items, data);

  const text = data.map((armor) => (`
==== ${armor.name} ====

{| class="article-table"
! colspan="2" rowspan="2" | ${getImageOrPlaceholder(`${armor.imagesPath}fullset.png`, "86x86px", images, usedImages, false)}
!${getImageOrPlaceholder(`${starboundFile('interface/inventory/sword.png')}`, "30x30px", images, usedImages, false)}
!${getImageOrPlaceholder(`${starboundFile('interface/inventory/shield.png')}`, "30x30px", images, usedImages, false)}
!${getImageOrPlaceholder(`${starboundFile('interface/inventory/lightning.png')}`, "30x30px", images, usedImages, false)}
!${getImageOrPlaceholder(`${starboundFile('interface/inventory/heart.png')}`, "30x30px", images, usedImages, false)}
|-
|${genMaxStat(armor, 'powerMultiplier')} %
|${genMaxStat(armor, 'protection')}
|${genMaxStat(armor, 'maxEnergy')}
|${genMaxStat(armor, 'maxHealth')}
|-
|Bonuses
| colspan="5" |${armor.bonus ? armor.bonus.label : ""}
|-
| colspan="2" |${armor.head.name}
| colspan="2" |${armor.chest.name}
| colspan="2" |${armor.pants.name}
|-
| colspan="2" |

${recipeFun(armor.head, usedImages)}

| colspan="2" |

${recipeFun(armor.chest, usedImages)}

| colspan="2" |

${recipeFun(armor.pants, usedImages)}

|-
|${getImageOrPlaceholder(`${starboundFile('interface/inventory/sword.png')}`, "30x30px", images, usedImages, false)}
|${getStat(armor.head, 'powerMultiplier')} %
|${getImageOrPlaceholder(`${starboundFile('interface/inventory/sword.png')}`, "30x30px", images, usedImages, false)}
|${getStat(armor.chest, 'powerMultiplier')} %
|${getImageOrPlaceholder(`${starboundFile('interface/inventory/sword.png')}`, "30x30px", images, usedImages, false)}
|${getStat(armor.pants, 'powerMultiplier')} %
|-
|${getImageOrPlaceholder(`${starboundFile('interface/inventory/shield.png')}`, "30x30px", images, usedImages, false)}
|${getStat(armor.head, 'protection')}
|${getImageOrPlaceholder(`${starboundFile('interface/inventory/shield.png')}`, "30x30px", images, usedImages, false)}
|${getStat(armor.chest, 'protection')}
|${getImageOrPlaceholder(`${starboundFile('interface/inventory/shield.png')}`, "30x30px", images, usedImages, false)}
|${getStat(armor.pants, 'protection')}
|-
|${getImageOrPlaceholder(`${starboundFile('interface/inventory/lightning.png')}`, "30x30px", images, usedImages, false)}
|${getStat(armor.head, 'maxEnergy')}
|${getImageOrPlaceholder(`${starboundFile('interface/inventory/lightning.png')}`, "30x30px", images, usedImages, false)}
|${getStat(armor.chest, 'maxEnergy')}
|${getImageOrPlaceholder(`${starboundFile('interface/inventory/lightning.png')}`, "30x30px", images, usedImages, false)}
|${getStat(armor.pants, 'maxEnergy')}
|-
|${getImageOrPlaceholder(`${starboundFile('interface/inventory/heart.png')}`, "30x30px", images, usedImages, false)}
|${getStat(armor.head, 'maxHealth')}
|${getImageOrPlaceholder(`${starboundFile('interface/inventory/heart.png')}`, "30x30px", images, usedImages, false)}
|${getStat(armor.chest, 'maxHealth')}
|${getImageOrPlaceholder(`${starboundFile('interface/inventory/heart.png')}`, "30x30px", images, usedImages, false)}
|${getStat(armor.pants, 'maxHealth')}
|}`)).join(`\n\n`);

  return { usedImages: _.uniq(usedImages), text: `<div class="armor-list">\n${text}\n</div>` };
}

module.exports = genTemplate;
<commit_msg>Display the tier of the armors<commit_after>const _ = require('lodash');
const sha1File = require('sha1-file');

const FileUtils = require('../utils/file');

const frackinJson = FileUtils.frackinJson;
const frackinFile = FileUtils.frackinFile;
const starboundFile = FileUtils.starboundFile;

const getImageOrPlaceholder = (image, size, images, usedImages, thumb) => {
  const path = image;
  const sha1 = sha1File(path);
  thumb = thumb !== undefined ? thumb : true;
  if (images[sha1]) {
    return `[[${images[sha1].title}|${thumb ? 'thumb|' : ''}${size}]]`;
  } else {
    // Add the image to the list of used images
    usedImages.push(path);
    return `[[File:${path.replace(/\//g,"")}|${thumb ? 'thumb|' : ''}${size}]]`;
  }
}

const generateRecipe = (images, items, armors) => (item, usedImages) => {
  if (item.recipe) {
    return item.recipe.map((i) => {
      let icon = ""
      let description = ""

      if (items[i.item]) {
        icon = items[i.item].inventoryIcon.slice(1);
        description = items[i.item].shortdescription;
      } else {
        item = _.flatten(armors.map((a) => [
          Object.assign({}, a.head, {imagesPath: a.imagesPath}),
          Object.assign({}, a.chest, {imagesPath: a.imagesPath}),
          Object.assign({}, a.pants, {imagesPath: a.imagesPath}),
        ])).find((a) => a.id === i.item)

        // Turn icon.png:head into iconhead.png

        icon = item.imagesPath + item.icon.replace(".png","").replace("s:","") + ".png";
        description = item.name;
      }
      return `<p>${getImageOrPlaceholder(icon, "16x16px", images, usedImages)}${i.count} x ${description.replace(/(\^.*?\;)/g, "")}</p>`;
      //return `[[File:Cotton.png|thumb|16x16px]]${i.count} x ${description.replace(/(\^.*?\;)/g, "")}`;
    }).join(`\n`);
  } else{
    return "";
  }
}

const genMaxStat = (armor, stat) => (getStat(armor.chest, stat) + getStat(armor.head, stat) + getStat(armor.pants, stat)).toFixed(2);

const getStat = (json, stat) => {
  const eff = json.leveledStatusEffects.find((x) => x.stat === stat);
  return eff ? Number(eff.value.toFixed(2)) : 0;
}
const genTemplate = (data, items, images) => {
  const usedImages = [];
  const recipeFun = generateRecipe(images, items, data);

  const armorsByTier = data.reduce((acc, cur) => {
    acc[Number(cur.level)] = (acc[Number(cur.level)] || []).concat(cur);
    return acc;
  }, {})

  const text = Object.keys(armorsByTier).sort().filter((o) => o > 0).map((tier) => `

== Tier ${tier} ==

${armorsByTier[tier].map((armor) => (`

=== ${armor.name} ===

{| class="article-table"
! colspan="2" rowspan="2" | ${getImageOrPlaceholder(`${armor.imagesPath}fullset.png`, "86x86px", images, usedImages, false)}
!${getImageOrPlaceholder(`${starboundFile('interface/inventory/sword.png')}`, "30x30px", images, usedImages, false)}
!${getImageOrPlaceholder(`${starboundFile('interface/inventory/shield.png')}`, "30x30px", images, usedImages, false)}
!${getImageOrPlaceholder(`${starboundFile('interface/inventory/lightning.png')}`, "30x30px", images, usedImages, false)}
!${getImageOrPlaceholder(`${starboundFile('interface/inventory/heart.png')}`, "30x30px", images, usedImages, false)}
|-
|${genMaxStat(armor, 'powerMultiplier')} %
|${genMaxStat(armor, 'protection')}
|${genMaxStat(armor, 'maxEnergy')}
|${genMaxStat(armor, 'maxHealth')}
|-
|Bonuses
| colspan="5" |${armor.bonus ? armor.bonus.label : ""}
|-
| colspan="2" |${armor.head.name}
| colspan="2" |${armor.chest.name}
| colspan="2" |${armor.pants.name}
|-
| colspan="2" |

${recipeFun(armor.head, usedImages)}

| colspan="2" |

${recipeFun(armor.chest, usedImages)}

| colspan="2" |

${recipeFun(armor.pants, usedImages)}

|-
|${getImageOrPlaceholder(`${starboundFile('interface/inventory/sword.png')}`, "30x30px", images, usedImages, false)}
|${getStat(armor.head, 'powerMultiplier')} %
|${getImageOrPlaceholder(`${starboundFile('interface/inventory/sword.png')}`, "30x30px", images, usedImages, false)}
|${getStat(armor.chest, 'powerMultiplier')} %
|${getImageOrPlaceholder(`${starboundFile('interface/inventory/sword.png')}`, "30x30px", images, usedImages, false)}
|${getStat(armor.pants, 'powerMultiplier')} %
|-
|${getImageOrPlaceholder(`${starboundFile('interface/inventory/shield.png')}`, "30x30px", images, usedImages, false)}
|${getStat(armor.head, 'protection')}
|${getImageOrPlaceholder(`${starboundFile('interface/inventory/shield.png')}`, "30x30px", images, usedImages, false)}
|${getStat(armor.chest, 'protection')}
|${getImageOrPlaceholder(`${starboundFile('interface/inventory/shield.png')}`, "30x30px", images, usedImages, false)}
|${getStat(armor.pants, 'protection')}
|-
|${getImageOrPlaceholder(`${starboundFile('interface/inventory/lightning.png')}`, "30x30px", images, usedImages, false)}
|${getStat(armor.head, 'maxEnergy')}
|${getImageOrPlaceholder(`${starboundFile('interface/inventory/lightning.png')}`, "30x30px", images, usedImages, false)}
|${getStat(armor.chest, 'maxEnergy')}
|${getImageOrPlaceholder(`${starboundFile('interface/inventory/lightning.png')}`, "30x30px", images, usedImages, false)}
|${getStat(armor.pants, 'maxEnergy')}
|-
|${getImageOrPlaceholder(`${starboundFile('interface/inventory/heart.png')}`, "30x30px", images, usedImages, false)}
|${getStat(armor.head, 'maxHealth')}
|${getImageOrPlaceholder(`${starboundFile('interface/inventory/heart.png')}`, "30x30px", images, usedImages, false)}
|${getStat(armor.chest, 'maxHealth')}
|${getImageOrPlaceholder(`${starboundFile('interface/inventory/heart.png')}`, "30x30px", images, usedImages, false)}
|${getStat(armor.pants, 'maxHealth')}
|}`)).join(`\n\n`)}`)

  return { usedImages: _.uniq(usedImages), text: `<div class="armor-list">\n${text}\n</div>` };
}

module.exports = genTemplate;
<|endoftext|>


<commit_before>import React from "react";
import { Link } from "gatsby";
import { prepareTitle } from "../common.js";
import Layout from "../components/layout";
import styled from "@emotion/styled";
import SEO from "../components/seo";

const VolumeWrapper = styled.div`
  border-top: 1px solid #faf9f3;
`;

const Volume = styled.div`
  max-width: 960px;
  margin: 0 auto;
  font-size: 0.92rem;
`;

const VolumeTitle = styled.h2`
  padding-left: 24px;
  padding-right: 24px;
`;

const DiscourseList = styled.div`
  -moz-border-radius: 2px;
  -webkit-border-radius: 2px;
  border-bottom: 1px solid #e3e1ce;
  border-left: 1px solid #e3e1ce;
  border-spacing: 0;
  border-top: 1px solid #e3e1ce;
  clear: both;
  max-width: 100%;
  background-color: white;
  margin-bottom: 16px;
  @media (max-width: 640px) {
    padding: 12px;
  }
`;

const DiscourseListItem = styled.div`
  display: flex;
  @media (max-width: 640px) {
    flex-direction: column;
    margin-top: 24px;
    margin-bottom: 24px;
  }
  @media (min-width: 641px) {
    margin-top: 8px;
    margin-bottom: 8px;
  }
  &:first-of-type {
    margin-top: 8px;
  }
  &:last-of-type {
    margin-bottom: 8px;
  }
  &:hover {
    background-color: #f8f8f8;
  }
`;

const Pages = styled.div`
  width: 80px;
  padding: 4px 8px;
  @media (max-width: 640px) {
    order: 4;
    padding-left: 24px;
  }
  @media (min-width: 641px) {
    padding-left: 12px;
  }
`;

const DateComponent = styled.div`
  width: 145px;
  padding: 4px 8px;
  @media (max-width: 640px) {
    padding-left: 24px;
    order: 3;
  }
`;

const Speaker = styled.div`
  width: 130px;
  padding: 4px 8px;
  @media (max-width: 640px) {
    order: 2;
    padding-left: 24px;
  }
`;
const Title = styled.div`
  flex: 1;
  @media (max-width: 640px) {
    order: 1;
  }
  padding: 4px 8px;
  padding-right: 12px;
`;

export default ({
  pageContext: { volumeNumbers, volumeNumber, discourses }
}) => {
  return (
    <Layout volumeNumbers={volumeNumbers} volumeNumber={volumeNumber}>
      <SEO title={`Journal of Discourses, vol. ${volumeNumber}`} />
      <VolumeWrapper>
        <Volume>
          <VolumeTitle>Volume {volumeNumber}</VolumeTitle>
          <DiscourseList>
            {discourses.map(discourse => {
              const event = new Date();
              if (discourse.date) {
                event.setFullYear(parseInt(discourse.date.substr(0, 4), 10));
                event.setMonth(parseInt(discourse.date.substr(5, 7), 10) - 1);
                event.setDate(parseInt(discourse.date.substr(8, 10), 10));
                event.setUTCHours(0);
              }
              const dateOptions = {
                year: "numeric",
                month: "long",
                day: "numeric"
              };
              return (
                <DiscourseListItem key={discourse.id}>
                  <Pages>
                    pp. {discourse.start_page}-{discourse.end_page}
                  </Pages>
                  <DateComponent title={discourse.date}>
                    {discourse.date &&
                      event.toLocaleDateString("default", dateOptions)}
                  </DateComponent>
                  <Speaker>{discourse.speaker}</Speaker>
                  <Title>
                    <Link
                      to={`/${discourse.volume}/${discourse.start_page}`}
                      dangerouslySetInnerHTML={{
                        __html: prepareTitle(discourse.title)
                      }}
                    />
                  </Title>
                </DiscourseListItem>
              );
            })}
          </DiscourseList>
        </Volume>
      </VolumeWrapper>
    </Layout>
  );
};
<commit_msg>Fix volume list item quirk<commit_after>import React from "react";
import { Link } from "gatsby";
import { prepareTitle } from "../common.js";
import Layout from "../components/layout";
import styled from "@emotion/styled";
import SEO from "../components/seo";

const VolumeWrapper = styled.div`
  border-top: 1px solid #faf9f3;
`;

const Volume = styled.div`
  max-width: 960px;
  margin: 0 auto;
  font-size: 0.92rem;
`;

const VolumeTitle = styled.h2`
  padding-left: 24px;
  padding-right: 24px;
`;

const DiscourseList = styled.div`
  -moz-border-radius: 2px;
  -webkit-border-radius: 2px;
  border-bottom: 1px solid #e3e1ce;
  border-left: 1px solid #e3e1ce;
  border-spacing: 0;
  border-top: 1px solid #e3e1ce;
  clear: both;
  max-width: 100%;
  background-color: white;
  margin-bottom: 16px;
  @media (max-width: 640px) {
    padding: 12px;
  }
`;

const DiscourseListItem = styled.div`
  display: flex;
  width: 100%;
  @media (max-width: 640px) {
    flex-direction: column;
    margin-top: 24px;
    margin-bottom: 24px;
  }
  @media (min-width: 641px) {
    margin-top: 8px;
    margin-bottom: 8px;
  }
  &:first-of-type {
    margin-top: 8px;
  }
  &:last-of-type {
    margin-bottom: 8px;
  }
  &:hover {
    background-color: #f8f8f8;
  }
`;

const Pages = styled.div`
  width: 80px;
  padding: 4px 8px;
  @media (max-width: 640px) {
    order: 4;
    padding-left: 24px;
  }
  @media (min-width: 641px) {
    padding-left: 12px;
  }
`;

const DateComponent = styled.div`
  width: 145px;
  padding: 4px 8px;
  @media (max-width: 640px) {
    padding-left: 24px;
    order: 3;
  }
`;

const Speaker = styled.div`
  padding: 4px 8px;
  @media (max-width: 640px) {
    order: 2;
    padding-left: 24px;
  }
  @media (min-width: 641px) {
    width: 130px;
    order: 2;
    padding-left: 24px;
  }
`;
const Title = styled.div`
  flex: 1;
  @media (max-width: 640px) {
    order: 1;
  }
  padding: 4px 8px;
  padding-right: 12px;
`;

export default ({
  pageContext: { volumeNumbers, volumeNumber, discourses }
}) => {
  return (
    <Layout volumeNumbers={volumeNumbers} volumeNumber={volumeNumber}>
      <SEO title={`Journal of Discourses, vol. ${volumeNumber}`} />
      <VolumeWrapper>
        <Volume>
          <VolumeTitle>Volume {volumeNumber}</VolumeTitle>
          <DiscourseList>
            {discourses.map(discourse => {
              const event = new Date();
              if (discourse.date) {
                event.setFullYear(parseInt(discourse.date.substr(0, 4), 10));
                event.setMonth(parseInt(discourse.date.substr(5, 7), 10) - 1);
                event.setDate(parseInt(discourse.date.substr(8, 10), 10));
                event.setUTCHours(0);
              }
              const dateOptions = {
                year: "numeric",
                month: "long",
                day: "numeric"
              };
              return (
                <DiscourseListItem key={discourse.id}>
                  <Pages>
                    pp. {discourse.start_page}-{discourse.end_page}
                  </Pages>
                  <DateComponent title={discourse.date}>
                    {discourse.date &&
                      event.toLocaleDateString("default", dateOptions)}
                  </DateComponent>
                  <Speaker>{discourse.speaker}</Speaker>
                  <Title>
                    <Link
                      to={`/${discourse.volume}/${discourse.start_page}`}
                      dangerouslySetInnerHTML={{
                        __html: prepareTitle(discourse.title)
                      }}
                    />
                  </Title>
                </DiscourseListItem>
              );
            })}
          </DiscourseList>
        </Volume>
      </VolumeWrapper>
    </Layout>
  );
};
<|endoftext|>