<commit_before>/**
 * This Module manages all /minified/* requests. It controls the
 * minification && compression of Javascript and CSS.
 */

/*
 * 2011 Peter 'Pita' Martischka (Primary Technology Ltd)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS-IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var ERR = require("async-stacktrace");
var settings = require('./Settings');
var async = require('async');
var fs = require('fs');
var cleanCSS = require('clean-css');
var jsp = require("uglify-js").parser;
var pro = require("uglify-js").uglify;
var path = require('path');
var RequireKernel = require('require-kernel');
var server = require('../server');

var ROOT_DIR = path.normalize(__dirname + "/../" );
var JS_DIR = ROOT_DIR + '../static/js/';
var CSS_DIR = ROOT_DIR + '../static/css/';
var TAR_PATH = path.join(__dirname, 'tar.json');
var tar = JSON.parse(fs.readFileSync(TAR_PATH, 'utf8'));

exports.tar = {};
for (var key in tar) {
  exports.tar['/' + key] =
    tar[key].map(function (p) {return '/' + p}).concat(
      tar[key].map(function (p) {return '/' + p.replace(/\.js$/, '')})
    );
}

/**
 * creates the minifed javascript for the given minified name
 * @param req the Express request
 * @param res the Express response
 */
exports.minifyJS = function(req, res, next)
{
  var filename = req.params['filename'];
  res.header("Content-Type","text/javascript");

  statFile(filename, function (error, date, exists) {
    date = new Date(date);
    res.setHeader('last-modified', date.toUTCString());
    res.setHeader('date', (new Date()).toUTCString());
    if (server.maxAge) {
      var expiresDate = new Date((new Date()).getTime() + server.maxAge*1000);
      res.setHeader('expires', expiresDate.toUTCString());
      res.setHeader('cache-control', 'max-age=' + server.maxAge);
    }

    if (error) {
      res.writeHead(500, {});
      res.end();
    } else if (!exists) {
      res.writeHead(404, {});
      res.end();
    } else if (new Date(req.headers['if-modified-since']) >= date) {
      res.writeHead(304, {});
      res.end();
    } else {
      if (req.method == 'HEAD') {
        res.writeHead(200, {});
        res.end();
      } else if (req.method == 'GET') {
        getFileCompressed(filename, function (error, content) {
          if(ERR(error)) return;
          res.writeHead(200, {});
          res.write(content);
          res.end();
        });
      } else {
        res.writeHead(405, {'allow': 'HEAD, GET'});
        res.end();
      }
    }
  });
}

// find all includes in ace.js and embed them.
function getAceFile(callback) {
  fs.readFile(JS_DIR + 'ace.js', "utf8", function(err, data) {
    if(ERR(err, callback)) return;

    // Find all includes in ace.js and embed them
    var founds = data.match(/\$\$INCLUDE_[a-zA-Z_]+\([a-zA-Z0-9.\/_"-]+\)/gi);
    if (!settings.minify) {
      founds = [];
    }
    founds.push('$$INCLUDE_JS("../static/js/require-kernel.js")');

    data += ';\n';
    data += 'Ace2Editor.EMBEDED = Ace2Editor.EMBEDED || {};\n';

    //go trough all includes
    async.forEach(founds, function (item, callback) {
      var filename = item.match(/"([^"]*)"/)[1];
      var type = item.match(/INCLUDE_([A-Z]+)/)[1];
      var shortFilename =
          (filename.match(/^\.\.\/static\/js\/(.*)$/, '') || [])[1];

      //read the included files
      if (shortFilename) {
        if (shortFilename == 'require-kernel.js') {
          // the kernel isn’t actually on the file system.
          handleEmbed(null, requireDefinition());
        } else {
          var contents = '';
          tarCode(tar[shortFilename] || shortFilename
          , function (content) {
              contents += content;
            }
          , function () {
              handleEmbed(null, contents);
            }
          );
        }
      } else {
        fs.readFile(ROOT_DIR + filename, "utf8", handleEmbed);
      }

      function handleEmbed(error, data_) {
        if (error) {
          return; // Don't bother to include it.
        }
        if (settings.minify) {
          if (type == "JS") {
            try {
              data_ = compressJS([data_]);
            } catch (e) {
              // Ignore, include uncompresseed, which will break in browser.
            }
          } else {
            data_ = compressCSS([data_]);
          }
        }
        data += 'Ace2Editor.EMBEDED[' + JSON.stringify(filename) + '] = '
            + JSON.stringify(data_) + ';\n';
        callback();
      }
    }, function(error) {
      callback(error, data);
    });
  });
}

function statFile(filename, callback) {
  if (filename == 'ace.js') {
    lastModifiedDateOfEverything(function (error, date) {
      callback(error, date, !error);
    });
  } else {
    fs.stat(JS_DIR + filename, function (error, stats) {
      if (error) {
        if (error.code == "ENOENT") { // Stat the directory instead.
          fs.stat(JS_DIR, function (error, stats) {
            if (error) {
              callback(error);
            } else if (filename == 'require-kernel.js') {
              callback(null, stats.mtime.getTime(), true);
            } else {
              callback(null, stats.mtime.getTime(), false);
            }
          });
        } else {
          callback(error);
        }
      } else {
        callback(null, stats.mtime.getTime(), true);
      }
    });
  }
}
function lastModifiedDateOfEverything(callback) {
  var folders2check = [CSS_DIR, JS_DIR];
  var latestModification = 0;
  //go trough this two folders
  async.forEach(folders2check, function(path, callback)
  {
    //read the files in the folder
    fs.readdir(path, function(err, files)
    {
      if(ERR(err, callback)) return;

      //we wanna check the directory itself for changes too
      files.push(".");

      //go trough all files in this folder
      async.forEach(files, function(filename, callback)
      {
        //get the stat data of this file
        fs.stat(path + "/" + filename, function(err, stats)
        {
          if(ERR(err, callback)) return;

          //get the modification time
          var modificationTime = stats.mtime.getTime();

          //compare the modification time to the highest found
          if(modificationTime > latestModification)
          {
            latestModification = modificationTime;
          }

          callback();
        });
      }, callback);
    });
  }, function () {
    callback(null, latestModification);
  });
}

function requireDefinition() {
  return 'var require = ' + RequireKernel.kernelSource + ';\n';
}

function getFileCompressed(filename, callback) {
  getFile(filename, function (error, content) {
    if (error || !content) {
      callback(error, content);
    } else {
      if (settings.minify) {
        try {
          content = compressJS([content])
        } catch (error) {
          // silence
        }
      }
      callback(null, content);
    }
  });
}

function getFile(filename, callback) {
  if (filename == 'ace.js') {
    getAceFile(callback);
  } else if (filename == 'require-kernel.js') {
    callback(undefined, requireDefinition());
  } else {
    fs.readFile(JS_DIR + filename, "utf8", callback);
  }
}

function tarCode(jsFiles, write, callback) {
  write('require.define({');
  var initialEntry = true;
  async.forEach(jsFiles, function (filename, callback){
    getFile(filename, handleFile)

    function handleFile(err, data) {
      if(ERR(err, callback)) return;
      var srcPath = JSON.stringify('/' + filename);
      var srcPathAbbv = JSON.stringify('/' + filename.replace(/\.js$/, ''));
      if (!initialEntry) {
        write('\n,');
      } else {
        initialEntry = false;
      }
      write(srcPath + ': ')
      data = '(function (require, exports, module) {' + data + '})';
      if (settings.minify) {
        write(compressJS([data]));
      } else {
        write(data);
      }
      if (srcPath != srcPathAbbv) {
        write('\n,' + srcPathAbbv + ': null');
      }

      callback();
    }
  }, function () {
    write('});\n');
    callback();
  });
}

function compressJS(values)
{
  var complete = values.join("\n");
  var ast = jsp.parse(complete); // parse code and get the initial AST
  ast = pro.ast_mangle(ast); // get a new AST with mangled names
  ast = pro.ast_squeeze(ast); // get an AST with compression optimizations
  return pro.gen_code(ast); // compressed code here
}

function compressCSS(values)
{
  var complete = values.join("\n");
  return cleanCSS.process(complete);
}
<commit_msg>Only add date if date exists.<commit_after>/**
 * This Module manages all /minified/* requests. It controls the
 * minification && compression of Javascript and CSS.
 */

/*
 * 2011 Peter 'Pita' Martischka (Primary Technology Ltd)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS-IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var ERR = require("async-stacktrace");
var settings = require('./Settings');
var async = require('async');
var fs = require('fs');
var cleanCSS = require('clean-css');
var jsp = require("uglify-js").parser;
var pro = require("uglify-js").uglify;
var path = require('path');
var RequireKernel = require('require-kernel');
var server = require('../server');

var ROOT_DIR = path.normalize(__dirname + "/../" );
var JS_DIR = ROOT_DIR + '../static/js/';
var CSS_DIR = ROOT_DIR + '../static/css/';
var TAR_PATH = path.join(__dirname, 'tar.json');
var tar = JSON.parse(fs.readFileSync(TAR_PATH, 'utf8'));

exports.tar = {};
for (var key in tar) {
  exports.tar['/' + key] =
    tar[key].map(function (p) {return '/' + p}).concat(
      tar[key].map(function (p) {return '/' + p.replace(/\.js$/, '')})
    );
}

/**
 * creates the minifed javascript for the given minified name
 * @param req the Express request
 * @param res the Express response
 */
exports.minifyJS = function(req, res, next)
{
  var filename = req.params['filename'];
  res.header("Content-Type","text/javascript");

  statFile(filename, function (error, date, exists) {
    if (date) {
      date = new Date(date);
      res.setHeader('last-modified', date.toUTCString());
      res.setHeader('date', (new Date()).toUTCString());
      if (server.maxAge) {
        var expiresDate = new Date((new Date()).getTime()+server.maxAge*1000);
        res.setHeader('expires', expiresDate.toUTCString());
        res.setHeader('cache-control', 'max-age=' + server.maxAge);
      }
    }

    if (error) {
      res.writeHead(500, {});
      res.end();
    } else if (!exists) {
      res.writeHead(404, {});
      res.end();
    } else if (new Date(req.headers['if-modified-since']) >= date) {
      res.writeHead(304, {});
      res.end();
    } else {
      if (req.method == 'HEAD') {
        res.writeHead(200, {});
        res.end();
      } else if (req.method == 'GET') {
        getFileCompressed(filename, function (error, content) {
          if(ERR(error)) return;
          res.writeHead(200, {});
          res.write(content);
          res.end();
        });
      } else {
        res.writeHead(405, {'allow': 'HEAD, GET'});
        res.end();
      }
    }
  });
}

// find all includes in ace.js and embed them.
function getAceFile(callback) {
  fs.readFile(JS_DIR + 'ace.js', "utf8", function(err, data) {
    if(ERR(err, callback)) return;

    // Find all includes in ace.js and embed them
    var founds = data.match(/\$\$INCLUDE_[a-zA-Z_]+\([a-zA-Z0-9.\/_"-]+\)/gi);
    if (!settings.minify) {
      founds = [];
    }
    founds.push('$$INCLUDE_JS("../static/js/require-kernel.js")');

    data += ';\n';
    data += 'Ace2Editor.EMBEDED = Ace2Editor.EMBEDED || {};\n';

    //go trough all includes
    async.forEach(founds, function (item, callback) {
      var filename = item.match(/"([^"]*)"/)[1];
      var type = item.match(/INCLUDE_([A-Z]+)/)[1];
      var shortFilename =
          (filename.match(/^\.\.\/static\/js\/(.*)$/, '') || [])[1];

      //read the included files
      if (shortFilename) {
        if (shortFilename == 'require-kernel.js') {
          // the kernel isn’t actually on the file system.
          handleEmbed(null, requireDefinition());
        } else {
          var contents = '';
          tarCode(tar[shortFilename] || shortFilename
          , function (content) {
              contents += content;
            }
          , function () {
              handleEmbed(null, contents);
            }
          );
        }
      } else {
        fs.readFile(ROOT_DIR + filename, "utf8", handleEmbed);
      }

      function handleEmbed(error, data_) {
        if (error) {
          return; // Don't bother to include it.
        }
        if (settings.minify) {
          if (type == "JS") {
            try {
              data_ = compressJS([data_]);
            } catch (e) {
              // Ignore, include uncompresseed, which will break in browser.
            }
          } else {
            data_ = compressCSS([data_]);
          }
        }
        data += 'Ace2Editor.EMBEDED[' + JSON.stringify(filename) + '] = '
            + JSON.stringify(data_) + ';\n';
        callback();
      }
    }, function(error) {
      callback(error, data);
    });
  });
}

function statFile(filename, callback) {
  if (filename == 'ace.js') {
    lastModifiedDateOfEverything(function (error, date) {
      callback(error, date, !error);
    });
  } else {
    fs.stat(JS_DIR + filename, function (error, stats) {
      if (error) {
        if (error.code == "ENOENT") { // Stat the directory instead.
          fs.stat(JS_DIR, function (error, stats) {
            if (error) {
              callback(error);
            } else if (filename == 'require-kernel.js') {
              callback(null, stats.mtime.getTime(), true);
            } else {
              callback(null, stats.mtime.getTime(), false);
            }
          });
        } else {
          callback(error);
        }
      } else {
        callback(null, stats.mtime.getTime(), true);
      }
    });
  }
}
function lastModifiedDateOfEverything(callback) {
  var folders2check = [CSS_DIR, JS_DIR];
  var latestModification = 0;
  //go trough this two folders
  async.forEach(folders2check, function(path, callback)
  {
    //read the files in the folder
    fs.readdir(path, function(err, files)
    {
      if(ERR(err, callback)) return;

      //we wanna check the directory itself for changes too
      files.push(".");

      //go trough all files in this folder
      async.forEach(files, function(filename, callback)
      {
        //get the stat data of this file
        fs.stat(path + "/" + filename, function(err, stats)
        {
          if(ERR(err, callback)) return;

          //get the modification time
          var modificationTime = stats.mtime.getTime();

          //compare the modification time to the highest found
          if(modificationTime > latestModification)
          {
            latestModification = modificationTime;
          }

          callback();
        });
      }, callback);
    });
  }, function () {
    callback(null, latestModification);
  });
}

function requireDefinition() {
  return 'var require = ' + RequireKernel.kernelSource + ';\n';
}

function getFileCompressed(filename, callback) {
  getFile(filename, function (error, content) {
    if (error || !content) {
      callback(error, content);
    } else {
      if (settings.minify) {
        try {
          content = compressJS([content])
        } catch (error) {
          // silence
        }
      }
      callback(null, content);
    }
  });
}

function getFile(filename, callback) {
  if (filename == 'ace.js') {
    getAceFile(callback);
  } else if (filename == 'require-kernel.js') {
    callback(undefined, requireDefinition());
  } else {
    fs.readFile(JS_DIR + filename, "utf8", callback);
  }
}

function tarCode(jsFiles, write, callback) {
  write('require.define({');
  var initialEntry = true;
  async.forEach(jsFiles, function (filename, callback){
    getFile(filename, handleFile)

    function handleFile(err, data) {
      if(ERR(err, callback)) return;
      var srcPath = JSON.stringify('/' + filename);
      var srcPathAbbv = JSON.stringify('/' + filename.replace(/\.js$/, ''));
      if (!initialEntry) {
        write('\n,');
      } else {
        initialEntry = false;
      }
      write(srcPath + ': ')
      data = '(function (require, exports, module) {' + data + '})';
      if (settings.minify) {
        write(compressJS([data]));
      } else {
        write(data);
      }
      if (srcPath != srcPathAbbv) {
        write('\n,' + srcPathAbbv + ': null');
      }

      callback();
    }
  }, function () {
    write('});\n');
    callback();
  });
}

function compressJS(values)
{
  var complete = values.join("\n");
  var ast = jsp.parse(complete); // parse code and get the initial AST
  ast = pro.ast_mangle(ast); // get a new AST with mangled names
  ast = pro.ast_squeeze(ast); // get an AST with compression optimizations
  return pro.gen_code(ast); // compressed code here
}

function compressCSS(values)
{
  var complete = values.join("\n");
  return cleanCSS.process(complete);
}
<|endoftext|>


<commit_before>/* to show _read function is only called
   when the consumer requests,
   we can modify readable stream code
   slightly to add a delay
*/

var Readable = require('stream').Readable;
var rs = Readable();

var c = 97 -1;

rs._read = function() {
	if(c >= 'z'.charCodeAt(0)) return rs.push(null);

	setTimeout(function () { // setTimeout : OS requires some time to send relevant signals to close pipe
		rs.push(String.fromCharCode(++c));
	}, 100);
};

rs.pipe(process.stdout);

process.on('exit', function () {
	console.error('\n_read() called ' + (c - 97) + 'times');
});
process.stdout.on('error', process.exit);

// `process.stdout.on` : OS will send a SIGPIPE to process
// when `head` no longer interested in program's output
// which gets emitted as an EPIPE error on `process.stdout`

// create a readable stream that pushes arbitrary values
// instead of just string and buffers
// make sure to create readable stream with
// `Readable({ objectMode: true })<commit_msg>Removed files<commit_after><|endoftext|>


<commit_before>/*    Copyright 2016-2020 Firewalla Inc.
 *
 *    This program is free software: you can redistribute it and/or  modify
 *    it under the terms of the GNU Affero General Public License, version 3,
 *    as published by the Free Software Foundation.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

'use strict';

const log = require('../net2/logger.js')(__filename);
const f = require('../net2/Firewalla.js');
const fs = require('fs');
const Promise = require('bluebird');
const cp = require('child_process');
Promise.promisifyAll(fs);

const { exec } = require('child-process-promise');

class Platform {
  getAllNicNames() {
    // for red/blue, there is only one NIC
    return ["eth0"];
  }

  async getPlatformConfig() {
    const path = `${f.getFirewallaHome()}/platform/${this.getName()}/files/config.json`;
    if (fs.existsSync(path))
      try {
        return JSON.parse(await fs.readFileAsync(path, 'utf8'));
      } catch (err) {
        log.error('Error parsing platform config', err)
      }

    return {}
  }

  async getNicStates() {
    const nics = this.getAllNicNames();
    const result = {};
    for (const nic of nics) {
      const address = await fs.readFileAsync(`/sys/class/net/${nic}/address`, {encoding: 'utf8'}).then(result => result.trim().toUpperCase()).catch(() => "");
      const speed = await fs.readFileAsync(`/sys/class/net/${nic}/speed`, {encoding: 'utf8'}).then(result => result.trim()).catch(() => "");
      const carrier = await fs.readFileAsync(`/sys/class/net/${nic}/carrier`, {encoding: 'utf8'}).then(result => result.trim()).catch(() => "");
      result[nic] = {address, speed, carrier};
    }
    return result;
  }

  getSignatureMac() {
    if (!this.signatureMac) {
      try {
        const mac = cp.execSync("cat /sys/class/net/eth0/address", {encoding: 'utf8'});
        this.signatureMac = mac && mac.trim().toUpperCase();
      } catch (err) {}
    }
    return this.signatureMac;
  }

  async getNetworkSpeed() {
    try {
      const output = await fs.readFileAsync(`/sys/class/net/${this.getAllNicNames[0]}/speed`, {encoding: 'utf8'});
      return output.trim();
    } catch(err) {
      log.debug('Error getting network speed', err)
      return null
    }
  }

  getDHKeySize() {
    return 1024;
  }

  getLedPaths() {
    return []
  }

  async turnOnPowerLED() {
    try {
      for (const path of this.getLedPaths()) {
        const trigger = `${path}/trigger`;
        const brightness = `${path}/brightness`;
        await exec(`sudo bash -c 'echo default-on > ${trigger}'`);
        await exec(`sudo bash -c 'echo 255 > ${brightness}'`);
      }
    } catch(err) {
      log.error("Error turning on LED", err)
    }
  }

  async turnOffPowerLED() {
    try {
      for (const path of this.getLedPaths()) {
        const trigger = `${path}/trigger`;
        await exec(`sudo bash -c 'echo none > ${trigger}'`);
        const brightness = `${path}/brightness`;
        await exec(`sudo bash -c 'echo 0 > ${brightness}'`);
      }
    } catch(err) {
      log.error("Error turning off LED", err)
    }
  }

  async blinkPowerLED() {
    try {
      for (const path of this.getLedPaths()) {
        const trigger = `${path}/trigger`;
        await exec(`sudo bash -c 'echo heartbeat > ${trigger}'`);
      }
    } catch(err) {
      log.error("Error blinking LED", err)
    }
  }

  async switchQoS(state, qdisc) {

  }

  getDNSServiceName() {
    return "firemasq";
  }

  getDHCPServiceName() {
    return "firemasq";
  }

  getVPNServerDefaultProtocol() {
    return "udp";
  }

  getName() {}

  getBoardSerial() {}

  getLicenseTypes() {}

  getSubnetCapacity() {}

  async getCpuTemperature() {}

  getPolicyCapacity() {}

  getAllowCustomizedProfiles(){}
  getRatelimitConfig(){}

  getDHCPCapacity() {
    return true
  }

  isFireRouterManaged() {
  }

  getCronTabFile() {
    return `${f.getFirewallaHome()}/etc/crontab`;
  }

  hasMultipleCPUs() {
    return false
  }

  isBonjourBroadcastEnabled() {
    return true;
  }

  defaultPassword() {
    return null;
  }

  isOverlayNetworkAvailable() {
    return true;
  }

  getSystemResetAllOverlayfsScriptName() {
    return "system-reset-all-overlayfs.sh";
  }

  getRetentionTimeMultiplier() {
    return 1;
  }

  getRetentionCountMultiplier() {
    return 1;
  }

  async applyProfile() {
    log.info("NO need to apply profile");
  }

  async onWanIPChanged(ip) {
    log.info("WanIP is changed to", ip);
  }

  async onVPNPortProtocolChanged() {
    log.info("VPN Port Protocol is changed");
  }
}

module.exports = Platform;
<commit_msg>remove platform.getPlatformConfig()<commit_after>/*    Copyright 2016-2020 Firewalla Inc.
 *
 *    This program is free software: you can redistribute it and/or  modify
 *    it under the terms of the GNU Affero General Public License, version 3,
 *    as published by the Free Software Foundation.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

'use strict';

const log = require('../net2/logger.js')(__filename);
const f = require('../net2/Firewalla.js');
const fs = require('fs');
const Promise = require('bluebird');
const cp = require('child_process');
Promise.promisifyAll(fs);

const { exec } = require('child-process-promise');

class Platform {
  getAllNicNames() {
    // for red/blue, there is only one NIC
    return ["eth0"];
  }

  async getNicStates() {
    const nics = this.getAllNicNames();
    const result = {};
    for (const nic of nics) {
      const address = await fs.readFileAsync(`/sys/class/net/${nic}/address`, {encoding: 'utf8'}).then(result => result.trim().toUpperCase()).catch(() => "");
      const speed = await fs.readFileAsync(`/sys/class/net/${nic}/speed`, {encoding: 'utf8'}).then(result => result.trim()).catch(() => "");
      const carrier = await fs.readFileAsync(`/sys/class/net/${nic}/carrier`, {encoding: 'utf8'}).then(result => result.trim()).catch(() => "");
      result[nic] = {address, speed, carrier};
    }
    return result;
  }

  getSignatureMac() {
    if (!this.signatureMac) {
      try {
        const mac = cp.execSync("cat /sys/class/net/eth0/address", {encoding: 'utf8'});
        this.signatureMac = mac && mac.trim().toUpperCase();
      } catch (err) {}
    }
    return this.signatureMac;
  }

  async getNetworkSpeed() {
    try {
      const output = await fs.readFileAsync(`/sys/class/net/${this.getAllNicNames[0]}/speed`, {encoding: 'utf8'});
      return output.trim();
    } catch(err) {
      log.debug('Error getting network speed', err)
      return null
    }
  }

  getDHKeySize() {
    return 1024;
  }

  getLedPaths() {
    return []
  }

  async turnOnPowerLED() {
    try {
      for (const path of this.getLedPaths()) {
        const trigger = `${path}/trigger`;
        const brightness = `${path}/brightness`;
        await exec(`sudo bash -c 'echo default-on > ${trigger}'`);
        await exec(`sudo bash -c 'echo 255 > ${brightness}'`);
      }
    } catch(err) {
      log.error("Error turning on LED", err)
    }
  }

  async turnOffPowerLED() {
    try {
      for (const path of this.getLedPaths()) {
        const trigger = `${path}/trigger`;
        await exec(`sudo bash -c 'echo none > ${trigger}'`);
        const brightness = `${path}/brightness`;
        await exec(`sudo bash -c 'echo 0 > ${brightness}'`);
      }
    } catch(err) {
      log.error("Error turning off LED", err)
    }
  }

  async blinkPowerLED() {
    try {
      for (const path of this.getLedPaths()) {
        const trigger = `${path}/trigger`;
        await exec(`sudo bash -c 'echo heartbeat > ${trigger}'`);
      }
    } catch(err) {
      log.error("Error blinking LED", err)
    }
  }

  async switchQoS(state, qdisc) {

  }

  getDNSServiceName() {
    return "firemasq";
  }

  getDHCPServiceName() {
    return "firemasq";
  }

  getVPNServerDefaultProtocol() {
    return "udp";
  }

  getName() {}

  getBoardSerial() {}

  getLicenseTypes() {}

  getSubnetCapacity() {}

  async getCpuTemperature() {}

  getPolicyCapacity() {}

  getAllowCustomizedProfiles(){}
  getRatelimitConfig(){}

  getDHCPCapacity() {
    return true
  }

  isFireRouterManaged() {
  }

  getCronTabFile() {
    return `${f.getFirewallaHome()}/etc/crontab`;
  }

  hasMultipleCPUs() {
    return false
  }

  isBonjourBroadcastEnabled() {
    return true;
  }

  defaultPassword() {
    return null;
  }

  isOverlayNetworkAvailable() {
    return true;
  }

  getSystemResetAllOverlayfsScriptName() {
    return "system-reset-all-overlayfs.sh";
  }

  getRetentionTimeMultiplier() {
    return 1;
  }

  getRetentionCountMultiplier() {
    return 1;
  }

  async applyProfile() {
    log.info("NO need to apply profile");
  }

  async onWanIPChanged(ip) {
    log.info("WanIP is changed to", ip);
  }

  async onVPNPortProtocolChanged() {
    log.info("VPN Port Protocol is changed");
  }
}

module.exports = Platform;
<|endoftext|>


<commit_before>
/**
 * Convert data in CSV (comma separated value) format to a javascript array.
 *
 * Values are separated by a comma, or by a custom one character delimeter.
 * Rows are separated by a new-line character.
 *
 * Leading and trailing spaces and tabs are ignored.
 * Values may optionally be enclosed by double quotes.
 * Values containing a special character (comma's, double-quotes, or new-lines)
 *   must be enclosed by double-quotes.
 * Embedded double-quotes must be represented by a pair of consecutive
 * double-quotes.
 *
 * Example usage:
 *   var csv = '"x", "y", "z"\n12.3, 2.3, 8.7\n4.5, 1.2, -5.6\n';
 *   var array = csv2array(csv);
 *
 * Author: Jos de Jong, 2010
 *
 * @param {string} data      The data in CSV format.
 * @param {string} delimeter [optional] a custom delimeter. Comma ',' by default
 *                           The Delimeter must be a single character.
 * @return {Array} array     A two dimensional array containing the data
 * @throw {String} error     The method throws an error when there is an
 *                           error in the provided data.
 */
function csv2array(data, delimeter) {
  // Retrieve the delimeter
  if (delimeter == undefined)
    delimeter = ',';
  if (delimeter && delimeter.length > 1)
    delimeter = ',';

  // initialize variables
  var newline = '\n';
  var eof = '';
  var i = 0;
  var c = data.charAt(i);
  var row = 0;
  var col = 0;
  var array = new Array();

  while (c != eof) {
    // skip whitespaces
    while (c == ' ' || c == '\t' || c == '\r') {
      c = data.charAt(++i); // read next char
    }

    // get value
    var value = "";
    if (c == '\"') {
      // value enclosed by double-quotes
      c = data.charAt(++i);

      do {
        if (c != '\"') {
          // read a regular character and go to the next character
          value += c;
          c = data.charAt(++i);
        }

        if (c == '\"') {
          // check for escaped double-quote
          var cnext = data.charAt(i+1);
          if (cnext == '\"') {
            // this is an escaped double-quote.
            // Add a double-quote to the value, and move two characters ahead.
            value += '\"';
            i += 2;
            c = data.charAt(i);
          }
        }
      }
      while (c != eof && c != '\"');

      if (c == eof) {
        throw "Unexpected end of data, double-quote expected";
      }

      c = data.charAt(++i);
    }
    else {
      // value without quotes
      while (c != eof && c != delimeter && c!= newline && c != ' ' && c != '\t' && c != '\r') {
        value += c;
        c = data.charAt(++i);
      }
    }

    // add the value to the array
    if (array.length <= row)
      array.push(new Array());
    array[row].push(value);

    // skip whitespaces
    while (c == ' ' || c == '\t' || c == '\r') {
      c = data.charAt(++i);
    }

    // go to the next row or column
    if (c == delimeter) {
      // to the next column
      col++;
    }
    else if (c == newline) {
      // to the next row
      col = 0;
      row++;
    }
    else if (c != eof) {
      // unexpected character
      throw "Delimiter expected after character " + i;
    }

    // go to the next character
    c = data.charAt(++i);
  }

  return array;
}

/*
function affichertab(data)
{
	document.write("
");
	for(var ligne=0; ligne<data.length; ++ligne)
	{
		document.write("
");
		for(var colonne=0; colonne<data[ligne].length; ++colonne)
		{
			document.write("");
			document.write(data[ligne][colonne]);
			document.write("	");
		}
		document.write("
");
		document.write("
");
	}
	document.write("
");
}*/

function actualise(v1,v2) {
   $.ajax( "data/theme.csv" )
    .done(function(csv) {
      montab = csv2array(csv);
      genererdataviz(montab, v1, v2);
   });
}

function genererdataviz(data, idville1, idville2)
{
   var i=0;
	var coul= new Array("#8dc1bd", "#eae9e4", "#bf8a82", "#f6e59d");
	var arrayLignes = document.getElementById("tableau-match").rows;

	while(arrayLignes.length < data.length)
	{
      var tmp = document.getElementById("tableau-match").insertRow(-1);
      tmp.insertCell(0);
      tmp.insertCell(1);
      tmp.insertCell(2);
	}

	//Affichage nom des villes
   var listville1=''+data[0][idville1]+'
';
   var listville2=''+data[0][idville2]+'
';

   i=1;
   while(i< data[0].length)
   {
	   if(i!=idville1 && i!=idville2)
	   {
	   listville1=listville1+'
'+data[0][i]+'
';
	   listville2=listville2+'
'+data[0][i]+'
';
	   }
	   i++;
   }
   listville1=listville1+'
';
   listville2=listville2+'
';

	arrayLignes[0].cells[0].innerHTML=listville1;
	arrayLignes[0].cells[1].innerHTML='<button class="tiny secondary radius" onclick="genererdataviz(montab, '+idville2+', '+idville1+');">inverser</button>';
	arrayLignes[0].cells[2].innerHTML=listville2;

	i=1;
	while(i<arrayLignes.length)
	{

	// right
	arrayLignes[i].cells[0].innerHTML='
.
';
	arrayLignes[i].cells[0].align = "right";

	// middle
	arrayLignes[i].cells[1].innerHTML="
"+data[i][0]+"
";
	arrayLignes[i].cells[1].align = "middle";

	// left
	arrayLignes[i].cells[2].innerHTML='
.
';

	$('#dataviz-'+idville1+'-cr'+i).animate({'width': data[i][idville1]+'%'},750);
	$('#dataviz-'+idville2+'-cr'+i).animate({'width': data[i][idville2]+'%'},750);

	i++;
	}
}

<commit_msg>ajout valeurs<commit_after>
/**
 * Convert data in CSV (comma separated value) format to a javascript array.
 *
 * Values are separated by a comma, or by a custom one character delimeter.
 * Rows are separated by a new-line character.
 *
 * Leading and trailing spaces and tabs are ignored.
 * Values may optionally be enclosed by double quotes.
 * Values containing a special character (comma's, double-quotes, or new-lines)
 *   must be enclosed by double-quotes.
 * Embedded double-quotes must be represented by a pair of consecutive
 * double-quotes.
 *
 * Example usage:
 *   var csv = '"x", "y", "z"\n12.3, 2.3, 8.7\n4.5, 1.2, -5.6\n';
 *   var array = csv2array(csv);
 *
 * Author: Jos de Jong, 2010
 *
 * @param {string} data      The data in CSV format.
 * @param {string} delimeter [optional] a custom delimeter. Comma ',' by default
 *                           The Delimeter must be a single character.
 * @return {Array} array     A two dimensional array containing the data
 * @throw {String} error     The method throws an error when there is an
 *                           error in the provided data.
 */
function csv2array(data, delimeter) {
  // Retrieve the delimeter
  if (delimeter == undefined)
    delimeter = ',';
  if (delimeter && delimeter.length > 1)
    delimeter = ',';

  // initialize variables
  var newline = '\n';
  var eof = '';
  var i = 0;
  var c = data.charAt(i);
  var row = 0;
  var col = 0;
  var array = new Array();

  while (c != eof) {
    // skip whitespaces
    while (c == ' ' || c == '\t' || c == '\r') {
      c = data.charAt(++i); // read next char
    }

    // get value
    var value = "";
    if (c == '\"') {
      // value enclosed by double-quotes
      c = data.charAt(++i);

      do {
        if (c != '\"') {
          // read a regular character and go to the next character
          value += c;
          c = data.charAt(++i);
        }

        if (c == '\"') {
          // check for escaped double-quote
          var cnext = data.charAt(i+1);
          if (cnext == '\"') {
            // this is an escaped double-quote.
            // Add a double-quote to the value, and move two characters ahead.
            value += '\"';
            i += 2;
            c = data.charAt(i);
          }
        }
      }
      while (c != eof && c != '\"');

      if (c == eof) {
        throw "Unexpected end of data, double-quote expected";
      }

      c = data.charAt(++i);
    }
    else {
      // value without quotes
      while (c != eof && c != delimeter && c!= newline && c != ' ' && c != '\t' && c != '\r') {
        value += c;
        c = data.charAt(++i);
      }
    }

    // add the value to the array
    if (array.length <= row)
      array.push(new Array());
    array[row].push(value);

    // skip whitespaces
    while (c == ' ' || c == '\t' || c == '\r') {
      c = data.charAt(++i);
    }

    // go to the next row or column
    if (c == delimeter) {
      // to the next column
      col++;
    }
    else if (c == newline) {
      // to the next row
      col = 0;
      row++;
    }
    else if (c != eof) {
      // unexpected character
      throw "Delimiter expected after character " + i;
    }

    // go to the next character
    c = data.charAt(++i);
  }

  return array;
}

/*
function affichertab(data)
{
	document.write("
");
	for(var ligne=0; ligne<data.length; ++ligne)
	{
		document.write("
");
		for(var colonne=0; colonne<data[ligne].length; ++colonne)
		{
			document.write("");
			document.write(data[ligne][colonne]);
			document.write("	");
		}
		document.write("
");
		document.write("
");
	}
	document.write("
");
}*/

function actualise(v1,v2) {
   $.ajax( "data/theme.csv" )
    .done(function(csv) {
      montab = csv2array(csv);
      genererdataviz(montab, v1, v2);
   });
}

function genererdataviz(data, idville1, idville2)
{
   var i=0;
	var coul= new Array("#8dc1bd", "#eae9e4", "#bf8a82", "#f6e59d");
	var arrayLignes = document.getElementById("tableau-match").rows;

	while(arrayLignes.length < data.length)
	{
      var tmp = document.getElementById("tableau-match").insertRow(-1);
      tmp.insertCell(0);
      tmp.insertCell(1);
      tmp.insertCell(2);
	}

	//Affichage nom des villes
   var listville1=''+data[0][idville1]+'
';
   var listville2=''+data[0][idville2]+'
';

   i=1;
   while(i< data[0].length)
   {
	   if(i!=idville1 && i!=idville2)
	   {
	   listville1=listville1+'
'+data[0][i]+'
';
	   listville2=listville2+'
'+data[0][i]+'
';
	   }
	   i++;
   }
   listville1=listville1+'
';
   listville2=listville2+'
';

	arrayLignes[0].cells[0].innerHTML=listville1;
	arrayLignes[0].cells[1].innerHTML='<button class="tiny secondary radius" onclick="genererdataviz(montab, '+idville2+', '+idville1+');">inverser</button>';
	arrayLignes[0].cells[2].innerHTML=listville2;

	i=1;
	while(i<arrayLignes.length)
	{

	// right
	arrayLignes[i].cells[0].innerHTML='
'+data[i][idville1]+'
';
	arrayLignes[i].cells[0].align = "right";

	// middle
	arrayLignes[i].cells[1].innerHTML="
"+data[i][0]+"
";
	arrayLignes[i].cells[1].align = "middle";

	// left
	arrayLignes[i].cells[2].innerHTML='
'+data[i][idville2]+'
';

	$('#dataviz-'+idville1+'-cr'+i).animate({'width': data[i][idville1]+'%'},750);
	$('#dataviz-'+idville2+'-cr'+i).animate({'width': data[i][idville2]+'%'},750);

	i++;
	}
}

<|endoftext|>


<commit_before>'use strict';

require("./index.less");

require('jquery');
require('angular');
require('availity-angular');

var app = require('./module');
var registration = require('./registration');

app.addModules([
  'ui.router',
  'availity',
  'availity.ui',
  'availity.ui.templates'
]);

app.controller('PageController', function($scope, AvModal, AV_GLOBALS) {

  var reg = {
    name: null,
    selectedState: null,
    date: null,
    states: AV_GLOBALS.REGIONS,
    onShow: function() {
      new AvModal({
        show: true,
        scope: $scope,
        templateUrl: 'registration/templates/notification.html'
      });
    }
  };

  reg.selectedState = reg.states[0];

  $scope.reg = reg;

});

app.config(function($stateProvider, $urlRouterProvider, avValProvider) {

  var defaultRules = {
    'name': {
      'required': {
        'message': 'Your name is required.'
      },
      'size': {
        'min': 2,
        'max': 10,
        'message': 'Your name must be between 2 and 10 characters.'
      }
    },
    'date': {
      'required': {
        'message': 'Date of service is required.'
      },
      'dateFormat': {
        'format': 'MM/DD/YYYY',
        'message': 'Format needs to be MM/DD/YYYY'
      }
    }
  };

  avValProvider.addRules({
    'default': defaultRules
  });

  $stateProvider
    .state('registration', {
      url: '/registration',
      template: registration.TEMPLATES.PAGE,
      controller: 'PageController'
    });

  $urlRouterProvider.otherwise('/registration');

});

module.exports = app;

<commit_msg>linter fix<commit_after>'use strict';

require('./index.less');

require('jquery');
require('angular');
require('availity-angular');

var app = require('./module');
var registration = require('./registration');

app.addModules([
  'ui.router',
  'availity',
  'availity.ui',
  'availity.ui.templates'
]);

app.controller('PageController', function($scope, AvModal, AV_GLOBALS) {

  var reg = {
    name: null,
    selectedState: null,
    date: null,
    states: AV_GLOBALS.REGIONS,
    onShow: function() {
      new AvModal({
        show: true,
        scope: $scope,
        templateUrl: 'registration/templates/notification.html'
      });
    }
  };

  reg.selectedState = reg.states[0];

  $scope.reg = reg;

});

app.config(function($stateProvider, $urlRouterProvider, avValProvider) {

  var defaultRules = {
    'name': {
      'required': {
        'message': 'Your name is required.'
      },
      'size': {
        'min': 2,
        'max': 10,
        'message': 'Your name must be between 2 and 10 characters.'
      }
    },
    'date': {
      'required': {
        'message': 'Date of service is required.'
      },
      'dateFormat': {
        'format': 'MM/DD/YYYY',
        'message': 'Format needs to be MM/DD/YYYY'
      }
    }
  };

  avValProvider.addRules({
    'default': defaultRules
  });

  $stateProvider
    .state('registration', {
      url: '/registration',
      template: registration.TEMPLATES.PAGE,
      controller: 'PageController'
    });

  $urlRouterProvider.otherwise('/registration');

});

module.exports = app;

<|endoftext|>


<commit_before>// patreon.js
// https://www.patreon.com/platform/documentation/webhooks
// ========
const BaseProvider = require('../util/BaseProvider');

// HTML Regular Expressions
const boldRegex = /(.*?)<\/strong>/;
const italicRegex = /(.*?)<\/em>/;
const underlineRegex = /(.*?)<\/u>/;
const anchorRegex = /(.*?)<\/a>/;
const ulRegex = /
(.*?)<\/ul>/;
const liRegex = /
(.*?)<\/li>/;
const imageRegex = //;

class Patreon extends BaseProvider {

    static getName() {
        return 'Patreon';
    }

    static _formatHTML(html, baseLink) {
        const newLineRegex = /
/g;
        //Match lists
        while (ulRegex.test(html)) {
            let match = ulRegex.exec(html);
            html = html.replace(ulRegex, match[1]);
            let str = match[1];
            while (liRegex.test(str)) {
                let match2 = liRegex.exec(match[1]);
                str = str.replace(match2[0], '');
                html = html.replace(liRegex, '\uFEFF\u00A0\u00A0\u00A0\u00A0\u2022 ' + match2[1] + '\n');
            }
        }
        //Match bold
        while (boldRegex.test(html)) {
            let match = boldRegex.exec(html);
            html = html.replace(boldRegex, '**' + match[1] + '**');
        }
        //Match Italic
        while (italicRegex.test(html)) {
            let match = italicRegex.exec(html);
            html = html.replace(italicRegex, '_' + match[1] + '_');
        }
        //Replace Underlined
        while (underlineRegex.test(html)) {
            let match = underlineRegex.exec(html);
            html = html.replace(underlineRegex, '__' + match[1] + '__');
        }
        //Replace Anchors
        while (anchorRegex.test(html)) {
            let match = anchorRegex.exec(html);
            let url = match[1].startsWith('#') ? baseLink + match[1] : match[1];
            html = html.replace(anchorRegex, '[' + match[2] + '](' + url + ')');
        }
        //Replace Images
        while (imageRegex.test(html)) {
            let match = imageRegex.exec(html);
            html = html.replace(imageRegex, '[View Image..](' + match[1] + ')');
        }
        //Replace all br tags
        html = html.replace(newLineRegex, '\n');
        return html;
    }

    constructor() {
        super();
        this.payload.setEmbedColor(0xF96854);
    }

    async getType() {
        return this.req.get('X-Patreon-Event');
    }

    _createUpdateCommon(type) {
        let embed = {};
        const creator_id = this.body.data.relationships.creator.data.id;
        const patron_id = this.body.data.relationships.patron.data.id;
        const reward_id = this.body.data.relationships.reward.data.id;

        const incl = this.body.included;
        let reward = null;
        for (let i = 0; i < incl.length; ++i) {
            const attr = incl[i];
            if (attr.id === creator_id) {
                if (type === 'delete') {
                    embed.title = 'Canceled $' + (this.body.data.attributes.amount_cents / 100).toFixed(2) + ' pledge to ' + attr.attributes.full_name;
                } else {
                    embed.title = 'Pledged $' + (this.body.data.attributes.amount_cents / 100).toFixed(2) + ' to ' + attr.attributes.full_name;
                }
                embed.url = attr.attributes.url;
                /*embed.thumbnail = {
                    url: attr.attributes.image_url
                };*/
            } else if (attr.id === patron_id) {
                embed.author = {
                    name: attr.attributes.full_name,
                    icon_url: attr.attributes.thumb_url,
                    url: attr.attributes.url
                };
            } else if (attr.id === reward_id) {
                reward = attr;
            }
        }
        if (reward != null) {
            embed.description = '---';
            const field = {
                name: 'Unlocked \'' + reward.attributes.title + '\'',
                value: '[$' + (reward.attributes.amount_cents / 100).toFixed(2) + '+ per month](https://www.patreon.com' + reward.attributes.url + ')\n' + this._formatHTML(reward.attributes.description, embed.url),
                inline: false
            };
            if (type === 'delete') {
                field.name = 'Lost \'' + reward.attributes.title + '\'';
            }
            embed.fields = [field];
        }
        this.payload.addEmbed(embed);
    }

    async pledgesCreate() {
        this._createUpdateCommon('create');
    }

    async pledgesUpdate() {
        this._createUpdateCommon('update');
    }

    async pledgesDelete() {
        this._createUpdateCommon('delete');
    }

}

module.exports = Patreon;<commit_msg>Fixing error in patreon provider due to static change.<commit_after>// patreon.js
// https://www.patreon.com/platform/documentation/webhooks
// ========
const BaseProvider = require('../util/BaseProvider');

// HTML Regular Expressions
const boldRegex = /(.*?)<\/strong>/;
const italicRegex = /(.*?)<\/em>/;
const underlineRegex = /(.*?)<\/u>/;
const anchorRegex = /(.*?)<\/a>/;
const ulRegex = /
(.*?)<\/ul>/;
const liRegex = /
(.*?)<\/li>/;
const imageRegex = //;

class Patreon extends BaseProvider {

    static getName() {
        return 'Patreon';
    }

    static _formatHTML(html, baseLink) {
        const newLineRegex = /
/g;
        //Match lists
        while (ulRegex.test(html)) {
            let match = ulRegex.exec(html);
            html = html.replace(ulRegex, match[1]);
            let str = match[1];
            while (liRegex.test(str)) {
                let match2 = liRegex.exec(match[1]);
                str = str.replace(match2[0], '');
                html = html.replace(liRegex, '\uFEFF\u00A0\u00A0\u00A0\u00A0\u2022 ' + match2[1] + '\n');
            }
        }
        //Match bold
        while (boldRegex.test(html)) {
            let match = boldRegex.exec(html);
            html = html.replace(boldRegex, '**' + match[1] + '**');
        }
        //Match Italic
        while (italicRegex.test(html)) {
            let match = italicRegex.exec(html);
            html = html.replace(italicRegex, '_' + match[1] + '_');
        }
        //Replace Underlined
        while (underlineRegex.test(html)) {
            let match = underlineRegex.exec(html);
            html = html.replace(underlineRegex, '__' + match[1] + '__');
        }
        //Replace Anchors
        while (anchorRegex.test(html)) {
            let match = anchorRegex.exec(html);
            let url = match[1].startsWith('#') ? baseLink + match[1] : match[1];
            html = html.replace(anchorRegex, '[' + match[2] + '](' + url + ')');
        }
        //Replace Images
        while (imageRegex.test(html)) {
            let match = imageRegex.exec(html);
            html = html.replace(imageRegex, '[View Image..](' + match[1] + ')');
        }
        //Replace all br tags
        html = html.replace(newLineRegex, '\n');
        return html;
    }

    constructor() {
        super();
        this.payload.setEmbedColor(0xF96854);
    }

    async getType() {
        return this.req.get('X-Patreon-Event');
    }

    _createUpdateCommon(type) {
        let embed = {};
        const creator_id = this.body.data.relationships.creator.data.id;
        const patron_id = this.body.data.relationships.patron.data.id;
        const reward_id = this.body.data.relationships.reward.data.id;

        const incl = this.body.included;
        let reward = null;
        for (let i = 0; i < incl.length; ++i) {
            const attr = incl[i];
            if (attr.id === creator_id) {
                if (type === 'delete') {
                    embed.title = 'Canceled $' + (this.body.data.attributes.amount_cents / 100).toFixed(2) + ' pledge to ' + attr.attributes.full_name;
                } else {
                    embed.title = 'Pledged $' + (this.body.data.attributes.amount_cents / 100).toFixed(2) + ' to ' + attr.attributes.full_name;
                }
                embed.url = attr.attributes.url;
                /*embed.thumbnail = {
                    url: attr.attributes.image_url
                };*/
            } else if (attr.id === patron_id) {
                embed.author = {
                    name: attr.attributes.full_name,
                    icon_url: attr.attributes.thumb_url,
                    url: attr.attributes.url
                };
            } else if (attr.id === reward_id) {
                reward = attr;
            }
        }
        if (reward != null) {
            embed.description = '---';
            const field = {
                name: 'Unlocked \'' + reward.attributes.title + '\'',
                value: '[$' + (reward.attributes.amount_cents / 100).toFixed(2) + '+ per month](https://www.patreon.com' + reward.attributes.url + ')\n' + Patreon._formatHTML(reward.attributes.description, embed.url),
                inline: false
            };
            if (type === 'delete') {
                field.name = 'Lost \'' + reward.attributes.title + '\'';
            }
            embed.fields = [field];
        }
        this.payload.addEmbed(embed);
    }

    async pledgesCreate() {
        this._createUpdateCommon('create');
    }

    async pledgesUpdate() {
        this._createUpdateCommon('update');
    }

    async pledgesDelete() {
        this._createUpdateCommon('delete');
    }

}

module.exports = Patreon;<|endoftext|>


<commit_before>apos.widgetPlayers.facebook = function($el) {
  // N.B. Even though this is a player, it's not getting refreshed
  // once it's been created. Hrmmm.

  var data = apos.getWidgetData($el),
      pageUrl = data.pageUrl;

  $.getJSON(
    '/apos-facebook/feed',
    {
      limit: (data.limit || 5),
      pageUrl: pageUrl,
    },
    function(posts) {

      //Define our posts object as well as the template and loader.
      var $posts = $el.find('[data-apos-facebook-posts]'),
          $postTemplate = $posts.find('[data-apos-facebook-post].apos-template'),
          $loader = $posts.find('[data-apos-facebook-loader]');

      if (!posts.length) {
        $el.trigger('aposFacebookNull');
        return;
      }

      function init(){
        removePlaceholder();
        generatePostMarkup(posts);
      }

      function removePlaceholder(){
        $posts.find('[data-apos-facebook-placeholder]').remove();
      }

      function removeTemplate(){
        $postTemplate.remove();
      };

      function buildTemplate($template){
        $template.$title = $template.find('[data-apos-facebook-title]');
        $template.$link = $template.find('[data-apos-facebook-link]');
        $template.$date = $template.find('[data-apos-facebook-date]');
        $template.$photo = $template.find('[data-apos-facebook-photo]');
        $template.$body = $template.find('[data-apos-facebook-body]');
        return $template;
      }

      function cloneTemplate($obj){
        $clone = $obj.clone();
        $clone.removeClass('apos-template');
        clone = buildTemplate($clone);
        return clone;
      }

      function getImageUrl(postId, callback){
        var id = postId;
        $.getJSON(
          '/apos-facebook/photo',
          { id: id},
          function(response) {
            return callback(response);
          }
        );
      }

      function getFacebookDate(date){
        var postDate = moment(date, 'MM-DD-YYYY'),
            postMonth = postDate.month(),
            postDay = postDate.date(),
            postYear = postDate.year(),
            thisYear = moment().year();
        return ((postYear != thisYear ) ? postMonth +"/"+postDay+"/"+postYear: postMonth +"/"+postDay);
      }

      function generatePostMarkup(posts){
        _.each(posts, function(post){
          //Clone our Template
          var $post = cloneTemplate($postTemplate);
          //console.log("The post should be:", $post);
          //Add Title
          if(post.name){
            $post.$title.text(post.name);
          } else {
            $post.$title.remove();
          }

          //Add Link href
          if(post.link){
            $post.$link.attr('href', post.link);
          }

          //Add Date
          if(post.date){
            var postDate = getFacebookDate(post.date);
            $post.$date.text(postDate || '');
          } else {
            $post.$date.remove();
          }

          //Add Photo based on type
          if (post.type === "photo"){
            getImageUrl(post.object_id, function(result){
              $post.$photo.find('img').attr('src', result);
            });
          } else if(post.photo){
            $post.$photo.find('img').attr('src', post.photo);
          }

          //Add Body
          if(post.body){
            $post.$body.html(post.body);
          } else {
            $post.$body.remove();
          }

          //Add Type --> Arguably, this could add a class as well.
          $post.attr('data-post-type', post.type || '');

          //If there's still a loader, kill it.
          $loader.remove();

          //Add That to the List

          $posts.append($post);
        });
        removeTemplate();
        apos.widgetPlayers.facebook.afterLoad($el, posts);
      };

      init();
    }
  );

  Date.fromISO = (function(){
    var testIso = '2011-11-24T09:00:27+0200';
    // Chrome
    var diso= Date.parse(testIso);
    if(diso===1322118027000) return function(s){
        return new Date(Date.parse(s));
    }
    // JS 1.8 gecko
    var noOffset = function(s) {
      var day= s.slice(0,-5).split(/\D/).map(function(itm){
        return parseInt(itm, 10) || 0;
      });
      day[1]-= 1;
      day= new Date(Date.UTC.apply(Date, day));
      var offsetString = s.slice(-5)
      var offset = parseInt(offsetString,10)/100;
      if (offsetString.slice(0,1)=="+") offset*=-1;
      day.setHours(day.getHours()+offset);
      return day.getTime();
    }
    if (noOffset(testIso)===1322118027000) {
       return noOffset;
    }
    return function(s){ // kennebec@SO + QTax@SO
        var day, tz,
        rx = /^(\d{4}\-\d\d\-\d\d([tT][\d:\.]*)?)([zZ]|([+\-])(\d\d):?(\d\d))?$/,

        p= rx.exec(s) || [];
        if(p[1]){
            day= p[1].split(/\D/).map(function(itm){
                return parseInt(itm, 10) || 0;
            });
            day[1]-= 1;
            day= new Date(Date.UTC.apply(Date, day));
            if(!day.getDate()) return NaN;
            if(p[5]){
                tz= parseInt(p[5], 10)/100*60;
                if(p[6]) tz += parseInt(p[6], 10);
                if(p[4]== "+") tz*= -1;
                if(tz) day.setUTCMinutes(day.getUTCMinutes()+ tz);
            }
            return day;
        }
        return NaN;
    }
})()
}

apos.widgetPlayers.facebook.afterLoad = function($el, posts){
  //You can do whatever you want here.
}
<commit_msg>Removed client side logic about dates<commit_after>apos.widgetPlayers.facebook = function($el) {
  // N.B. Even though this is a player, it's not getting refreshed
  // once it's been created. Hrmmm.

  var data = apos.getWidgetData($el),
      pageUrl = data.pageUrl;

  $.getJSON(
    '/apos-facebook/feed',
    {
      limit: (data.limit || 5),
      pageUrl: pageUrl,
    },
    function(posts) {

      //Define our posts object as well as the template and loader.
      var $posts = $el.find('[data-apos-facebook-posts]'),
          $postTemplate = $posts.find('[data-apos-facebook-post].apos-template'),
          $loader = $posts.find('[data-apos-facebook-loader]');

      if (!posts.length) {
        $el.trigger('aposFacebookNull');
        return;
      }

      function init(){
        removePlaceholder();
        generatePostMarkup(posts);
      }

      function removePlaceholder(){
        $posts.find('[data-apos-facebook-placeholder]').remove();
      }

      function removeTemplate(){
        $postTemplate.remove();
      };

      function buildTemplate($template){
        $template.$title = $template.find('[data-apos-facebook-title]');
        $template.$link = $template.find('[data-apos-facebook-link]');
        $template.$date = $template.find('[data-apos-facebook-date]');
        $template.$photo = $template.find('[data-apos-facebook-photo]');
        $template.$body = $template.find('[data-apos-facebook-body]');
        return $template;
      }

      function cloneTemplate($obj){
        $clone = $obj.clone();
        $clone.removeClass('apos-template');
        clone = buildTemplate($clone);
        return clone;
      }

      function getImageUrl(postId, callback){
        var id = postId;
        $.getJSON(
          '/apos-facebook/photo',
          { id: id},
          function(response) {
            return callback(response);
          }
        );
      }

      function generatePostMarkup(posts){
        _.each(posts, function(post){
          //Clone our Template
          var $post = cloneTemplate($postTemplate);
          //console.log("The post should be:", $post);
          //Add Title
          if(post.name){
            $post.$title.text(post.name);
          } else {
            $post.$title.remove();
          }

          //Add Link href
          if(post.link){
            $post.$link.attr('href', post.link);
          }

          //Add Date
          if(post.date){
            $post.$date.text(post.date || '');
          } else {
            $post.$date.remove();
          }

          //Add Photo based on type
          if (post.type === "photo"){
            getImageUrl(post.object_id, function(result){
              $post.$photo.find('img').attr('src', result);
            });
          } else if(post.photo){
            $post.$photo.find('img').attr('src', post.photo);
          }

          //Add Body
          if(post.body){
            $post.$body.html(post.body);
          } else {
            $post.$body.remove();
          }

          //Add Type --> Arguably, this could add a class as well.
          $post.attr('data-post-type', post.type || '');

          //If there's still a loader, kill it.
          $loader.remove();

          //Add That to the List

          $posts.append($post);
        });
        removeTemplate();
        apos.widgetPlayers.facebook.afterLoad($el, posts);
      };

      init();
    }
  );
}

apos.widgetPlayers.facebook.afterLoad = function($el, posts){
  //You can do whatever you want here.
}
<|endoftext|>


<commit_before>var myModule = angular.module("counterapp", ['ionic']);

// Function to be used for adding padded 0s to the time
function pad(d) {
    return (d < 10) ? '0' + d.toString() : d.toString();
}

// Simple function used to return the array index from the key value

function getArrayIndexForKey(arr, key, val){
    for(var i = 0; i < arr.length; i++){
	if(arr[i][key] == val)
	return i;
    }
    return -1;
}

myModule.controller("counterCtrl",['$scope','$timeout', function($scope,$timeout){

    $scope.jobCounter = function() {
	stopped = $timeout(function() {
	    $scope.seconds++;
	    $scope.tDur++;
	    if ($scope.seconds == 60) { $scope.minutes++; $scope.seconds = 0; }
	    if ($scope.minutes == 60) { $scope.hours++; $scope.minutes = 0; }
	    if ($scope.tDur%5 == 0) $scope.savesession('Session');
	    $scope.jobCounter();
	}, 1000);  //1000ms = 1 second
    }
    // Initializing timer values
    $scope.tDur = 0;
    $scope.seconds = 0;
    $scope.hours = 0;
    $scope.minutes = 0;

    //Formatting the time -> needs to be function
    while ($scope.seconds >= 3600) {
	$scope.seconds = $scope.seconds - 3600;
	$scope.hours++;
    }

    while ($scope.seconds >= 60) {
	$scope.seconds = $scope.seconds - 60;
	$scope.minutes++;
    }

    var stopped;
    var savetimer;

    $scope.session =
	{'intervals': [{start : '', stop: ''}],
	 'duration': 0 };

    // Check for stored sessions
    var storedSession = localStorage.getItem('Session_' + $scope.job.id);
    if (storedSession == (null)) {
	//No local storage load blank session for now
	$scope.session =
	    {'intervals': [{start : '', stop: ''}],
	     'duration': 0 };
	// If person clicks Start, jobs loads to active session
    }
    else{
	// load stored session
        $scope.session = JSON.parse(storedSession);
	$scope.tDur = $scope.session.duration;
	$scope.seconds = $scope.tDur;

	while ($scope.seconds >= 3600) {
	    $scope.seconds = $scope.seconds - 3600;
	    $scope.hours++;
	}

	while ($scope.seconds >= 60) {
	    $scope.seconds = $scope.seconds - 60;
	    $scope.minutes++;
	}
	if ($scope.session.intervals[$scope.session.intervals.length - 1].stop == 'false') {
	    $scope.ResumeDisabled = true;
	    $scope.StartDisabled = true;
	    $scope.jobCounter();
	}
    }
    // These are the functions used when clicking the corresponding
    // buttons displayed on each job

    $scope.start = function() {
	$scope.StartDisabled = true;
	$scope.ResumeDisabled = true;
	$scope.session.intervals[0].start = Date.now();
	$scope.session.intervals[0].stop = 'false';
	$scope.savesession('Session');
	$scope.jobCounter();
    };

    $scope.stop = function(){
	$scope.ResumeDisabled = false;
	//Stops the current timer
	$timeout.cancel(stopped);
	$scope.ResumeDisabled = false;
	$scope.intervalstop();
	$scope.savesession('Session');
	//Add a new start interval
    }

    $scope.resume = function(){
	$scope.ResumeDisabled = true;
	$scope.session.intervals.push({'start': Date.now(),'stop': 'false'});
	$scope.savesession('Session');
	$scope.jobCounter();
    }

    $scope.reset = function(){
	$scope.StartDisabled = false;
	$scope.ResumeDisabled = true;
	$scope.clearsession();
	$timeout.cancel(stopped);
	$scope.cleartime();
    }

    $scope.log = function(){
	$scope.intervalstop();
	$scope.savesession('Session');
	$scope.savesession('Archive');
	$scope.reset();
    }

    $scope.removejob = function(){
	$scope.clearsession();
	$timeout.cancel(stopped);
	$scope.cleartime();
	localStorage.removeItem('Session_' + $scope.job.id);
	var indextoremove = getArrayIndexForKey($scope.jobs, "id", $scope.job.id);
	$scope.jobs.splice(indextoremove, 1)
    }

    // These functions are used internally to create more readable,
    // aswell as modular code.

    $scope.savesession = function(name){
	$scope.session.duration = $scope.tDur;
	localStorage.setItem(name + '_' + $scope.job.id, JSON.stringify($scope.session));
    }

    $scope.intervalstop = function(){
	$scope.session.intervals[$scope.session.intervals.length - 1].stop = Date.now();
    }

    $scope.clearsession = function(){
	$scope.session =
	    {'intervals': [
		{'start': '',
		 'stop' : ''}
	    ],
	    'duration': 0
	    }
	localStorage.removeItem('Session_' + $scope.job.id);
    }

    $scope.cleartime = function(){
	$scope.seconds = 0;
	$scope.minutes = 0;
	$scope.hours = 0;
	$scope.tDur = 0;
    }

}]);

// The following is run when the the job list is first created

function JobsListCtrl ($scope, $timeout) {
    //Store in local storage with job-id
    //Check Local Storage
    var storedJobs = localStorage.getItem('jobs');
    if (storedJobs == (null)) {
	//No local storage load test data
	$scope.jobs = [
	    { 'id' : '2X0XAA', 'name' : 'Working on the MOM app' },
	    { 'id' : 'AH49SJ', 'name' : 'Creating logo'}
	];
	// If person clicks Start, jobs loads to active session
    }
    else{
	// load stored jobs
        $scope.jobs = JSON.parse(storedJobs);
    }

/*
    runCounter = function() {
	//GLOBAL TIMER TO SAVE ALL SESSIONS
	$timeout(runCounter, 5000);
    };

    runCounter();
*/
}
<commit_msg>fixed travis error<commit_after>var myModule = angular.module("counterapp", ['ionic']);
angular.module('myApp.services', []).value('version', '0.1');

// Function to be used for adding padded 0s to the time
function pad(d) {
    return (d < 10) ? '0' + d.toString() : d.toString();
}

// Simple function used to return the array index from the key value

function getArrayIndexForKey(arr, key, val){
    for(var i = 0; i < arr.length; i++){
	if(arr[i][key] == val)
	return i;
    }
    return -1;
}

myModule.controller("counterCtrl",['$scope','$timeout', function($scope,$timeout){

    $scope.jobCounter = function() {
	stopped = $timeout(function() {
	    $scope.seconds++;
	    $scope.tDur++;
	    if ($scope.seconds == 60) { $scope.minutes++; $scope.seconds = 0; }
	    if ($scope.minutes == 60) { $scope.hours++; $scope.minutes = 0; }
	    if ($scope.tDur%5 == 0) $scope.savesession('Session');
	    $scope.jobCounter();
	}, 1000);  //1000ms = 1 second
    }
    // Initializing timer values
    $scope.tDur = 0;
    $scope.seconds = 0;
    $scope.hours = 0;
    $scope.minutes = 0;

    //Formatting the time -> needs to be function
    while ($scope.seconds >= 3600) {
	$scope.seconds = $scope.seconds - 3600;
	$scope.hours++;
    }

    while ($scope.seconds >= 60) {
	$scope.seconds = $scope.seconds - 60;
	$scope.minutes++;
    }

    var stopped;
    var savetimer;

    $scope.session =
	{'intervals': [{start : '', stop: ''}],
	 'duration': 0 };

    // Check for stored sessions
    var storedSession = localStorage.getItem('Session_' + $scope.job.id);
    if (storedSession == (null)) {
	//No local storage load blank session for now
	$scope.session =
	    {'intervals': [{start : '', stop: ''}],
	     'duration': 0 };
	// If person clicks Start, jobs loads to active session
    }
    else{
	// load stored session
        $scope.session = JSON.parse(storedSession);
	$scope.tDur = $scope.session.duration;
	$scope.seconds = $scope.tDur;

	while ($scope.seconds >= 3600) {
	    $scope.seconds = $scope.seconds - 3600;
	    $scope.hours++;
	}

	while ($scope.seconds >= 60) {
	    $scope.seconds = $scope.seconds - 60;
	    $scope.minutes++;
	}
	if ($scope.session.intervals[$scope.session.intervals.length - 1].stop == 'false') {
	    $scope.ResumeDisabled = true;
	    $scope.StartDisabled = true;
	    $scope.jobCounter();
	}
    }
    // These are the functions used when clicking the corresponding
    // buttons displayed on each job

    $scope.start = function() {
	$scope.StartDisabled = true;
	$scope.ResumeDisabled = true;
	$scope.session.intervals[0].start = Date.now();
	$scope.session.intervals[0].stop = 'false';
	$scope.savesession('Session');
	$scope.jobCounter();
    };

    $scope.stop = function(){
	$scope.ResumeDisabled = false;
	//Stops the current timer
	$timeout.cancel(stopped);
	$scope.ResumeDisabled = false;
	$scope.intervalstop();
	$scope.savesession('Session');
	//Add a new start interval
    }

    $scope.resume = function(){
	$scope.ResumeDisabled = true;
	$scope.session.intervals.push({'start': Date.now(),'stop': 'false'});
	$scope.savesession('Session');
	$scope.jobCounter();
    }

    $scope.reset = function(){
	$scope.StartDisabled = false;
	$scope.ResumeDisabled = true;
	$scope.clearsession();
	$timeout.cancel(stopped);
	$scope.cleartime();
    }

    $scope.log = function(){
	$scope.intervalstop();
	$scope.savesession('Session');
	$scope.savesession('Archive');
	$scope.reset();
    }

    $scope.removejob = function(){
	$scope.clearsession();
	$timeout.cancel(stopped);
	$scope.cleartime();
	localStorage.removeItem('Session_' + $scope.job.id);
	var indextoremove = getArrayIndexForKey($scope.jobs, "id", $scope.job.id);
	$scope.jobs.splice(indextoremove, 1)
    }

    // These functions are used internally to create more readable,
    // aswell as modular code.

    $scope.savesession = function(name){
	$scope.session.duration = $scope.tDur;
	localStorage.setItem(name + '_' + $scope.job.id, JSON.stringify($scope.session));
    }

    $scope.intervalstop = function(){
	$scope.session.intervals[$scope.session.intervals.length - 1].stop = Date.now();
    }

    $scope.clearsession = function(){
	$scope.session =
	    {'intervals': [
		{'start': '',
		 'stop' : ''}
	    ],
	    'duration': 0
	    }
	localStorage.removeItem('Session_' + $scope.job.id);
    }

    $scope.cleartime = function(){
	$scope.seconds = 0;
	$scope.minutes = 0;
	$scope.hours = 0;
	$scope.tDur = 0;
    }

}]);

// The following is run when the the job list is first created

function JobsListCtrl ($scope, $timeout) {
    //Store in local storage with job-id
    //Check Local Storage
    var storedJobs = localStorage.getItem('jobs');
    if (storedJobs == (null)) {
	//No local storage load test data
	$scope.jobs = [
	    { 'id' : '2X0XAA', 'name' : 'Working on the MOM app' },
	    { 'id' : 'AH49SJ', 'name' : 'Creating logo'}
	];
	// If person clicks Start, jobs loads to active session
    }
    else{
	// load stored jobs
        $scope.jobs = JSON.parse(storedJobs);
    }

/*
    runCounter = function() {
	//GLOBAL TIMER TO SAVE ALL SESSIONS
	$timeout(runCounter, 5000);
    };

    runCounter();
*/
}
<|endoftext|>


<commit_before>var LOG_FUNC = console.log.bind(console);
var logData = [];
console.log = function(){
  args = Array.prototype.slice(arguments);
  logData.push(args);
  LOG_FUNC(LOG_FUNC.apply(null, args);
};

var CDN = 'http://cdn.peerjs.com';
var FILE = 'peer.js';

var FULL_TEST_TIMEOUT = 30000;

function loadScript(v, cb) {
  if (!cb) {
    cb = noop;
  }
  var loadTimeout = setTimeout(function(){
    cb(new Error('Could not load PeerJS v' + v));
  }, 2000);
  var script = document.createElement('script');
  script.onload = function(){
    clearTimeout(loadTimeout);
    cb()
  };
  script.setAttribute("type", "text/javascript");
  script.setAttribute("src", CDN + "/" + v + "/" + FILE);
  document.getElementsByTagName("head")[0].appendChild(script);
}

function saveTestData(id, data, cb) {
  if (!cb) {
    cb = noop;
  }
  var out = {};
  out[ROLE] = data;
  out.testId = id;
  post('/save', out, cb);
}

function end(workerId, msg) {
  end = function(){};
  // Ensure end only runs once
  clearTimeout(testTimeout);
  if (TEST_ID) {
    console.log(msg);
    saveTestData(TEST_ID, {ended: msg, log: logData});
  }
  post('/end', {workerId: workerId, msg: msg}, noop);
}

// Load testing dependency
var queryData = getQueryData();

var WORKER_ID = queryData.WORKER_ID;
var TEST_ID = queryData.TEST_ID;
var ROLE = queryData.ROLE; // 'client' or 'host'
var PEERJS_VERSION = queryData.PEERJS_VERSION || '0';

if (!WORKER_ID) {
  // Shit
  throw new Error('No WORKER_ID');
}
if (!ROLE) {
  // Shit
  throw new Error('No ROLE specified');
}
if (!TEST_ID) {
  end(WORKER_ID, 'Missing TEST_ID');
  throw new Error('Missing TEST_ID');
}

loadScript(PEERJS_VERSION, function(err){
  if (err) {
    console.log('Error:', err.message);
    end(WORKER_ID, err.message);
  } else {
    console.log('Script loaded');
    saveTestData(TEST_ID, {
      browser: browserInfo(),
      peerJSVersion: PEERJS_VERSION
    });
    init();
  }
});

var testTimeout = setTimeout(function(){
  end(WORKER_ID, 'timeout');
}, FULL_TEST_TIMEOUT);

<commit_msg>FIx console log shim<commit_after>var logData = [];
console.log = function(){
  args = Array.prototype.slice.call(arguments, 0);
  logData.push(args.join(' '));
};

var CDN = 'http://cdn.peerjs.com';
var FILE = 'peer.js';

var FULL_TEST_TIMEOUT = 30000;

function loadScript(v, cb) {
  if (!cb) {
    cb = noop;
  }
  var loadTimeout = setTimeout(function(){
    cb(new Error('Could not load PeerJS v' + v));
  }, 2000);
  var script = document.createElement('script');
  script.onload = function(){
    clearTimeout(loadTimeout);
    cb()
  };
  script.setAttribute("type", "text/javascript");
  script.setAttribute("src", CDN + "/" + v + "/" + FILE);
  document.getElementsByTagName("head")[0].appendChild(script);
}

function saveTestData(id, data, cb) {
  if (!cb) {
    cb = noop;
  }
  var out = {};
  out[ROLE] = data;
  out.testId = id;
  post('/save', out, cb);
}

function end(workerId, msg) {
  end = function(){};
  // Ensure end only runs once
  clearTimeout(testTimeout);
  if (TEST_ID) {
    console.log(msg);
    saveTestData(TEST_ID, {ended: msg, log: logData});
  }
  post('/end', {workerId: workerId, msg: msg}, noop);
}

// Load testing dependency
var queryData = getQueryData();

var WORKER_ID = queryData.WORKER_ID;
var TEST_ID = queryData.TEST_ID;
var ROLE = queryData.ROLE; // 'client' or 'host'
var PEERJS_VERSION = queryData.PEERJS_VERSION || '0';

if (!WORKER_ID) {
  // Shit
  throw new Error('No WORKER_ID');
}
if (!ROLE) {
  // Shit
  throw new Error('No ROLE specified');
}
if (!TEST_ID) {
  end(WORKER_ID, 'Missing TEST_ID');
  throw new Error('Missing TEST_ID');
}

loadScript(PEERJS_VERSION, function(err){
  if (err) {
    console.log('Error:', err.message);
    end(WORKER_ID, err.message);
  } else {
    console.log('Script loaded');
    saveTestData(TEST_ID, {
      browser: browserInfo(),
      peerJSVersion: PEERJS_VERSION
    });
    init();
  }
});

var testTimeout = setTimeout(function(){
  end(WORKER_ID, 'timeout');
}, FULL_TEST_TIMEOUT);

<|endoftext|>


<commit_before>$(document).ready(function() {
	//$("#category").val($("#target option:first").val());
	$('#category').change(function() {
		var category = $("#category").val();
		$.fn.searchSpecifications(category);
	});

	$( "#product" ).submit(function() {
		var select = $('select[name="measures[]"] option:selected');
		result = true;
		$(select).each(function(){
			if(!this.hasAttribute('value')) {
				result = false;
				$("#specification-error").html("

debe seleccionar las especificaciones del producto

");
			}
		});
		return result;
	});
});

$.fn.searchSpecifications = function(category) {
	if (category>0) {
		$.ajax({
			type : "POST",
			url : "search-specifications",
			data : {
				category : 			category,
			}
		})
		.done(
			function(result) {
				if (typeof result === 'object') {
					$("#tab-product-specifications").html("
");

					$.each(result.specification, function( id, specification ) {
						var select = "<select name='measures[]'>" ;
						select += "<option></option>" ;
						$.each(specification.measure, function( id, measure ) {
							select += "<option value='"+id+"'>"+measure+"</option>" ;
						});
						select += "<select>" ;

						var image = !specification.image || 0 === specification.name.length ? "/img/icons/picture.png" : "/images/specification/"+specification.image ;
						$("#tab-product-specifications ul").append("
 "+specification.name+"
"+select+"

");
					});
				} else {
					console.log("debe seleccionar una categoria");
				}
			});
	}
	else
		$("#tab-product-specifications ul").html("");
}<commit_msg>test js production<commit_after>$(document).ready(function() {
	//$("#category").val($("#target option:first").val());
	$('#category').change(function() {
		var category = $("#category").val();
		$.fn.searchSpecifications(category);
	});

	$( "#product" ).submit(function() {
		var select = $('select[name="measures[]"] option:selected');
		result = true;
		$(select).each(function(){
			if(!this.hasAttribute('value')) {
				result = false;
				$("#specification-error").html("

debe seleccionar las especificaciones del producto

");
			}
		});
		return result;
	});
});

$.fn.searchSpecifications = function(category) {
	console.log("category "+category)
	if (category>0) {
		$.ajax({
			type : "POST",
			url : "search-specifications",
			data : {
				category : 			category,
			}
		})
		.done(
			function(result) {
				if (typeof result === 'object') {
					$("#tab-product-specifications").html("
");

					$.each(result.specification, function( id, specification ) {
						var select = "<select name='measures[]'>" ;
						select += "<option></option>" ;
						$.each(specification.measure, function( id, measure ) {
							select += "<option value='"+id+"'>"+measure+"</option>" ;
						});
						select += "<select>" ;

						var image = !specification.image || 0 === specification.name.length ? "/img/icons/picture.png" : "/images/specification/"+specification.image ;
						$("#tab-product-specifications ul").append("
 "+specification.name+"
"+select+"

");
					});
				} else {
					console.log("debe seleccionar una categoria");
				}
			});
	}
	else
		$("#tab-product-specifications ul").html("");
}<|endoftext|>


<commit_before>function getUrl(){
  var currentUrl = window.location.href;
  var locationToCut = currentUrl.indexOf("?");
  currentUrl = currentUrl.substring(locationToCut+1);
	return currentUrl;

}

function routTo(currentUrl, back){

  if (back == undefined){back = false};

  var slashPostion = currentUrl.indexOf("/");
  //var currentType = currentUrl.slice(0,slashPostion) || sessionStorage.getItem("_entityType");
  var currentType = sessionStorage.getItem("_entityType");

  //var currentEntety = currentUrl.slice(slashPostion+1);
  //var currentEntety = sessionStorage.getItem("_urlAfterLogin");
  var currentEntety = sessionStorage.getItem("_currentEntity");

  switch (currentType){
    case "group":
      DB.child("groups/"+currentEntety).once("value", function (group){
        if(group.exists()){
          showGroup(currentEntety, back);
//          if (!back){setUrl("groups", currentEntety)};
        } else { console.log("group "+currentEntety+" do not exist"); }
      })
      break;
    case "topic":
      DB.child("topics/"+currentEntety).once("value", function (topic){
        if (topic.exists()){
          showTopic(currentEntety, back);
//          if (!back){setUrl("topics", currentEntety)};
        } else { console.log("topic "+currentEntety+" do not exist");}
      })
      break;
    case "question":
      DB.child("questions/"+currentEntety).once("value", function (question){
        if (question.exists()){
          showQuestion(currentEntety, back);
//          if (!back){setUrl("questions", currentEntety)};
        } else { console.log("question "+currentEntety+" do not exist");}
      })
      break;
    default:
      showPublicGroups();
  }

};

function setUrl(type, uid){
  //get domain
  var currentUrl = window.location.href;
  var locationToCut = currentUrl.indexOf("?");
  var domainUrl = currentUrl.slice(0,locationToCut);

  if(type == undefined || uid == undefined){
    history.pushState({}, uid, domainUrl );
  } else{

    var typeEntety = {type: type, entety: uid};

    var url = domainUrl+"?"+type+"/"+uid;
    history.pushState(typeEntety, uid, url );
  }

}
<commit_msg>fix typo entity/entety<commit_after>function getUrl(){
  var currentUrl = window.location.href;
  var locationToCut = currentUrl.indexOf("?");
  currentUrl = currentUrl.substring(locationToCut+1);
	return currentUrl;

}

function routTo(currentUrl, back){

  if (back == undefined){back = false};

  var slashPostion = currentUrl.indexOf("/");
  //var currentType = currentUrl.slice(0,slashPostion) || sessionStorage.getItem("_entityType");
  var currentType = sessionStorage.getItem("_entityType");

  //var currentEntity = currentUrl.slice(slashPostion+1);
  //var currentEntity = sessionStorage.getItem("_urlAfterLogin");
  var currentEntity = sessionStorage.getItem("_currentEntity");

  switch (currentType){
    case "group":
      DB.child("groups/"+currentEntity).once("value", function (group){
        if(group.exists()){
          showGroup(currentEntity, back);
        } else { console.log("group "+currentEntity+" do not exist"); }
      })
      break;
    case "topic":
      DB.child("topics/"+currentEntity).once("value", function (topic){
        if (topic.exists()){
          showTopic(currentEntity, back);
        } else { console.log("topic "+currentEntity+" do not exist");}
      })
      break;
    case "question":
      DB.child("questions/"+currentEntity).once("value", function (question){
        if (question.exists()){
          showQuestion(currentEntity, back);
        } else { console.log("question "+currentEntity+" do not exist");}
      })
      break;
    default:
      showPublicGroups();
  }

};

function setUrl(type, uid){
  //get domain
  var currentUrl = window.location.href;
  var locationToCut = currentUrl.indexOf("?");
  var domainUrl = currentUrl.slice(0,locationToCut);

  if(type == undefined || uid == undefined){
    history.pushState({}, uid, domainUrl );
  } else{

    var typeEntity = {type: type, entity: uid};

    var url = domainUrl+"?"+type+"/"+uid;
    history.pushState(typeEntity, uid, url );
  }

}
<|endoftext|>


<commit_before>var currentQuestion = null;
var questionBank = null;
var answers = [];

function getSelectedAnswer() {
	var selectedAnswer = document.querySelector("input[name='nr-question']:checked");
	var answer = null;
	if (selectedAnswer) {
		var answerId = selectedAnswer.getAttribute("nr-answer");
		answer = document.getElementById(answerId).innerHTML;
	}

	return answer;
}

function getQuestion() {
	currentQuestion = questionBank.shift();
}

function getQuestionNumber() {
	return Math.abs(questionBank.length - QUIZ_LENGTH);
}

function queryQuestionsWithDifficulty(questions, difficulty, amount) {
	var allQuestions = questions.filter(function(question) {
		return question["difficulty"] === difficulty
	});
	var result = [];
	for (var i = 0; i < amount; i++) {
		var index = Math.floor(Math.random() * allQuestions.length);
		result.push(allQuestions.splice(index, 1)[0]);
	}

	return result;
}

function getFirstQuestion() {
	var questions = jQuery.extend(true, [], QUESTIONS);
	var easyQuestions = queryQuestionsWithDifficulty(questions, "easy", 8);
	var mediumQuestions = queryQuestionsWithDifficulty(questions, "medium", 7);
	var hardQuestions = queryQuestionsWithDifficulty(questions, "hard", 6);
	var expertQuestions = queryQuestionsWithDifficulty(questions, "expert", 4);
	questionBank = [].concat(easyQuestions, mediumQuestions, hardQuestions, expertQuestions);

	getQuestion();
}

function startTest() {
	getFirstQuestion();
	fillQuestion();

	document.getElementById("homepage-area").style.display = "none";
	document.getElementById("finished-area").style.display = "none";
	document.getElementById("question-area").style.display = "block";
}

function finishTest() {
	$.post("/grade-quiz", JSON.stringify({ "answers": answers }), function(data) {
		var mastery = data.mastery_score;
		console.log("DATA: " + JSON.stringify(data));
		console.log("mastery: " + mastery)
		var masteryRank = document.getElementById("mastery-rank");

		var progressBar = document.getElementById("percent-progress");
		progressBar.setAttribute("aria-valuenow", mastery);
		progressBar.style.width = mastery + "%";

		document.getElementById("percent-correct-label").innerHTML = mastery.toString();

		var progressClassname = "progress-bar progress-bar-striped active";
		var masteryClassname = "label";
		var rank = "";
		if (mastery >= 80) {
			progressClassname += " progress-bar-success";
			masteryClassname += " label-success";
			rank = "Companion";
		}
		else if (mastery >= 50) {
			progressClassname += " progress-bar-warning";
			masteryClassname += " label-warning";
			rank = "Friend";
		}
		else {
			progressClassname += " progress-bar-danger";
			masteryClassname += " label-danger";
			rank = "Associate";
		}
		progressBar.className = progressClassname;
		masteryRank.className = masteryClassname;
		masteryRank.innerHTML = rank + " of Nick";

		document.getElementById("question-area").style.display = "none";
		document.getElementById("finished-area").style.display = "block";
		window.scrollTo(0, 0);
	});
 }

function fillQuestion() {
	document.getElementById("question-title").innerHTML = "Question #" + getQuestionNumber();
	document.getElementById("question-text").innerHTML = currentQuestion["question_text"];
	document.getElementById("possible-answer-1").innerHTML = currentQuestion["possible_answers"][0];
	document.getElementById("possible-answer-2").innerHTML = currentQuestion["possible_answers"][1];
	document.getElementById("possible-answer-3").innerHTML = currentQuestion["possible_answers"][2];
	document.getElementById("possible-answer-4").innerHTML = currentQuestion["possible_answers"][3];
}

function getNextQuestion(answer) {
	var key = currentQuestion["question_id"];
	var value = currentQuestion["possible_answers"].indexOf(answer);
	answers.push({ "key": key, "value": value });

	if (getQuestionNumber() >= QUIZ_LENGTH) {
		finishTest();
	}
	else {
		getQuestion();
		fillQuestion();
	}
}

function onAnswerSubmit() {
	var answer = getSelectedAnswer();

	if (answer) {
		document.getElementById("no-answer-alert").style.display = "none";
		getNextQuestion(answer);
	}
	else {
		document.getElementById("no-answer-alert").style.display = "block";
	}
}<commit_msg>Fixed bug where every test taken after the first was giving the original answers that were input the first time<commit_after>var currentQuestion = null;
var questionBank = null;
var answers = [];

function getSelectedAnswer() {
	var selectedAnswer = document.querySelector("input[name='nr-question']:checked");
	var answer = null;
	if (selectedAnswer) {
		var answerId = selectedAnswer.getAttribute("nr-answer");
		answer = document.getElementById(answerId).innerHTML;
	}

	return answer;
}

function getQuestion() {
	currentQuestion = questionBank.shift();
}

function getQuestionNumber() {
	return Math.abs(questionBank.length - QUIZ_LENGTH);
}

function queryQuestionsWithDifficulty(questions, difficulty, amount) {
	var allQuestions = questions.filter(function(question) {
		return question["difficulty"] === difficulty
	});
	var result = [];
	for (var i = 0; i < amount; i++) {
		var index = Math.floor(Math.random() * allQuestions.length);
		result.push(allQuestions.splice(index, 1)[0]);
	}

	return result;
}

function getFirstQuestion() {
	var questions = jQuery.extend(true, [], QUESTIONS);
	var easyQuestions = queryQuestionsWithDifficulty(questions, "easy", 8);
	var mediumQuestions = queryQuestionsWithDifficulty(questions, "medium", 7);
	var hardQuestions = queryQuestionsWithDifficulty(questions, "hard", 6);
	var expertQuestions = queryQuestionsWithDifficulty(questions, "expert", 4);
	questionBank = [].concat(easyQuestions, mediumQuestions, hardQuestions, expertQuestions);

	getQuestion();
}

function startTest() {
	getFirstQuestion();
	fillQuestion();

	document.getElementById("homepage-area").style.display = "none";
	document.getElementById("finished-area").style.display = "none";
	document.getElementById("question-area").style.display = "block";
}

function finishTest() {
	$.post("/grade-quiz", JSON.stringify({ "answers": answers }), function(data) {
		var mastery = data.mastery_score;
		console.log("DATA: " + JSON.stringify(data));
		console.log("mastery: " + mastery)
		var masteryRank = document.getElementById("mastery-rank");

		var progressBar = document.getElementById("percent-progress");
		progressBar.setAttribute("aria-valuenow", mastery);
		progressBar.style.width = mastery + "%";

		document.getElementById("percent-correct-label").innerHTML = mastery.toString();

		var progressClassname = "progress-bar progress-bar-striped active";
		var masteryClassname = "label";
		var rank = "";
		if (mastery >= 80) {
			progressClassname += " progress-bar-success";
			masteryClassname += " label-success";
			rank = "Companion";
		}
		else if (mastery >= 50) {
			progressClassname += " progress-bar-warning";
			masteryClassname += " label-warning";
			rank = "Friend";
		}
		else {
			progressClassname += " progress-bar-danger";
			masteryClassname += " label-danger";
			rank = "Associate";
		}
		progressBar.className = progressClassname;
		masteryRank.className = masteryClassname;
		masteryRank.innerHTML = rank + " of Nick";

		answers = [];
		document.getElementById("question-area").style.display = "none";
		document.getElementById("finished-area").style.display = "block";
		window.scrollTo(0, 0);
	});
 }

function fillQuestion() {
	document.getElementById("question-title").innerHTML = "Question #" + getQuestionNumber();
	document.getElementById("question-text").innerHTML = currentQuestion["question_text"];
	document.getElementById("possible-answer-1").innerHTML = currentQuestion["possible_answers"][0];
	document.getElementById("possible-answer-2").innerHTML = currentQuestion["possible_answers"][1];
	document.getElementById("possible-answer-3").innerHTML = currentQuestion["possible_answers"][2];
	document.getElementById("possible-answer-4").innerHTML = currentQuestion["possible_answers"][3];
}

function getNextQuestion(answer) {
	var key = currentQuestion["question_id"];
	var value = currentQuestion["possible_answers"].indexOf(answer);
	answers.push({ "key": key, "value": value });

	if (getQuestionNumber() >= QUIZ_LENGTH) {
		finishTest();
	}
	else {
		getQuestion();
		fillQuestion();
	}
}

function onAnswerSubmit() {
	var answer = getSelectedAnswer();

	if (answer) {
		document.getElementById("no-answer-alert").style.display = "none";
		getNextQuestion(answer);
	}
	else {
		document.getElementById("no-answer-alert").style.display = "block";
	}
}<|endoftext|>