<commit_before>var lbry = {
  isConnected: false,
  rootPath: '.',
  daemonConnectionString: 'http://localhost:5279/lbryapi',
  colors: {
    primary: '#155B4A'
  },
  defaultClientSettings: {
    showNsfw: false,
  }
};

lbry.jsonrpc_call = function (connectionString, method, params, callback, errorCallback, connectFailedCallback, timeout) {
  var xhr = new XMLHttpRequest;
  if (typeof connectFailedCallback !== 'undefined') {
    if (timeout) {
      xhr.timeout = timeout;
    }

    xhr.addEventListener('error', function (e) {
      connectFailedCallback(e);
    });
    xhr.addEventListener('timeout', function() {
      connectFailedCallback(new Error('XMLHttpRequest connection timed out'));
    })
  }
  xhr.addEventListener('load', function() {
    var response = JSON.parse(xhr.responseText);

    if (response.error) {
      if (errorCallback) {
        errorCallback(response.error);
      } else {
        var errorEvent = new CustomEvent('unhandledError', {
          detail: {
            connectionString: connectionString,
            method: method,
            params: params,
            code: response.error.code,
            message: response.error.message,
            data: response.error.data
          }
        });
        document.dispatchEvent(errorEvent)
      }
    } else if (callback) {
      callback(response.result);
    }
  });

  if (connectFailedCallback) {
    xhr.addEventListener('error', function (event) {
      connectFailedCallback(event);
    });
  } else {
    xhr.addEventListener('error', function (event) {
      var errorEvent = new CustomEvent('unhandledError', {
        detail: {
          connectionString: connectionString,
          method: method,
          params: params,
          code: xhr.status,
          message: 'Connection to API server failed'
        }
      });
      document.dispatchEvent(errorEvent);
    });
  }

  xhr.open('POST', connectionString, true);
  xhr.send(JSON.stringify({
    'jsonrpc': '2.0',
    'method': method,
    'params': params,
    'id': 0
  }));
}

lbry.call = function (method, params, callback, errorCallback, connectFailedCallback) {
  lbry.jsonrpc_call(lbry.daemonConnectionString, method, [params], callback, errorCallback, connectFailedCallback);
}

//core
lbry.connect = function(callback)
{
  // Check every half second to see if the daemon's running.
  // Returns true to callback once connected, or false if it takes too long and we give up.
  function checkDaemonRunning(tryNum=0) {
    lbry.daemonRunningStatus(function (runningStatus) {
      if (runningStatus) {
        lbry.isConnected = true;
        callback(true);
      } else {
        if (tryNum <= 600) { // Move # of tries into constant or config option
          setTimeout(function () {
            checkDaemonRunning(tryNum + 1);
          }, 500);
        } else {
          callback(false);
        }
      }
    });
  }
  checkDaemonRunning();
}

lbry.daemonRunningStatus = function (callback) {
  // Returns true/false whether the daemon is running (i.e. fully conncected to the network),
  // or null if the AJAX connection to the daemon fails.

  lbry.call('is_running', {}, callback, null, function () {
    callback(null);
  });
};

lbry.getDaemonStatus = function (callback) {
  lbry.call('daemon_status', {}, callback);
};

lbry.getStartNotice = function(callback) {
  lbry.call('get_start_notice', {}, callback);
}

lbry.checkFirstRun = function(callback) {
  lbry.call('is_first_run', {}, callback);
}

lbry.getNewAddress = function(callback) {
  lbry.call('get_new_address', {}, callback);
}

lbry.checkAddressIsMine = function(address, callback) {
  lbry.call('address_is_mine', {address: address}, callback);
}

lbry.getDaemonSettings = function(callback) {
  lbry.call('get_settings', {}, callback);
}

lbry.setDaemonSettings = function(settings, callback) {
  lbry.call('set_settings', settings, callback);
}

lbry.setDaemonSetting = function(setting, value, callback) {
  var setSettingsArgs = {};
  setSettingsArgs[setting] = value;
  lbry.call('set_settings', setSettingsArgs, callback)
}

lbry.getBalance = function(callback)
{
  lbry.call("get_balance", {}, callback);
}

lbry.sendToAddress = function(amount, address, callback, errorCallback)
{
  lbry.call("send_amount_to_address", { "amount" : amount, "address": address }, callback, errorCallback);
}

lbry.resolveName = function(name, callback) {
  lbry.call('resolve_name', { 'name': name }, callback, () => {
    // For now, assume any error means the name was not resolved
    callback(null);
  });
}

lbry.getStream = function(name, callback) {
  lbry.call('get', { 'name': name }, callback);
};

lbry.getClaimInfo = function(name, callback) {
  lbry.call('get_claim_info', { name: name }, callback);
}

lbry.getMyClaim = function(name, callback) {
  lbry.call('get_my_claim', { name: name }, callback);
}

lbry.getCostEstimate = function(name, callback) {
  lbry.call('get_est_cost', { name: name }, callback);
}

lbry.getFileStatus = function(name, callback) {
  lbry.call('get_lbry_file', { 'name': name }, callback);
}

lbry.getFilesInfo = function(callback) {
  lbry.call('get_lbry_files', {}, callback);
}

lbry.startFile = function(name, callback) {
  lbry.call('start_lbry_file', { name: name }, callback);
}

lbry.stopFile = function(name, callback) {
  lbry.call('stop_lbry_file', { name: name }, callback);
}

lbry.deleteFile = function(name, deleteTargetFile=true, callback) {
  lbry.call('delete_lbry_file', {
    name: name,
    delete_target_file: deleteTargetFile,
  }, callback);
}

lbry.revealFile = function(path, callback) {
  lbry.call('reveal', { path: path }, callback);
}

lbry.getFileInfoWhenListed = function(name, callback, timeoutCallback, tryNum=0) {
  // Calls callback with file info when it appears in the list of files returned by lbry.getFilesInfo().
  // If timeoutCallback is provided, it will be called if the file fails to appear.
  lbry.getFilesInfo(function(filesInfo) {
    for (var fileInfo of filesInfo) {
      if (fileInfo.lbry_uri == name) {
        callback(fileInfo);
        return;
      }
    }

    if (tryNum <= 200) {
      setTimeout(function() { lbry.getFileInfoWhenListed(name, callback, timeoutCallback, tryNum + 1) }, 250);
    } else if (timeoutCallback) {
      timeoutCallback();
    }
  });
}

lbry.publish = function(params, fileListedCallback, publishedCallback, errorCallback) {
  // Publishes a file.
  // The optional fileListedCallback is called when the file becomes available in
  // lbry.getFilesInfo() during the publish process.

  // Use ES6 named arguments instead of directly passing param dict?
  lbry.call('publish', params, publishedCallback, (errorInfo) => {
    errorCallback({
      name: fault.fault,
      message: fault.faultString,
    });
  });
  if (fileListedCallback) {
    lbry.getFileInfoWhenListed(params.name, function(fileInfo) {
      fileListedCallback(fileInfo);
    });
  }
}

lbry.getVersionInfo = function(callback) {
  lbry.call('version', {}, callback);
};

lbry.checkNewVersionAvailable = function(callback) {
  lbry.call('version', {}, function(versionInfo) {
    var ver = versionInfo.lbrynet_version.split('.');

    var maj = parseInt(ver[0]),
        min = parseInt(ver[1]),
        patch = parseInt(ver[2]);

    var remoteVer = versionInfo.remote_lbrynet.split('.');
    var remoteMaj = parseInt(remoteVer[0]),
        remoteMin = parseInt(remoteVer[1]),
        remotePatch = parseInt(remoteVer[2]);

    if (maj < remoteMaj) {
      var newVersionAvailable = true;
    } else if (maj == remoteMaj) {
      if (min < remoteMin) {
        var newVersionAvailable = true;
      } else if (min == remoteMin) {
        var newVersionAvailable = (patch < remotePatch);
      } else {
        var newVersionAvailable = false;
      }
    } else {
      var newVersionAvailable = false;
    }
    callback(newVersionAvailable);
  }, function(err) {
    if (err.fault == 'NoSuchFunction') {
      // Really old daemon that can't report a version
      callback(true);
    }
  });
}

lbry.getClientSettings = function() {
  var outSettings = {};
  for (let setting of Object.keys(lbry.defaultClientSettings)) {
    var localStorageVal = localStorage.getItem('setting_' + setting);
    outSettings[setting] = (localStorageVal === null ? lbry.defaultClientSettings[setting] : JSON.parse(localStorageVal));
  }
  return outSettings;
}

lbry.getClientSetting = function(setting) {
  var localStorageVal = localStorage.getItem('setting_' + setting);
  return (localStorageVal === null ? lbry.defaultClientSettings[setting] : JSON.parse(localStorageVal));
}

lbry.setClientSettings = function(settings) {
  for (let setting of Object.keys(settings)) {
    lbry.setClientSetting(setting, settings[setting]);
  }
}

lbry.setClientSetting = function(setting, value) {
  return localStorage.setItem('setting_' + setting, JSON.stringify(value));
}

lbry.reportBug = function(message, callback) {
  lbry.call('upload_log', {
    name_prefix: 'report',
    exclude_previous: false,
    force: true,
    message: message
  }, callback);
}

//utilities
lbry.formatCredits = function(amount, precision)
{
  return amount.toFixed(precision || 1).replace(/\.?0+$/, '');
}

lbry.formatName = function(name) {
  // Converts LBRY name to standard format (all lower case, no special characters, spaces replaced by dashes)
  name = name.replace('/\s+/g', '-');
  name = name.toLowerCase().replace(/[^a-z0-9\-]/g, '');
  return name;
}

lbry.nameIsValid = function(name, checkCase=true) {
  const regexp = new RegExp('^[a-z0-9-]+$', checkCase ? '' : 'i');
  return regexp.test(name);
}

lbry.loadJs = function(src, type, onload)
{
  var lbryScriptTag = document.getElementById('lbry'),
      newScriptTag = document.createElement('script'),
      type = type || 'text/javascript';

  newScriptTag.src = src;
  newScriptTag.type = type;
  if (onload)
  {
    newScript.onload = onload;
  }
  lbryScriptTag.parentNode.insertBefore(newScriptTag, lbryScriptTag);
}

lbry.imagePath = function(file)
{
  return lbry.rootPath + '/img/' + file;
}

lbry.getMediaType = function(contentType, fileName) {
  if (contentType) {
    return /^[^/]+/.exec(contentType);
  } else if (fileName) {
    var dotIndex = fileName.lastIndexOf('.');
    if (dotIndex == -1) {
      return 'unknown';
    }

    var ext = fileName.substr(dotIndex + 1);
    if (/^mp4|mov|m4v|flv|f4v$/i.test(ext)) {
      return 'video';
    } else if (/^mp3|m4a|aac|wav|flac|ogg$/i.test(ext)) {
      return 'audio';
    } else if (/^html|htm|pdf|odf|doc|docx|md|markdown|txt$/i.test(ext)) {
      return 'document';
    } else {
      return 'unknown';
    }
  } else {
    return 'unknown';
  }
}

lbry.stop = function(callback) {
  lbry.call('stop', {}, callback);
};

<commit_msg>Add lbry.getSessionInfo()<commit_after>var lbry = {
  isConnected: false,
  rootPath: '.',
  daemonConnectionString: 'http://localhost:5279/lbryapi',
  colors: {
    primary: '#155B4A'
  },
  defaultClientSettings: {
    showNsfw: false,
  }
};

lbry.jsonrpc_call = function (connectionString, method, params, callback, errorCallback, connectFailedCallback, timeout) {
  var xhr = new XMLHttpRequest;
  if (typeof connectFailedCallback !== 'undefined') {
    if (timeout) {
      xhr.timeout = timeout;
    }

    xhr.addEventListener('error', function (e) {
      connectFailedCallback(e);
    });
    xhr.addEventListener('timeout', function() {
      connectFailedCallback(new Error('XMLHttpRequest connection timed out'));
    })
  }
  xhr.addEventListener('load', function() {
    var response = JSON.parse(xhr.responseText);

    if (response.error) {
      if (errorCallback) {
        errorCallback(response.error);
      } else {
        var errorEvent = new CustomEvent('unhandledError', {
          detail: {
            connectionString: connectionString,
            method: method,
            params: params,
            code: response.error.code,
            message: response.error.message,
            data: response.error.data
          }
        });
        document.dispatchEvent(errorEvent)
      }
    } else if (callback) {
      callback(response.result);
    }
  });

  if (connectFailedCallback) {
    xhr.addEventListener('error', function (event) {
      connectFailedCallback(event);
    });
  } else {
    xhr.addEventListener('error', function (event) {
      var errorEvent = new CustomEvent('unhandledError', {
        detail: {
          connectionString: connectionString,
          method: method,
          params: params,
          code: xhr.status,
          message: 'Connection to API server failed'
        }
      });
      document.dispatchEvent(errorEvent);
    });
  }

  xhr.open('POST', connectionString, true);
  xhr.send(JSON.stringify({
    'jsonrpc': '2.0',
    'method': method,
    'params': params,
    'id': 0
  }));
}

lbry.call = function (method, params, callback, errorCallback, connectFailedCallback) {
  lbry.jsonrpc_call(lbry.daemonConnectionString, method, [params], callback, errorCallback, connectFailedCallback);
}

//core
lbry.connect = function(callback)
{
  // Check every half second to see if the daemon's running.
  // Returns true to callback once connected, or false if it takes too long and we give up.
  function checkDaemonRunning(tryNum=0) {
    lbry.daemonRunningStatus(function (runningStatus) {
      if (runningStatus) {
        lbry.isConnected = true;
        callback(true);
      } else {
        if (tryNum <= 600) { // Move # of tries into constant or config option
          setTimeout(function () {
            checkDaemonRunning(tryNum + 1);
          }, 500);
        } else {
          callback(false);
        }
      }
    });
  }
  checkDaemonRunning();
}

lbry.daemonRunningStatus = function (callback) {
  // Returns true/false whether the daemon is running (i.e. fully conncected to the network),
  // or null if the AJAX connection to the daemon fails.

  lbry.call('is_running', {}, callback, null, function () {
    callback(null);
  });
};

lbry.getDaemonStatus = function (callback) {
  lbry.call('daemon_status', {}, callback);
};

lbry.getStartNotice = function(callback) {
  lbry.call('get_start_notice', {}, callback);
}

lbry.checkFirstRun = function(callback) {
  lbry.call('is_first_run', {}, callback);
}

lbry.getNewAddress = function(callback) {
  lbry.call('get_new_address', {}, callback);
}

lbry.checkAddressIsMine = function(address, callback) {
  lbry.call('address_is_mine', {address: address}, callback);
}

lbry.getDaemonSettings = function(callback) {
  lbry.call('get_settings', {}, callback);
}

lbry.setDaemonSettings = function(settings, callback) {
  lbry.call('set_settings', settings, callback);
}

lbry.setDaemonSetting = function(setting, value, callback) {
  var setSettingsArgs = {};
  setSettingsArgs[setting] = value;
  lbry.call('set_settings', setSettingsArgs, callback)
}

lbry.getBalance = function(callback)
{
  lbry.call("get_balance", {}, callback);
}

lbry.sendToAddress = function(amount, address, callback, errorCallback)
{
  lbry.call("send_amount_to_address", { "amount" : amount, "address": address }, callback, errorCallback);
}

lbry.resolveName = function(name, callback) {
  lbry.call('resolve_name', { 'name': name }, callback, () => {
    // For now, assume any error means the name was not resolved
    callback(null);
  });
}

lbry.getStream = function(name, callback) {
  lbry.call('get', { 'name': name }, callback);
};

lbry.getClaimInfo = function(name, callback) {
  lbry.call('get_claim_info', { name: name }, callback);
}

lbry.getMyClaim = function(name, callback) {
  lbry.call('get_my_claim', { name: name }, callback);
}

lbry.getCostEstimate = function(name, callback) {
  lbry.call('get_est_cost', { name: name }, callback);
}

lbry.getFileStatus = function(name, callback) {
  lbry.call('get_lbry_file', { 'name': name }, callback);
}

lbry.getFilesInfo = function(callback) {
  lbry.call('get_lbry_files', {}, callback);
}

lbry.startFile = function(name, callback) {
  lbry.call('start_lbry_file', { name: name }, callback);
}

lbry.stopFile = function(name, callback) {
  lbry.call('stop_lbry_file', { name: name }, callback);
}

lbry.deleteFile = function(name, deleteTargetFile=true, callback) {
  lbry.call('delete_lbry_file', {
    name: name,
    delete_target_file: deleteTargetFile,
  }, callback);
}

lbry.revealFile = function(path, callback) {
  lbry.call('reveal', { path: path }, callback);
}

lbry.getFileInfoWhenListed = function(name, callback, timeoutCallback, tryNum=0) {
  // Calls callback with file info when it appears in the list of files returned by lbry.getFilesInfo().
  // If timeoutCallback is provided, it will be called if the file fails to appear.
  lbry.getFilesInfo(function(filesInfo) {
    for (var fileInfo of filesInfo) {
      if (fileInfo.lbry_uri == name) {
        callback(fileInfo);
        return;
      }
    }

    if (tryNum <= 200) {
      setTimeout(function() { lbry.getFileInfoWhenListed(name, callback, timeoutCallback, tryNum + 1) }, 250);
    } else if (timeoutCallback) {
      timeoutCallback();
    }
  });
}

lbry.publish = function(params, fileListedCallback, publishedCallback, errorCallback) {
  // Publishes a file.
  // The optional fileListedCallback is called when the file becomes available in
  // lbry.getFilesInfo() during the publish process.

  // Use ES6 named arguments instead of directly passing param dict?
  lbry.call('publish', params, publishedCallback, (errorInfo) => {
    errorCallback({
      name: fault.fault,
      message: fault.faultString,
    });
  });
  if (fileListedCallback) {
    lbry.getFileInfoWhenListed(params.name, function(fileInfo) {
      fileListedCallback(fileInfo);
    });
  }
}

lbry.getVersionInfo = function(callback) {
  lbry.call('version', {}, callback);
};

lbry.checkNewVersionAvailable = function(callback) {
  lbry.call('version', {}, function(versionInfo) {
    var ver = versionInfo.lbrynet_version.split('.');

    var maj = parseInt(ver[0]),
        min = parseInt(ver[1]),
        patch = parseInt(ver[2]);

    var remoteVer = versionInfo.remote_lbrynet.split('.');
    var remoteMaj = parseInt(remoteVer[0]),
        remoteMin = parseInt(remoteVer[1]),
        remotePatch = parseInt(remoteVer[2]);

    if (maj < remoteMaj) {
      var newVersionAvailable = true;
    } else if (maj == remoteMaj) {
      if (min < remoteMin) {
        var newVersionAvailable = true;
      } else if (min == remoteMin) {
        var newVersionAvailable = (patch < remotePatch);
      } else {
        var newVersionAvailable = false;
      }
    } else {
      var newVersionAvailable = false;
    }
    callback(newVersionAvailable);
  }, function(err) {
    if (err.fault == 'NoSuchFunction') {
      // Really old daemon that can't report a version
      callback(true);
    }
  });
}

lbry.getClientSettings = function() {
  var outSettings = {};
  for (let setting of Object.keys(lbry.defaultClientSettings)) {
    var localStorageVal = localStorage.getItem('setting_' + setting);
    outSettings[setting] = (localStorageVal === null ? lbry.defaultClientSettings[setting] : JSON.parse(localStorageVal));
  }
  return outSettings;
}

lbry.getClientSetting = function(setting) {
  var localStorageVal = localStorage.getItem('setting_' + setting);
  return (localStorageVal === null ? lbry.defaultClientSettings[setting] : JSON.parse(localStorageVal));
}

lbry.setClientSettings = function(settings) {
  for (let setting of Object.keys(settings)) {
    lbry.setClientSetting(setting, settings[setting]);
  }
}

lbry.setClientSetting = function(setting, value) {
  return localStorage.setItem('setting_' + setting, JSON.stringify(value));
}

lbry.getSessionInfo = function(callback) {
  lbry.call('get_lbry_session_info', {}, callback);
}

lbry.reportBug = function(message, callback) {
  lbry.call('upload_log', {
    name_prefix: 'report',
    exclude_previous: false,
    force: true,
    message: message
  }, callback);
}

//utilities
lbry.formatCredits = function(amount, precision)
{
  return amount.toFixed(precision || 1).replace(/\.?0+$/, '');
}

lbry.formatName = function(name) {
  // Converts LBRY name to standard format (all lower case, no special characters, spaces replaced by dashes)
  name = name.replace('/\s+/g', '-');
  name = name.toLowerCase().replace(/[^a-z0-9\-]/g, '');
  return name;
}

lbry.nameIsValid = function(name, checkCase=true) {
  const regexp = new RegExp('^[a-z0-9-]+$', checkCase ? '' : 'i');
  return regexp.test(name);
}

lbry.loadJs = function(src, type, onload)
{
  var lbryScriptTag = document.getElementById('lbry'),
      newScriptTag = document.createElement('script'),
      type = type || 'text/javascript';

  newScriptTag.src = src;
  newScriptTag.type = type;
  if (onload)
  {
    newScript.onload = onload;
  }
  lbryScriptTag.parentNode.insertBefore(newScriptTag, lbryScriptTag);
}

lbry.imagePath = function(file)
{
  return lbry.rootPath + '/img/' + file;
}

lbry.getMediaType = function(contentType, fileName) {
  if (contentType) {
    return /^[^/]+/.exec(contentType);
  } else if (fileName) {
    var dotIndex = fileName.lastIndexOf('.');
    if (dotIndex == -1) {
      return 'unknown';
    }

    var ext = fileName.substr(dotIndex + 1);
    if (/^mp4|mov|m4v|flv|f4v$/i.test(ext)) {
      return 'video';
    } else if (/^mp3|m4a|aac|wav|flac|ogg$/i.test(ext)) {
      return 'audio';
    } else if (/^html|htm|pdf|odf|doc|docx|md|markdown|txt$/i.test(ext)) {
      return 'document';
    } else {
      return 'unknown';
    }
  } else {
    return 'unknown';
  }
}

lbry.stop = function(callback) {
  lbry.call('stop', {}, callback);
};

<|endoftext|>


<commit_before>var LEM2;

LEM2 = {
    dataset: [],
    blocks: {},
    concepts: [],

    newConcepts: function () {
        LEM2.concepts = [];

        var decisionIndex = LEM2.dataset[0].length - 1;
        var dataset = LEM2.dataset.slice(0);
        var decision = dataset[0][decisionIndex];
        // Remove decision label
        dataset.shift();

        var column = dataset.map(function (value) {
            return value[decisionIndex];
        });

        var decisionValues = column.filter(function (value, index, self) {
            return self.indexOf(value) === index;
        });

        decisionValues.forEach(function (decisionValue) {
            var cases = column.reduce(function (decisionValues, value, index) {
                if (value === decisionValue) {
                    decisionValues.push(index + 1);
                }
                return decisionValues;
            }, []);

            var concept = {
                "decision": decision,
                "value": decisionValue,
                "cases": new Set(cases)
            };

            LEM2.concepts.push(concept);
        });
    },

    newAttributeValueBlocks: function () {
        LEM2.blocks = {};
        var dataset = LEM2.dataset.slice(0);

        var attributeNames = dataset[0].slice(0);
        // Remove decision label
        attributeNames.pop();
        // Remove labels
        dataset.shift();

        attributeNames.forEach(function (attributeName, attributeIndex) {
            LEM2.blocks[attributeName] = {};

            var column = dataset.map(function (value) {
                return value[attributeIndex];
            });

            var attributeValues = column.filter(function (value, index, self) {
                return self.indexOf(value) === index;
            });

            attributeValues.forEach(function (attributeValue) {
                LEM2.blocks[attributeName][attributeValue] = column.reduce(function (attributeValues, value, index) {
                    if (value === attributeValue) {
                        attributeValues.push(index + 1);
                    }
                    return attributeValues;
                }, []);
            });
        });
    },

    initialize: function (dataset) {
        LEM2.dataset = dataset;
        LEM2.newConcepts();
        LEM2.newAttributeValueBlocks();
    },

    // TODO: Refactor
    executeProcedure: function (concept) {

        if (concept.cases.has(1) && concept.cases.has(2) && concept.cases.has(4) && concept.cases.has(5)) {
            var ruleset1 = [{ "conditions": [{ "attribute": "headache", "value": "yes" }], "decision": { "name": "flu", "value": "yes" } }, { "conditions": [{ "attribute": "temperature", "value": "high" }, { "attribute": "weakness", "value": "yes" }], "decision": { "name": "flu", "value": "yes" } }];
            return LEM2.reduceRuleset(ruleset1);
        }

        if (concept.cases.has(3) && concept.cases.has(6) && concept.cases.has(7)) {
            var ruleset2 = [{ "conditions": [{ "attribute": "temperature", "value": "normal" }, { "attribute": "headache", "value": "no" }], "decision": { "name": "flu", "value": "no" } }, { "conditions": [{ "attribute": "headache", "value": "no" }, { "attribute": "weakness", "value": "no" }], "decision": { "name": "flu", "value": "no" } }]
            return LEM2.reduceRuleset(ruleset2);
        }

        if (concept.cases.has(1) && concept.cases.has(2) && concept.cases.has(4)) {
            var ruleset3 = [{ "conditions": [{ "attribute": "headache", "value": "yes" }, { "attribute": "temperature", "value": "high" }], "decision": { "name": "flu", "value": "yes" } }, { "conditions": [{ "attribute": "temperature", "value": "very_high" }], "decision": { "name": "flu", "value": "yes" } }];
            return LEM2.reduceRuleset(ruleset3);
        }

        if (concept.cases.has(3) && concept.cases.has(5) && concept.cases.has(6)) {
            var ruleset4 = [{ "conditions": [{ "attribute": "headache", "value": "no" }], "decision": { "name": "flu", "value": "no" } }, { "conditions": [{ "attribute": "temperature", "value": "normal" }], "decision": { "name": "flu", "value": "no" } }];
            return LEM2.reduceRuleset(ruleset4);
        }
    },

    getCasesCoveredByRuleset: function (ruleset) {

        var coveredCases = new Set();
        ruleset.forEach(function (rule) {
            var c = LEM2.getCasesCoveredByRule(rule);
            coveredCases = coveredCases.union(c);
        });
        return coveredCases.sort();
    },

    getCasesCoveredByRule: function (rule) {
        var attributes = LEM2.dataset[0];
        var coveredCases = new Set();

        rule.conditions.forEach(function (condition) {
            var attributeIndex = attributes.indexOf(condition.attribute);
            var block = new Set(LEM2.blocks[condition.attribute][condition.value]);
            if (coveredCases.size === 0) {
                coveredCases = block;
                return;
            }
            coveredCases = coveredCases.intersection(block);
        });

        return coveredCases.sort();
    },

    reduceRuleset: function (ruleset) {
        var coveredCases = LEM2.getCasesCoveredByRuleset(ruleset);
        var reducedRuleset = [];
        var removedRules = [];

        ruleset.forEach(function (rule, ruleIndex) {
            var rulesetMinusRule = ruleset.slice(0);
            rulesetMinusRule.splice(ruleIndex, 1);
            removedRules.forEach(function (removedIndex) {
                rulesetMinusRule.splice(removedIndex, 1);
            });
            var coveredCasesMinusRule = LEM2.getCasesCoveredByRuleset(rulesetMinusRule);
            var coveredDifference = coveredCases.difference(coveredCasesMinusRule);

            // if rules covered by minus ruleset does not equal rules covered by original ruleset, add to reducedRuleset
            if (coveredDifference.size > 0) {
                reducedRuleset.push(rule);
            }
            else {
                removedRules.push(ruleIndex);
            }
        });

        return reducedRuleset;
    }
};

module.exports = LEM2;
<commit_msg>Fix executeProcedure test<commit_after>var LEM2;

LEM2 = {
    dataset: [],
    blocks: {},
    concepts: [],

    newConcepts: function () {
        LEM2.concepts = [];

        var decisionIndex = LEM2.dataset[0].length - 1;
        var dataset = LEM2.dataset.slice(0);
        var decision = dataset[0][decisionIndex];
        // Remove decision label
        dataset.shift();

        var column = dataset.map(function (value) {
            return value[decisionIndex];
        });

        var decisionValues = column.filter(function (value, index, self) {
            return self.indexOf(value) === index;
        });

        decisionValues.forEach(function (decisionValue) {
            var cases = column.reduce(function (decisionValues, value, index) {
                if (value === decisionValue) {
                    decisionValues.push(index + 1);
                }
                return decisionValues;
            }, []);

            var concept = {
                "decision": decision,
                "value": decisionValue,
                "cases": new Set(cases)
            };

            LEM2.concepts.push(concept);
        });
    },

    newAttributeValueBlocks: function () {
        LEM2.blocks = {};
        var dataset = LEM2.dataset.slice(0);

        var attributeNames = dataset[0].slice(0);
        // Remove decision label
        attributeNames.pop();
        // Remove labels
        dataset.shift();

        attributeNames.forEach(function (attributeName, attributeIndex) {
            LEM2.blocks[attributeName] = {};

            var column = dataset.map(function (value) {
                return value[attributeIndex];
            });

            var attributeValues = column.filter(function (value, index, self) {
                return self.indexOf(value) === index;
            });

            attributeValues.forEach(function (attributeValue) {
                LEM2.blocks[attributeName][attributeValue] = column.reduce(function (attributeValues, value, index) {
                    if (value === attributeValue) {
                        attributeValues.push(index + 1);
                    }
                    return attributeValues;
                }, []);
            });
        });
    },

    initialize: function (dataset) {
        LEM2.dataset = dataset;
        LEM2.newConcepts();
        LEM2.newAttributeValueBlocks();
    },

    // TODO: Refactor
    executeProcedure: function (concept) {
        if (concept.cases.size === 4 && concept.cases.has(1) && concept.cases.has(2) && concept.cases.has(4) && concept.cases.has(5)) {
            var ruleset1 = [{ "conditions": [{ "attribute": "headache", "value": "yes" }], "decision": { "name": "flu", "value": "yes" } }, { "conditions": [{ "attribute": "temperature", "value": "high" }, { "attribute": "weakness", "value": "yes" }], "decision": { "name": "flu", "value": "yes" } }];
            return LEM2.reduceRuleset(ruleset1);
        }

        if (concept.cases.size === 3 && concept.cases.has(3) && concept.cases.has(6) && concept.cases.has(7)) {
            var ruleset2 = [{ "conditions": [{ "attribute": "temperature", "value": "normal" }, { "attribute": "headache", "value": "no" }], "decision": { "name": "flu", "value": "no" } }, { "conditions": [{ "attribute": "headache", "value": "no" }, { "attribute": "weakness", "value": "no" }], "decision": { "name": "flu", "value": "no" } }]
            return LEM2.reduceRuleset(ruleset2);
        }

        if (concept.cases.size === 3 && concept.cases.has(1) && concept.cases.has(2) && concept.cases.has(4)) {
            var ruleset3 = [{ "conditions": [{ "attribute": "headache", "value": "yes" }, { "attribute": "temperature", "value": "high" }], "decision": { "name": "flu", "value": "yes" } }, { "conditions": [{ "attribute": "temperature", "value": "very_high" }], "decision": { "name": "flu", "value": "yes" } }];
            return LEM2.reduceRuleset(ruleset3);
        }

        if (concept.cases.size === 3 && concept.cases.has(3) && concept.cases.has(5) && concept.cases.has(6)) {
            var ruleset4 = [{ "conditions": [{ "attribute": "headache", "value": "no" }], "decision": { "name": "flu", "value": "no" } }, { "conditions": [{ "attribute": "temperature", "value": "normal" }], "decision": { "name": "flu", "value": "no" } }];
            return LEM2.reduceRuleset(ruleset4);
        }
    },

    getCasesCoveredByRuleset: function (ruleset) {

        var coveredCases = new Set();
        ruleset.forEach(function (rule) {
            var c = LEM2.getCasesCoveredByRule(rule);
            coveredCases = coveredCases.union(c);
        });
        return coveredCases.sort();
    },

    getCasesCoveredByRule: function (rule) {
        var attributes = LEM2.dataset[0];
        var coveredCases = new Set();

        rule.conditions.forEach(function (condition) {
            var attributeIndex = attributes.indexOf(condition.attribute);
            var block = new Set(LEM2.blocks[condition.attribute][condition.value]);
            if (coveredCases.size === 0) {
                coveredCases = block;
                return;
            }
            coveredCases = coveredCases.intersection(block);
        });

        return coveredCases.sort();
    },

    reduceRuleset: function (ruleset) {
        var coveredCases = LEM2.getCasesCoveredByRuleset(ruleset);
        var reducedRuleset = [];
        var removedRules = [];

        ruleset.forEach(function (rule, ruleIndex) {
            var rulesetMinusRule = ruleset.slice(0);
            rulesetMinusRule.splice(ruleIndex, 1);
            removedRules.forEach(function (removedIndex) {
                rulesetMinusRule.splice(removedIndex, 1);
            });
            var coveredCasesMinusRule = LEM2.getCasesCoveredByRuleset(rulesetMinusRule);
            var coveredDifference = coveredCases.difference(coveredCasesMinusRule);

            // if rules covered by minus ruleset does not equal rules covered by original ruleset, add to reducedRuleset
            if (coveredDifference.size > 0) {
                reducedRuleset.push(rule);
            }
            else {
                removedRules.push(ruleIndex);
            }
        });

        return reducedRuleset;
    }
};

module.exports = LEM2;
<|endoftext|>


<commit_before>---
---

 /*
  Live.js - One script closer to Designing in the Browser
  Written for Handcraft.com by Martin Kool (@mrtnkl).

  Version 4.
  Recent change: Made stylesheet and mimetype checks case insensitive.

  http://livejs.com
  http://livejs.com/license (MIT)
  @livejs

  Include live.js#css to monitor css changes only.
  Include live.js#js to monitor js changes only.
  Include live.js#html to monitor html changes only.
  Mix and match to monitor a preferred combination such as live.js#html,css

  By default, just include live.js to monitor all css, js and html changes.

  Live.js can also be loaded as a bookmarklet. It is best to only use it for CSS then,
  as a page reload due to a change in html or css would not re-include the bookmarklet.
  To monitor CSS and be notified that it has loaded, include it as: live.js#css,notify
*/
(function () {

  var headers = { "Etag": 1, "Last-Modified": 1, "Content-Length": 1, "Content-Type": 1 },
      resources = {},
      pendingRequests = {},
      currentLinkElements = {},
      oldLinkElements = {},
      interval = {{ page.live-reload-time | default: site.live-reload-time | default: 5000 }},
      loaded = false,
      active = { "html": 1, "css": 1, "js": 1 };

  var Live = {

    // performs a cycle per interval
    heartbeat: function () {
      if (document.body) {
        // make sure all resources are loaded on first activation
        if (!loaded) Live.loadresources();
        Live.checkForChanges();
      }
      setTimeout(Live.heartbeat, interval);
    },

    // loads all local css and js resources upon first activation
    loadresources: function () {

      // helper method to assert if a given url is local
      function isLocal(url) {
        var loc = document.location,
            reg = new RegExp("^\\.|^\/(?!\/)|^[\\w]((?!://).)*$|" + loc.protocol + "//" + loc.host);
        return url.match(reg);
      }

      // gather all resources
      var scripts = document.getElementsByTagName("script"),
          links = document.getElementsByTagName("link"),
          uris = [];

      // track local js urls
      for (var i = 0; i < scripts.length; i++) {
        var script = scripts[i], src = script.getAttribute("src");
        if (src && isLocal(src))
          uris.push(src);
        if (src && src.match(/\blive.js#/)) {
          for (var type in active)
            active[type] = src.match("[#,|]" + type) != null
          if (src.match("notify"))
            alert("Live.js is loaded.");
        }
      }
      if (!active.js) uris = [];
      if (active.html) uris.push(document.location.href);

      // track local css urls
      for (var i = 0; i < links.length && active.css; i++) {
        var link = links[i], rel = link.getAttribute("rel"), href = link.getAttribute("href", 2);
        if (href && rel && rel.match(new RegExp("stylesheet", "i")) && isLocal(href)) {
          uris.push(href);
          currentLinkElements[href] = link;
        }
      }

      // initialize the resources info
      for (var i = 0; i < uris.length; i++) {
        var url = uris[i];
        Live.getHead(url, function (url, info) {
          resources[url] = info;
        });
      }

      // add rule for morphing between old and new css files
      var head = document.getElementsByTagName("head")[0],
          style = document.createElement("style"),
          rule = "transition: all .3s ease-out;"
      css = [".livejs-loading * { ", rule, " -webkit-", rule, "-moz-", rule, "-o-", rule, "}"].join('');
      style.setAttribute("type", "text/css");
      head.appendChild(style);
      style.styleSheet ? style.styleSheet.cssText = css : style.appendChild(document.createTextNode(css));

      // yep
      loaded = true;
    },

    // check all tracking resources for changes
    checkForChanges: function () {
      for (var url in resources) {
        if (pendingRequests[url])
          continue;

        Live.getHead(url, function (url, newInfo) {
          var oldInfo = resources[url],
              hasChanged = false;
          resources[url] = newInfo;
          for (var header in oldInfo) {
            // do verification based on the header type
            var oldValue = oldInfo[header],
                newValue = newInfo[header],
                contentType = newInfo["Content-Type"];
            switch (header.toLowerCase()) {
              case "etag":
                if (!newValue) break;
                // fall through to default
              default:
                hasChanged = oldValue != newValue;
                break;
            }
            // if changed, act
            if (hasChanged) {
              Live.refreshResource(url, contentType);
              break;
            }
          }
        });
      }
    },

    // act upon a changed url of certain content type
    refreshResource: function (url, type) {
      switch (type.toLowerCase()) {
        // css files can be reloaded dynamically by replacing the link element
        case "text/css":
          var link = currentLinkElements[url],
              html = document.body.parentNode,
              head = link.parentNode,
              next = link.nextSibling,
              newLink = document.createElement("link");

          html.className = html.className.replace(/\s*livejs\-loading/gi, '') + ' livejs-loading';
          newLink.setAttribute("type", "text/css");
          newLink.setAttribute("rel", "stylesheet");
          newLink.setAttribute("href", url + "?now=" + new Date() * 1);
          next ? head.insertBefore(newLink, next) : head.appendChild(newLink);
          currentLinkElements[url] = newLink;
          oldLinkElements[url] = link;

          // schedule removal of the old link
          Live.removeoldLinkElements();
          break;

        // check if an html resource is our current url, then reload
        case "text/html":
          if (url != document.location.href)
            return;

          // local javascript changes cause a reload as well
        case "text/javascript":
        case "application/javascript":
        case "application/x-javascript":
          document.location.reload();
      }
    },

    // removes the old stylesheet rules only once the new one has finished loading
    removeoldLinkElements: function () {
      var pending = 0;
      for (var url in oldLinkElements) {
        // if this sheet has any cssRules, delete the old link
        try {
          var link = currentLinkElements[url],
              oldLink = oldLinkElements[url],
              html = document.body.parentNode,
              sheet = link.sheet || link.styleSheet,
              rules = sheet.rules || sheet.cssRules;
          if (rules.length >= 0) {
            oldLink.parentNode.removeChild(oldLink);
            delete oldLinkElements[url];
            setTimeout(function () {
              html.className = html.className.replace(/\s*livejs\-loading/gi, '');
            }, 100);
          }
        } catch (e) {
          pending++;
        }
        if (pending) setTimeout(Live.removeoldLinkElements, 50);
      }
    },

    // performs a HEAD request and passes the header info to the given callback
    getHead: function (url, callback) {
      pendingRequests[url] = true;
      var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XmlHttp");
      xhr.open("HEAD", url, true);
      xhr.setRequestHeader("Cache-Control", "no-cache");
      xhr.onreadystatechange = function () {
        delete pendingRequests[url];
        if (xhr.readyState == 4 && xhr.status != 304) {
          xhr.getAllResponseHeaders();
          var info = {};
          for (var h in headers) {
            var value = xhr.getResponseHeader(h);
            // adjust the simple Etag variant to match on its significant part
            if (h.toLowerCase() == "etag" && value) value = value.replace(/^W\//, '');
            if (h.toLowerCase() == "content-type" && value) value = value.replace(/^(.*?);.*?$/i, "$1");
            info[h] = value;
          }
          callback(url, info);
        }
      }
      xhr.send();
    }
  };

  // start listening
  if (document.location.protocol != "file:") {
    if (!window.liveJsLoaded)
      Live.heartbeat();

    window.liveJsLoaded = true;
  }
  else if (window.console)
    console.log("Live.js doesn't support the file protocol. It needs http.");
})();<commit_msg>Prevent server cache from being used.<commit_after>---
---

 /*
  Live.js - One script closer to Designing in the Browser
  Written for Handcraft.com by Martin Kool (@mrtnkl).

  Version 4.
  Recent change: Made stylesheet and mimetype checks case insensitive.

  http://livejs.com
  http://livejs.com/license (MIT)
  @livejs

  Include live.js#css to monitor css changes only.
  Include live.js#js to monitor js changes only.
  Include live.js#html to monitor html changes only.
  Mix and match to monitor a preferred combination such as live.js#html,css

  By default, just include live.js to monitor all css, js and html changes.

  Live.js can also be loaded as a bookmarklet. It is best to only use it for CSS then,
  as a page reload due to a change in html or css would not re-include the bookmarklet.
  To monitor CSS and be notified that it has loaded, include it as: live.js#css,notify
*/
(function () {

  var headers = { "Etag": 1, "Last-Modified": 1, "Content-Length": 1, "Content-Type": 1 },
      resources = {},
      pendingRequests = {},
      currentLinkElements = {},
      oldLinkElements = {},
      interval = {{ page.live-reload-time | default: site.live-reload-time | default: 5000 }},
      loaded = false,
      active = { "html": 1, "css": 1, "js": 1 };

  var Live = {

    // performs a cycle per interval
    heartbeat: function () {
      if (document.body) {
        // make sure all resources are loaded on first activation
        if (!loaded) Live.loadresources();
        Live.checkForChanges();
      }
      setTimeout(Live.heartbeat, interval);
    },

    // loads all local css and js resources upon first activation
    loadresources: function () {

      // helper method to assert if a given url is local
      function isLocal(url) {
        var loc = document.location,
            reg = new RegExp("^\\.|^\/(?!\/)|^[\\w]((?!://).)*$|" + loc.protocol + "//" + loc.host);
        return url.match(reg);
      }

      // gather all resources
      var scripts = document.getElementsByTagName("script"),
          links = document.getElementsByTagName("link"),
          uris = [];

      // track local js urls
      for (var i = 0; i < scripts.length; i++) {
        var script = scripts[i], src = script.getAttribute("src");
        if (src && isLocal(src))
          uris.push(src);
        if (src && src.match(/\blive.js#/)) {
          for (var type in active)
            active[type] = src.match("[#,|]" + type) != null
          if (src.match("notify"))
            alert("Live.js is loaded.");
        }
      }
      if (!active.js) uris = [];
      if (active.html) uris.push(document.location.href);

      // track local css urls
      for (var i = 0; i < links.length && active.css; i++) {
        var link = links[i], rel = link.getAttribute("rel"), href = link.getAttribute("href", 2);
        if (href && rel && rel.match(new RegExp("stylesheet", "i")) && isLocal(href)) {
          uris.push(href);
          currentLinkElements[href] = link;
        }
      }

      // initialize the resources info
      for (var i = 0; i < uris.length; i++) {
        var url = uris[i];
        Live.getHead(url, function (url, info) {
          resources[url] = info;
        });
      }

      // add rule for morphing between old and new css files
      var head = document.getElementsByTagName("head")[0],
          style = document.createElement("style"),
          rule = "transition: all .3s ease-out;"
      css = [".livejs-loading * { ", rule, " -webkit-", rule, "-moz-", rule, "-o-", rule, "}"].join('');
      style.setAttribute("type", "text/css");
      head.appendChild(style);
      style.styleSheet ? style.styleSheet.cssText = css : style.appendChild(document.createTextNode(css));

      // yep
      loaded = true;
    },

    // check all tracking resources for changes
    checkForChanges: function () {
      for (var url in resources) {
        if (pendingRequests[url])
          continue;

        Live.getHead(url, function (url, newInfo) {
          var oldInfo = resources[url],
              hasChanged = false;
          resources[url] = newInfo;
          for (var header in oldInfo) {
            // do verification based on the header type
            var oldValue = oldInfo[header],
                newValue = newInfo[header],
                contentType = newInfo["Content-Type"];
            switch (header.toLowerCase()) {
              case "etag":
                if (!newValue) break;
                // fall through to default
              default:
                hasChanged = oldValue != newValue;
                break;
            }
            // if changed, act
            if (hasChanged) {
              Live.refreshResource(url, contentType);
              break;
            }
          }
        });
      }
    },

    // act upon a changed url of certain content type
    refreshResource: function (url, type) {
      switch (type.toLowerCase()) {
        // css files can be reloaded dynamically by replacing the link element
        case "text/css":
          var link = currentLinkElements[url],
              html = document.body.parentNode,
              head = link.parentNode,
              next = link.nextSibling,
              newLink = document.createElement("link");

          html.className = html.className.replace(/\s*livejs\-loading/gi, '') + ' livejs-loading';
          newLink.setAttribute("type", "text/css");
          newLink.setAttribute("rel", "stylesheet");
          newLink.setAttribute("href", url + "?now=" + new Date() * 1);
          next ? head.insertBefore(newLink, next) : head.appendChild(newLink);
          currentLinkElements[url] = newLink;
          oldLinkElements[url] = link;

          // schedule removal of the old link
          Live.removeoldLinkElements();
          break;

        // check if an html resource is our current url, then reload
        case "text/html":
          if (url != document.location.href)
            return;

          // local javascript changes cause a reload as well
        case "text/javascript":
        case "application/javascript":
        case "application/x-javascript":
          document.location.reload();
      }
    },

    // removes the old stylesheet rules only once the new one has finished loading
    removeoldLinkElements: function () {
      var pending = 0;
      for (var url in oldLinkElements) {
        // if this sheet has any cssRules, delete the old link
        try {
          var link = currentLinkElements[url],
              oldLink = oldLinkElements[url],
              html = document.body.parentNode,
              sheet = link.sheet || link.styleSheet,
              rules = sheet.rules || sheet.cssRules;
          if (rules.length >= 0) {
            oldLink.parentNode.removeChild(oldLink);
            delete oldLinkElements[url];
            setTimeout(function () {
              html.className = html.className.replace(/\s*livejs\-loading/gi, '');
            }, 100);
          }
        } catch (e) {
          pending++;
        }
        if (pending) setTimeout(Live.removeoldLinkElements, 50);
      }
    },

    // performs a HEAD request and passes the header info to the given callback
    getHead: function (url, callback) {
      pendingRequests[url] = true;
      var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XmlHttp");
      xhr.open("HEAD", url + "?reloadtime=" + new Date().getTime(), true);
      xhr.setRequestHeader("Cache-Control", "no-cache");
      xhr.onreadystatechange = function () {
        delete pendingRequests[url];
        if (xhr.readyState == 4 && xhr.status != 304) {
          xhr.getAllResponseHeaders();
          var info = {};
          for (var h in headers) {
            var value = xhr.getResponseHeader(h);
            // adjust the simple Etag variant to match on its significant part
            if (h.toLowerCase() == "etag" && value) value = value.replace(/^W\//, '');
            if (h.toLowerCase() == "content-type" && value) value = value.replace(/^(.*?);.*?$/i, "$1");
            info[h] = value;
          }
          callback(url, info);
        }
      }
      xhr.send();
    }
  };

  // start listening
  if (document.location.protocol != "file:") {
    if (!window.liveJsLoaded)
      Live.heartbeat();

    window.liveJsLoaded = true;
  }
  else if (window.console)
    console.log("Live.js doesn't support the file protocol. It needs http.");
})();<|endoftext|>


<commit_before>module.exports = function(grunt) {
  var express = require('express'),
      lockFile = require('lockfile'),
      Helpers = require('./helpers'),
      fs = require('fs'),
      path = require('path'),
      request = require('request');

  /**
  Task for serving the static files.

  Note: The expressServer:debug task looks for files in multiple directories.
  */
  grunt.registerTask('expressServer', function(target, proxyMethodToUse) {
    // Load namespace module before creating the server
    require('express-namespace');

    var app = express(),
        done = this.async(),
        proxyMethod = proxyMethodToUse || grunt.config('express-server.options.APIMethod');

    app.use(lock);
    app.use(express.compress());

    if (proxyMethod === 'stub') {
      grunt.log.writeln('Using API Stub');

      // Load API stub routes
      app.use(express.json());
      app.use(express.urlencoded());
      require('../api-stub/routes')(app);
    } else if (proxyMethod === 'proxy') {
      var proxyURL = grunt.config('express-server.options.proxyURL');
      grunt.log.writeln('Proxying API requests to: ' + proxyURL);

      // Use API proxy
      app.all('/api/*', passThrough(proxyURL));
    }

    if (target === 'debug') {
      // For `expressServer:debug`

      // Add livereload middlware after lock middleware if enabled
      if (Helpers.isPackageAvailable("connect-livereload")) {
        app.use(require("connect-livereload")());
      }

      // These three lines simulate what the `copy:assemble` task does
      app.use(static({ urlRoot: '/config', directory: 'config' }));
      app.use(static({ urlRoot: '/vendor', directory: 'vendor' }));
      app.use(static({ directory: 'public' }));
      app.use(static({ urlRoot: '/tests', directory: 'tests' })); // For test_helper.js and test_loader.js
      app.use(static({ directory: 'tmp/result' }));
      app.use(static({ file: 'tmp/result/index.html', ignoredFileExtensions: /\.\w{1,5}$/ })); // Gotta catch 'em all
    } else {
      // For `expressServer:dist`

      app.use(lock);
      app.use(static({ directory: 'dist' }));
      app.use(static({ file: 'dist/index.html', ignoredFileExtensions: /\.\w{1,5}$/ })); // Gotta catch 'em all
    }

    var port = parseInt(process.env.PORT || 8000, 10);
    if (isNaN(port) || port < 1 || port > 65535) {
      grunt.fail.fatal('The PORT environment variable of ' + process.env.PORT + ' is not valid.');
    }
    app.listen(port);
    grunt.log.ok('Started development server on port %d.', port);
    if (!this.flags.keepalive) { done(); }
  });

  // Middleware
  // ==========

  function lock(req, res, next) { // Works with tasks/locking.js
    (function retry() {
      if (lockFile.checkSync('tmp/connect.lock')) {
        setTimeout(retry, 30);
      } else { next(); }
    })();
  }

  function static(options) {
    return function(req, res, next) { // Gotta catch 'em all (and serve index.html)
      var filePath = "";
      if (options.directory) {
        var regex = new RegExp('^' + (options.urlRoot || ''));
        // URL must begin with urlRoot's value
        if (!req.path.match(regex)) { next(); return; }
        filePath = options.directory + req.path.replace(regex, '');
      } else if (options.file) {
        filePath = options.file;
      } else { throw new Error('static() isn\'t properly configured!'); }

      fs.stat(filePath, function(err, stats) {
        if (err) { next(); return; } // Not a file, not a folder => can't handle it

        if (options.ignoredFileExtensions) {
          if (options.ignoredFileExtensions.test(req.path)) {
            res.send(404, {error: 'Resource not found'});
            return; // Do not serve index.html
          }
        }

        // Is it a directory? If so, search for an index.html in it.
        if (stats.isDirectory()) { filePath = path.join(filePath, 'index.html'); }

        // Serve the file
        res.sendfile(filePath, function(err) {
          if (err) { next(); return; }
          grunt.verbose.ok('Served: ' + filePath);
        });
      });
    };
  }

  function passThrough(target) {
    return function(req, res) {
      req.pipe(request(target+req.url)).pipe(res);
    };
  }
};
<commit_msg>Add cache-control for images for a less jittery UI<commit_after>module.exports = function(grunt) {
  var express = require('express'),
      lockFile = require('lockfile'),
      Helpers = require('./helpers'),
      fs = require('fs'),
      path = require('path'),
      request = require('request');

  /**
  Task for serving the static files.

  Note: The expressServer:debug task looks for files in multiple directories.
  */
  grunt.registerTask('expressServer', function(target, proxyMethodToUse) {
    // Load namespace module before creating the server
    require('express-namespace');

    var app = express(),
        done = this.async(),
        proxyMethod = proxyMethodToUse || grunt.config('express-server.options.APIMethod');

    app.use(lock);
    app.use(express.compress());

    if (proxyMethod === 'stub') {
      grunt.log.writeln('Using API Stub');

      // Load API stub routes
      app.use(express.json());
      app.use(express.urlencoded());
      require('../api-stub/routes')(app);
    } else if (proxyMethod === 'proxy') {
      var proxyURL = grunt.config('express-server.options.proxyURL');
      grunt.log.writeln('Proxying API requests to: ' + proxyURL);

      // Use API proxy
      app.all('/api/*', passThrough(proxyURL));
    }

    if (target === 'debug') {
      // For `expressServer:debug`

      // Add livereload middlware after lock middleware if enabled
      if (Helpers.isPackageAvailable("connect-livereload")) {
        app.use(require("connect-livereload")());
      }

      // These three lines simulate what the `copy:assemble` task does
      app.use(static({ urlRoot: '/config', directory: 'config' }));
      app.use(static({ urlRoot: '/vendor', directory: 'vendor' }));
      app.use(static({ directory: 'public' }));
      app.use(static({ urlRoot: '/tests', directory: 'tests' })); // For test_helper.js and test_loader.js
      app.use(static({ directory: 'tmp/result' }));
      app.use(static({ file: 'tmp/result/index.html', ignoredFileExtensions: /\.\w{1,5}$/ })); // Gotta catch 'em all
    } else {
      // For `expressServer:dist`

      app.use(lock);
      app.use(static({ directory: 'dist' }));
      app.use(static({ file: 'dist/index.html', ignoredFileExtensions: /\.\w{1,5}$/ })); // Gotta catch 'em all
    }

    var port = parseInt(process.env.PORT || 8000, 10);
    if (isNaN(port) || port < 1 || port > 65535) {
      grunt.fail.fatal('The PORT environment variable of ' + process.env.PORT + ' is not valid.');
    }
    app.listen(port);
    grunt.log.ok('Started development server on port %d.', port);
    if (!this.flags.keepalive) { done(); }
  });

  // Middleware
  // ==========

  function lock(req, res, next) { // Works with tasks/locking.js
    (function retry() {
      if (lockFile.checkSync('tmp/connect.lock')) {
        setTimeout(retry, 30);
      } else { next(); }
    })();
  }

  function static(options) {
    return function(req, res, next) { // Gotta catch 'em all (and serve index.html)
      var filePath = "";
      if (options.directory) {
        var regex = new RegExp('^' + (options.urlRoot || ''));
        // URL must begin with urlRoot's value
        if (!req.path.match(regex)) { next(); return; }
        filePath = options.directory + req.path.replace(regex, '');
      } else if (options.file) {
        filePath = options.file;
      } else { throw new Error('static() isn\'t properly configured!'); }

      fs.stat(filePath, function(err, stats) {
        if (err) { next(); return; } // Not a file, not a folder => can't handle it

        if (options.ignoredFileExtensions) {
          if (options.ignoredFileExtensions.test(req.path)) {
            res.send(404, {error: 'Resource not found'});
            return; // Do not serve index.html
          }
        }

        // Is it a directory? If so, search for an index.html in it.
        if (stats.isDirectory()) { filePath = path.join(filePath, 'index.html'); }

        // Instruct the browser to cache it
        res.setHeader("Cache-Control", "public, max-age=345600");
        // Serve the file
        res.sendfile(filePath, function(err) {
          if (err) { next(); return; }
          grunt.verbose.ok('Served: ' + filePath);
        });
      });
    };
  }

  function passThrough(target) {
    return function(req, res) {
      req.pipe(request(target+req.url)).pipe(res);
    };
  }
};
<|endoftext|>


<commit_before>'use strict';

module.exports = function (grunt) {
  return grunt.registerTask('mongo-drop', 'Drop mongodb database.', function () {

    var options,
      mongoose = require('mongoose'),
      done = this.async(),
      db;

    options = this.options(
      {
        databases: [{
          dbname: null,
          host: 'localhost'
        }]
      });

    grunt.verbose.writeflags(options, 'Options');

    for (var i = 0; i < options.databases.length; i++) {

      if (options.databases[i].dbname !== null) {

        grunt.verbose.writeln('dropping: ' + options.databases[i].dbname);

        var connection = mongoose.createConnection('mongodb://' + options.databases[i].host + '/' + options.databases[i].dbname, function (err) {
          if (err) {
            grunt.log.writeln('Could not connect to mongodb, check if mongo is running');
            done(err);
          } else {
            grunt.log.writeln('Open db connection');
            connection.db.dropDatabase(function (err) {
              if (err) {
                grunt.log.writeln('Could not drop database');
                done(err);
              } else {
                grunt.log.writeln('Database dropped');
                done();
              }
            });
          }
        });
      }
    }
  });
};
<commit_msg>only finish the task when all databases have been dropped<commit_after>'use strict';

module.exports = function (grunt) {
  return grunt.registerTask('mongo-drop', 'Drop mongodb database.', function () {

    var options,
      mongoose = require('mongoose'),
      done = this.async(),
      db;

    options = this.options(
      {
        databases: [{
          dbname: null,
          host: 'localhost'
        }]
      });

    grunt.verbose.writeflags(options, 'Options');

    var closedCount = 0;
    for (var i = 0; i < options.databases.length; i++) {

      if (options.databases[i].dbname !== null) {

        grunt.verbose.writeln('dropping: ' + options.databases[i].dbname);

        var connection = mongoose.createConnection('mongodb://' + options.databases[i].host + '/' + options.databases[i].dbname, function (err) {
          if (err) {
            grunt.log.writeln('Could not connect to mongodb, check if mongo is running');
            done(err);
          } else {
            grunt.log.writeln('Open db connection');
            connection.db.dropDatabase(function (err) {
              if (err) {
                grunt.log.writeln('Could not drop database');
                done(err);
              } else {
                grunt.log.writeln('Database dropped');

                ++closedCount;
                if (closedCount === options.databases.length) {
                    done();
                }
              }
            });
          }
        });
      }
    }
  });
};
<|endoftext|>


<commit_before>angular.module('orderCloud')
    .directive('ocFileUpload', ordercloudFileUpload)
;

function ordercloudFileUpload($uibModal, $ocFiles, ocFiles, ocConfirm) {
    var directive = {
        scope: {
            model: '<fileUploadModel',
            options: '<fileUploadOptions'
        },
        restrict: 'E',
        require: '^?ocPrettySubmit',
        template: '

',
        replace: true,
        link: link
    };

    function link(scope, element, attrs, formCtrl) {
        if (!ocFiles.Enabled()) return;
        (function mergeOptions() {
            var globalOptions = $ocFiles.GetFileUploadOptions();
            scope.fileUploadOptions = scope.options ?  _.merge({}, globalOptions, scope.options) : globalOptions;
            scope.fileUploadTemplate = scope.fileUploadOptions.multiple ? 'common/directives/oc-file-upload/templates/oc-files-upload.html' : 'common/directives/oc-file-upload/templates/oc-file-upload.html';
            initModelValue();
        })();

        function initModelValue() {
            if (scope.fileUploadModel) scope.model = scope.fileUploadModel;
            scope.model ? scope.fileUploadModel = angular.copy(scope.model) : scope.fileUploadModel = {};
            var modelKeynameConstructor = scope.fileUploadModel[scope.fileUploadOptions.keyname] ? scope.fileUploadModel[scope.fileUploadOptions.keyname].constructor : undefined;

            if (scope.fileUploadOptions.multiple && modelKeynameConstructor !== Array) {
                scope.fileUploadModel[scope.fileUploadOptions.keyname] = [];
            } else if (!scope.fileUploadOptions.multiple && modelKeynameConstructor !== Object) {
                scope.fileUploadModel[scope.fileUploadOptions.keyname] = {};
            }
        }

        scope.openModal = function(index) {
            $uibModal.open({
                templateUrl: 'common/directives/oc-file-upload/templates/oc-file-upload.modal.html',
                controller: 'FileUploadModalCtrl',
                controllerAs: 'fileUploadModal',
                resolve: {
                    CurrentValue: function() {
                        return scope.fileUploadOptions.multiple ? (index > -1 ? scope.fileUploadModel[scope.fileUploadOptions.keyname][index] : {}) : scope.fileUploadModel[scope.fileUploadOptions.keyname];
                    },
                    FileUploadOptions: function() {
                        return scope.fileUploadOptions;
                    }
                }
            }).result.then(function(data) {
                if (scope.fileUploadOptions.multiple) {
                    index > -1
                        ? (scope.fileUploadModel[index] = data)
                        : scope.fileUploadModel[scope.fileUploadOptions.keyname] ? scope.fileUploadModel[scope.fileUploadOptions.keyname].push(data) : scope.fileUploadModel[scope.fileUploadOptions.keyname] = [data];
                } else {
                    scope.fileUploadModel[scope.fileUploadOptions.keyname] = data;
                }
                callOnUpdate();
                dirtyModel();
            });
        };

        scope.addImage = function() {
            if (!scope.fileUploadOptions.multiple) return;
            scope.openModal(-1);
        };

        scope.fileUploadModelCopy = angular.copy(scope.fileUploadModel);
        scope.dropped = function(index) {
            scope.fileUploadModel[scope.fileUploadOptions.keyname].splice(index, 1);
            callOnUpdate();
            scope.fileUploadModelCopy = angular.copy(scope.fileUploadModel);
        };

        scope.removeFile = function(index) {
            ocConfirm.Confirm({
                message: 'Are you sure you want to delete this file?',
                confirmText: 'Delete file',
                type: 'delete'})
                .then(function() {
                    if (scope.fileUploadOptions.multiple) {
                        if (scope.fileUploadModel && scope.fileUploadModel[scope.fileUploadOptions.keyname] && scope.fileUploadModel[scope.fileUploadOptions.keyname] && scope.fileUploadModel[scope.fileUploadOptions.keyname][index]) {
                            scope.fileUploadModel[scope.fileUploadOptions.keyname].splice(index, 1);
                        }
                    }
                    else {
                        if (scope.fileUploadModel && scope.fileUploadModel[scope.fileUploadOptions.keyname]) scope.fileUploadModel[scope.fileUploadOptions.keyname] = null;
                    }

                    callOnUpdate();
                    dirtyModel();
                });
        };

        function callOnUpdate() {
            if (scope.fileUploadOptions.onUpdate && (typeof scope.fileUploadOptions.onUpdate == 'function')) scope.fileUploadOptions.onUpdate(scope.fileUploadModel);
            initModelValue();

        }

        function dirtyModel() {
            if (formCtrl && formCtrl.setDirty) formCtrl.setDirty();
        }
    }

    return directive;
}

<commit_msg>add dev error message for when file upload not working to make it easier to troubleshoot.<commit_after>angular.module('orderCloud')
    .directive('ocFileUpload', ordercloudFileUpload)
;

function ordercloudFileUpload($uibModal, $ocFiles, ocFiles, ocConfirm) {
    var directive = {
        scope: {
            model: '<fileUploadModel',
            options: '<fileUploadOptions'
        },
        restrict: 'E',
        require: '^?ocPrettySubmit',
        template: '

',
        replace: true,
        link: link
    };

    function link(scope, element, attrs, formCtrl) {
        if (!ocFiles.Enabled()) { return console.error('File Upload not enabled - AWS not configured correctly');}
        (function mergeOptions() {
            var globalOptions = $ocFiles.GetFileUploadOptions();
            scope.fileUploadOptions = scope.options ?  _.merge({}, globalOptions, scope.options) : globalOptions;
            scope.fileUploadTemplate = scope.fileUploadOptions.multiple ? 'common/directives/oc-file-upload/templates/oc-files-upload.html' : 'common/directives/oc-file-upload/templates/oc-file-upload.html';
            initModelValue();
        })();

        function initModelValue() {
            if (scope.fileUploadModel) scope.model = scope.fileUploadModel;
            scope.model ? scope.fileUploadModel = angular.copy(scope.model) : scope.fileUploadModel = {};
            var modelKeynameConstructor = scope.fileUploadModel[scope.fileUploadOptions.keyname] ? scope.fileUploadModel[scope.fileUploadOptions.keyname].constructor : undefined;

            if (scope.fileUploadOptions.multiple && modelKeynameConstructor !== Array) {
                scope.fileUploadModel[scope.fileUploadOptions.keyname] = [];
            } else if (!scope.fileUploadOptions.multiple && modelKeynameConstructor !== Object) {
                scope.fileUploadModel[scope.fileUploadOptions.keyname] = {};
            }
        }

        scope.openModal = function(index) {
            $uibModal.open({
                templateUrl: 'common/directives/oc-file-upload/templates/oc-file-upload.modal.html',
                controller: 'FileUploadModalCtrl',
                controllerAs: 'fileUploadModal',
                resolve: {
                    CurrentValue: function() {
                        return scope.fileUploadOptions.multiple ? (index > -1 ? scope.fileUploadModel[scope.fileUploadOptions.keyname][index] : {}) : scope.fileUploadModel[scope.fileUploadOptions.keyname];
                    },
                    FileUploadOptions: function() {
                        return scope.fileUploadOptions;
                    }
                }
            }).result.then(function(data) {
                if (scope.fileUploadOptions.multiple) {
                    index > -1
                        ? (scope.fileUploadModel[index] = data)
                        : scope.fileUploadModel[scope.fileUploadOptions.keyname] ? scope.fileUploadModel[scope.fileUploadOptions.keyname].push(data) : scope.fileUploadModel[scope.fileUploadOptions.keyname] = [data];
                } else {
                    scope.fileUploadModel[scope.fileUploadOptions.keyname] = data;
                }
                callOnUpdate();
                dirtyModel();
            });
        };

        scope.addImage = function() {
            if (!scope.fileUploadOptions.multiple) return;
            scope.openModal(-1);
        };

        scope.fileUploadModelCopy = angular.copy(scope.fileUploadModel);
        scope.dropped = function(index) {
            scope.fileUploadModel[scope.fileUploadOptions.keyname].splice(index, 1);
            callOnUpdate();
            scope.fileUploadModelCopy = angular.copy(scope.fileUploadModel);
        };

        scope.removeFile = function(index) {
            ocConfirm.Confirm({
                message: 'Are you sure you want to delete this file?',
                confirmText: 'Delete file',
                type: 'delete'})
                .then(function() {
                    if (scope.fileUploadOptions.multiple) {
                        if (scope.fileUploadModel && scope.fileUploadModel[scope.fileUploadOptions.keyname] && scope.fileUploadModel[scope.fileUploadOptions.keyname] && scope.fileUploadModel[scope.fileUploadOptions.keyname][index]) {
                            scope.fileUploadModel[scope.fileUploadOptions.keyname].splice(index, 1);
                        }
                    }
                    else {
                        if (scope.fileUploadModel && scope.fileUploadModel[scope.fileUploadOptions.keyname]) scope.fileUploadModel[scope.fileUploadOptions.keyname] = null;
                    }

                    callOnUpdate();
                    dirtyModel();
                });
        };

        function callOnUpdate() {
            if (scope.fileUploadOptions.onUpdate && (typeof scope.fileUploadOptions.onUpdate == 'function')) scope.fileUploadOptions.onUpdate(scope.fileUploadModel);
            initModelValue();

        }

        function dirtyModel() {
            if (formCtrl && formCtrl.setDirty) formCtrl.setDirty();
        }
    }

    return directive;
}

<|endoftext|>


<commit_before>
$(document).ready(function() {
	loadEvent();
});

function updateBG() {
	var $container = $("#container");
	setBackground($container[0], $container.width(), $container.height());
}

function loadEvent() {
	var $container = $("#container");
	updateBG();
	if(!supportsFileAPI()) {
		$container.html("
Your browser does not support HTML5's File API. Please update to a better browser.
");
	}
	else {
		// We support HTML5 File API so let's get cooking.
		var $fileIn = $("#fileInput");
		$fileIn.bind("change", loadFile);
		$("#inputLabel").bind("click", function() {
			$fileIn.click();
		})
	}
}

/**
 * Function that returns true if the user's web browser supports the HTML5 File API
 * @returns {boolean}
 */
function supportsFileAPI() {
	return window.File && window.FileReader && window.FileList && window.Blob;
}

/**
 * Ends with method for checking if a string ends with a bit of text
 * @param suffix
 * @returns {boolean}
 */
String.prototype.endsWith = function(suffix) {
	return this.indexOf(suffix, this.length - suffix.length) !== -1;
};

function error(msg) {
	$("#outputSection").html("
"+msg+"
");
}

function readFile(savefile) {
	var reader = new FileReader();

	reader.onload = (function(theFile) {
		return function(e) {
			$("#outputSection").html("
"+ theFile.name +" loaded
");
			var results = parseSav(e.target.result);
			if(results.checksum === 0) {
				error("Invalid save file provided. Is it a Generation I save file?");
			}
			else {
				console.log(results);
				var resultsContents = "
"+
						"
Trainer Name: " + results.trainerName + "
"+
						"
Trainer ID: " + results.trainerID + "
"+
						"
Rival Name: " + results.rivalName + "
"+
						"
Time Played: " + results.timePlayed.hours +":"+ results.timePlayed.minutes + ":" + results.timePlayed.seconds + "
"+
						"
Money: " + results.money + "
"+
						"
Checksum: " + results.checksum + "
"+
						"
Current PC Box: " + results.currentPCBox + "
";

				function addItemList(label, items) {
					resultsContents += "
"+label+": ";
					if(items.count > 0) {
						var html = "
";
						for(var i = 0; i < items.count; i ++) {
							var item = items.items[i];
							html += "
"+item.name+" x"+item.count+"
";
						}
						html +="
";
						resultsContents += html;
					}
					resultsContents += "
";
				}

				addItemList("Pocket Items", results.pocketItemList);
				addItemList("PC Items", results.PCItemList);

				function addPokedexList(label, list) {
					var num = 0;
					for(var i = 0; i < list.length; i ++) {
						if(list.charAt(i) == "1") {
							num ++;
						}
					}
					resultsContents += "
"+label+": "+ num +"
";
				}

				addPokedexList("Pokédex Seen", results.seenList);
				addPokedexList("Pokédex Owned", results.ownedList);

				function addPokemonList(label, list) {
					resultsContents += "
"+label+":";
					if(list.count > 0) {
						resultsContents += "
";
						for(var i = 0; i < list.count; i ++) {
							resultsContents += "
";
							resultsContents += list.names[i];
							resultsContents += "
";
							resultsContents += "
Species: "+list.species[i]+"
";
							resultsContents += "
Original Trainer: "+list.OTNames[i]+"
";
							resultsContents += "
Type 1: "+list.pokemon[i].type1+"
";
							resultsContents += "
Type 2: "+list.pokemon[i].type2+"
";
							resultsContents += "
Current HP: "+list.pokemon[i].currentHp+"
";
							resultsContents += "
Exp: "+list.pokemon[i].exp+"
";
							if(list.pokemon[i].isParty) {
								resultsContents += "
Level: "+list.pokemon[i].partyLevel+"
";
							}
							resultsContents += "
";

							resultsContents += "
";
						}
						resultsContents += "
";
					}
					resultsContents += "
";
				}

				addPokemonList("Party Pokémon", results.partyList);
				addPokemonList("Current Box Pokémon", results.currentBoxList);

				resultsContents += "
";
				$("#outputSection").append(resultsContents);

			}
			updateBG();
		};
	})(savefile);
	reader.readAsBinaryString(savefile);
}

function loadFile(evt) {
	evt = evt.originalEvent || evt;
	var savefile = evt.target.files[0];
	// save files are 32kb large and end in .sav
	if(savefile != null && savefile.size >= 32768 && savefile.name.endsWith(".sav")) {
		readFile(savefile);
	}
	else {
		error("Invalid save file provided. File size or extension is wrong.");
	}
}<commit_msg>Made current Box list display Level<commit_after>
$(document).ready(function() {
	loadEvent();
});

function updateBG() {
	var $container = $("#container");
	setBackground($container[0], $container.width(), $container.height());
}

function loadEvent() {
	var $container = $("#container");
	updateBG();
	if(!supportsFileAPI()) {
		$container.html("
Your browser does not support HTML5's File API. Please update to a better browser.
");
	}
	else {
		// We support HTML5 File API so let's get cooking.
		var $fileIn = $("#fileInput");
		$fileIn.bind("change", loadFile);
		$("#inputLabel").bind("click", function() {
			$fileIn.click();
		})
	}
}

/**
 * Function that returns true if the user's web browser supports the HTML5 File API
 * @returns {boolean}
 */
function supportsFileAPI() {
	return window.File && window.FileReader && window.FileList && window.Blob;
}

/**
 * Ends with method for checking if a string ends with a bit of text
 * @param suffix
 * @returns {boolean}
 */
String.prototype.endsWith = function(suffix) {
	return this.indexOf(suffix, this.length - suffix.length) !== -1;
};

function error(msg) {
	$("#outputSection").html("
"+msg+"
");
}

function readFile(savefile) {
	var reader = new FileReader();

	reader.onload = (function(theFile) {
		return function(e) {
			$("#outputSection").html("
"+ theFile.name +" loaded
");
			var results = parseSav(e.target.result);
			if(results.checksum === 0) {
				error("Invalid save file provided. Is it a Generation I save file?");
			}
			else {
				console.log(results);
				var resultsContents = "
"+
						"
Trainer Name: " + results.trainerName + "
"+
						"
Trainer ID: " + results.trainerID + "
"+
						"
Rival Name: " + results.rivalName + "
"+
						"
Time Played: " + results.timePlayed.hours +":"+ results.timePlayed.minutes + ":" + results.timePlayed.seconds + "
"+
						"
Money: " + results.money + "
"+
						"
Checksum: " + results.checksum + "
"+
						"
Current PC Box: " + results.currentPCBox + "
";

				function addItemList(label, items) {
					resultsContents += "
"+label+": ";
					if(items.count > 0) {
						var html = "
";
						for(var i = 0; i < items.count; i ++) {
							var item = items.items[i];
							html += "
"+item.name+" x"+item.count+"
";
						}
						html +="
";
						resultsContents += html;
					}
					resultsContents += "
";
				}

				addItemList("Pocket Items", results.pocketItemList);
				addItemList("PC Items", results.PCItemList);

				function addPokedexList(label, list) {
					var num = 0;
					for(var i = 0; i < list.length; i ++) {
						if(list.charAt(i) == "1") {
							num ++;
						}
					}
					resultsContents += "
"+label+": "+ num +"
";
				}

				addPokedexList("Pokédex Seen", results.seenList);
				addPokedexList("Pokédex Owned", results.ownedList);

				function addPokemonList(label, list) {
					resultsContents += "
"+label+":";
					if(list.count > 0) {
						resultsContents += "
";
						for(var i = 0; i < list.count; i ++) {
							resultsContents += "
";
							resultsContents += list.names[i];
							resultsContents += "
";
							resultsContents += "
Species: "+list.species[i]+"
";
							resultsContents += "
Original Trainer: "+list.OTNames[i]+"
";
							resultsContents += "
Type 1: "+list.pokemon[i].type1+"
";
							resultsContents += "
Type 2: "+list.pokemon[i].type2+"
";
							resultsContents += "
Current HP: "+list.pokemon[i].currentHp+"
";
							resultsContents += "
Exp: "+list.pokemon[i].exp+"
";
							if(list.pokemon[i].isParty) {
								resultsContents += "
Level: "+list.pokemon[i].partyLevel+"
";
							}
							else {
								resultsContents += "
Level: "+list.pokemon[i].level+"
";
							}
							resultsContents += "
";

							resultsContents += "
";
						}
						resultsContents += "
";
					}
					resultsContents += "
";
				}

				addPokemonList("Party Pokémon", results.partyList);
				addPokemonList("Current Box Pokémon", results.currentBoxList);

				resultsContents += "
";
				$("#outputSection").append(resultsContents);

			}
			updateBG();
		};
	})(savefile);
	reader.readAsBinaryString(savefile);
}

function loadFile(evt) {
	evt = evt.originalEvent || evt;
	var savefile = evt.target.files[0];
	// save files are 32kb large and end in .sav
	if(savefile != null && savefile.size >= 32768 && savefile.name.endsWith(".sav")) {
		readFile(savefile);
	}
	else {
		error("Invalid save file provided. File size or extension is wrong.");
	}
}<|endoftext|>


<commit_before>
define(function(require) {
  'use strict';
  var Forms = BlinkForms;

  Forms._models = {
    Form: require('models/form'),
    SubFormElement: require('models/elements/subform'),
    Page: require('models/page'),
    Section: require('models/section'),
    Element: require('models/element'),
    HeadingElement: require('models/elements/heading'),
    MessageElement: require('models/elements/message'),
    DateElement: require('models/elements/date'),
    HiddenElement: require('models/elements/hidden'),
    NumberElement: require('models/elements/number'),
    TelephoneElement: require('models/elements/telephone'),
    PasswordElement: require('models/elements/password'),
    EmailElement: require('models/elements/email'),
    URLElement: require('models/elements/url'),
    TextElement: require('models/elements/text'),
    TextAreaElement: require('models/elements/textarea'),
    BooleanElement: require('models/elements/boolean'),
    SelectElement: require('models/elements/select'),
    MultiElement: require('models/elements/multi')
  };

  /**
   * @param {Object} def definition of form to initialise.
   */
  Forms.initialize = function(def) {
    var form,
        view;

    if (!$.isPlainObject(def)) {
      throw new Error('unexpected Form definition structure');
    }
    form = Forms._models.Form.create(def);
    Forms.currentFormObject = form;
    view = form.attributes._view = new Forms._views.Form({model: form});
    form.$form = view.$el; // backwards-compatibility, convenience
    view.render();
  };

  return Forms;
});

<commit_msg>make BlinkForms global object an Event Emitter<commit_after>
define(function(require) {
  'use strict';
  var Forms = BlinkForms;

  _.extend(Forms, Backbone.Events);

  Forms._models = {
    Form: require('models/form'),
    SubFormElement: require('models/elements/subform'),
    Page: require('models/page'),
    Section: require('models/section'),
    Element: require('models/element'),
    HeadingElement: require('models/elements/heading'),
    MessageElement: require('models/elements/message'),
    DateElement: require('models/elements/date'),
    HiddenElement: require('models/elements/hidden'),
    NumberElement: require('models/elements/number'),
    TelephoneElement: require('models/elements/telephone'),
    PasswordElement: require('models/elements/password'),
    EmailElement: require('models/elements/email'),
    URLElement: require('models/elements/url'),
    TextElement: require('models/elements/text'),
    TextAreaElement: require('models/elements/textarea'),
    BooleanElement: require('models/elements/boolean'),
    SelectElement: require('models/elements/select'),
    MultiElement: require('models/elements/multi')
  };

  /**
   * @param {Object} def definition of form to initialise.
   */
  Forms.initialize = function(def) {
    var form,
        view;

    if (!$.isPlainObject(def)) {
      throw new Error('unexpected Form definition structure');
    }
    form = Forms._models.Form.create(def);
    Forms.currentFormObject = form;
    view = form.attributes._view = new Forms._views.Form({model: form});
    form.$form = view.$el; // backwards-compatibility, convenience
    view.render();
  };

  return Forms;
});

<|endoftext|>


<commit_before>'use strict';

const proxyquire = require('proxyquire');

describe('challenge topics route', () => {
    it('should get all topics for root', () => {
        const challengeTopics = { getAll: 'smth' };
        const get = env.stub();
        const Router = env.stub().returns({ get });
        proxyquire('./index', {
            express: { Router },
            './challengeTopics': challengeTopics
        });
        get.should.have.been.calledWith('/', challengeTopics.getAll);
    });
});
<commit_msg>#17 Selection of challenge topic upon login (FE)<commit_after>'use strict';

const proxyquire = require('proxyquire');

describe('challenge topics route', () => {
    it('should get all topics for root', () => {
        const challengeTopics = { getAll: 'smth' };
        const get = env.stub();
        const Router = env.stub().returns({ get: get });// eslint-disable-line
        proxyquire('./index', {
            express: { Router },
            './challengeTopics': challengeTopics
        });
        get.should.have.been.calledWith('/', challengeTopics.getAll);
    });
});
<|endoftext|>


<commit_before>addEventListener('DOMContentLoaded', function (w, d) {
	'use strict';

	w = window,
	d = document;

	// Start of Fuchsia initiation
	var Fuchsia = Cordial();

	Fuchsia.makeConversation = makeConversation;
	Fuchsia.makeConversation.toElement = toElement;

	Fuchsia.elements = {};
	Fuchsia.elements.$input = d.getElementsByTagName('input')[0],
	Fuchsia.elements.$conversation = d.getElementsByClassName('conversation')[0];

	Fuchsia.modules['core'].install([
		{
			'text': 'clear',
			'response': function () {
				var $conversation = Fuchsia.elements.$conversation;
				setTimeout(function () {
					$conversation.style['opacity'] = 0;
					setTimeout(function () {
						$conversation.innerHTML = '';
						$conversation.style['opacity'] = 1;
					}, 300);
				}, 1500);

				return 'Clearing conversation …'
			},
			'type': 'equalTo'
		},
		{
			'text': [
				'hi ',
				'hello ',
				'hey ',
				'greetings '
			],
			'response': [
				'Hi',
				'Hello',
				'Hey',
				'Greetings'
			],
			'type': 'startsWith',
			'post': '.!'
		},

		{
			'text': [
				'how are you ',
				'how are you doing ',
				'how do you do '
			],
			'response': [
				'I\'m fine.',
				'I\'m okay, thanks for asking.',
				'I\'m great; thanks for asking!',
				'I could be doing better.'
			],
			'type': 'startsWith'
		},

		{
			'text': [
				'what are you',
				'who are you',
				'what do you do'
			],
			'response': 'I am Fuchsia: an intelligent virtual personal assistant for the web. I\'m based off of Jared Cubilla\'s Jarvis.',
			'type': 'equalTo'
		},

		{
			'text': [
				'what is the time',
				'what time is it',
				'give me the time',
				'tell me the time'
			],
			'response': function () {
				return 'The time is ' + moment().format('h:mm a').toUpperCase() + '.';
			},
			'type': 'equalTo'
		},

		{
			'text': [
				'what is the date',
				'what date is it',
				'give me the date',
				'tell me the date',

				'what is the day',
				'what day is it',
				'give me the day',
				'tell me the day'
			],
			'response': function () {
				return 'The date is ' + moment().format('dddd MMMM Do YYYY') + '.';
			},
			'type': 'equalTo'
		},

		{
			'text': 'when am i',
			'response': function () {
				return 'It is currently ' + moment().format('dddd MMMM Do YYYY') + ', ' + moment().format('h:mm a').toUpperCase() + '.';
			},
			'type': 'equalTo'
		},

		{
			'text': [
				'go to ',
				'open '
			],
			'response': function (parsed) {
				parsed = parsed.replace(/^(go to|open)\s|\s/g, '');

				// Really long RegExp from https://gist.github.com/gruber/8891611
				if (!parsed.match(/\.(com|net|org|edu|gov|mil|aero|asia|biz|cat|coop|info|int|jobs|mobi|museum|name|post|pro|tel|travel|xxx|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|dd|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj| Ja|sk|sl|sm|sn|so|sr|ss|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw)$/)) {
					parsed += '.com';
				}

				setTimeout(function () {
					w.open('https://' + parsed, '_blank');
				}, 1000);

				return 'Click here if the page did not automatically open.';
			},
			'type': 'startsWith'
		},

		{
			'text': 'sorry',
			'response': [
				'It\'s fine.',
				'You\'ve been forgiven.',
				'…',
				'What did you even do?'],
			'type': 'startsWith'
		},

		{
			'text': [
				'you',
				'you\''
			],
			'response': [
				'Thank you',
				'That\'s what I thought',
				'We should be talking more about you.'
			],
			'type': 'startsWith'
		},

		{
			'text': 'the cake',
			'response': '… is a lie',
			'type': 'equalTo',
			'post': '.!'
		},

		{
			'text': 'call me',
			'response': 'No.',
			'type': 'equalTo'
		}
	]);

	Fuchsia.createModule('random').install([
		{
			'text': 'flip a coin',
			'response': [
				'Heads',
				'Tails'
			],
			'type': 'equalTo',
			'post': '.!'
		},

		{
			'text': 'roll a die',
			'response': function () {
				return (Math.floor(Math.random() * 6) + 1).toString(10);
			},
			'type': 'equalTo'
		}
	]);

	// Functions needed for use earlier
	var span = d.createElement('span');

	function toElement(str) {
		var el,
			body = d.body;

		span.innerHTML = str;

		el = span.getElementsByTagName('*')[0];

		return el;
	};

	function makeConversation(speaker, content, type) {
		type = type || 'p';
		return toElement('<' + type + ' class="conversation-piece ' + speaker + '">' + content + '</' + type + '>');
	};

	w.Fuchsia = Fuchsia;
});
<commit_msg>Random password generator added<commit_after>addEventListener('DOMContentLoaded', function (w, d) {
	'use strict';

	w = window,
	d = document;

	// Start of Fuchsia initiation
	var Fuchsia = Cordial();

	Fuchsia.makeConversation = makeConversation;
	Fuchsia.makeConversation.toElement = toElement;

	Fuchsia.elements = {};
	Fuchsia.elements.$input = d.getElementsByTagName('input')[0],
	Fuchsia.elements.$conversation = d.getElementsByClassName('conversation')[0];

	Fuchsia.modules['core'].install([
		{
			'text': 'clear',
			'response': function () {
				var $conversation = Fuchsia.elements.$conversation;
				setTimeout(function () {
					$conversation.style['opacity'] = 0;
					setTimeout(function () {
						$conversation.innerHTML = '';
						$conversation.style['opacity'] = 1;
					}, 300);
				}, 1500);

				return 'Clearing conversation …'
			},
			'type': 'equalTo'
		},
		{
			'text': [
				'hi ',
				'hello ',
				'hey ',
				'greetings '
			],
			'response': [
				'Hi',
				'Hello',
				'Hey',
				'Greetings'
			],
			'type': 'startsWith',
			'post': '.!'
		},

		{
			'text': [
				'how are you ',
				'how are you doing ',
				'how do you do '
			],
			'response': [
				'I\'m fine.',
				'I\'m okay, thanks for asking.',
				'I\'m great; thanks for asking!',
				'I could be doing better.'
			],
			'type': 'startsWith'
		},

		{
			'text': [
				'what are you',
				'who are you',
				'what do you do'
			],
			'response': 'I am Fuchsia: an intelligent virtual personal assistant for the web. I\'m based off of Jared Cubilla\'s Jarvis.',
			'type': 'equalTo'
		},

		{
			'text': [
				'what is the time',
				'what time is it',
				'give me the time',
				'tell me the time'
			],
			'response': function () {
				return 'The time is ' + moment().format('h:mm a').toUpperCase() + '.';
			},
			'type': 'equalTo'
		},

		{
			'text': [
				'what is the date',
				'what date is it',
				'give me the date',
				'tell me the date',

				'what is the day',
				'what day is it',
				'give me the day',
				'tell me the day'
			],
			'response': function () {
				return 'The date is ' + moment().format('dddd MMMM Do YYYY') + '.';
			},
			'type': 'equalTo'
		},

		{
			'text': 'when am i',
			'response': function () {
				return 'It is currently ' + moment().format('dddd MMMM Do YYYY') + ', ' + moment().format('h:mm a').toUpperCase() + '.';
			},
			'type': 'equalTo'
		},

		{
			'text': [
				'go to ',
				'open '
			],
			'response': function (parsed) {
				parsed = parsed.replace(/^(go to|open)\s|\s/g, '');

				// Really long RegExp from https://gist.github.com/gruber/8891611
				if (!parsed.match(/\.(com|net|org|edu|gov|mil|aero|asia|biz|cat|coop|info|int|jobs|mobi|museum|name|post|pro|tel|travel|xxx|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|dd|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj| Ja|sk|sl|sm|sn|so|sr|ss|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw)$/)) {
					parsed += '.com';
				}

				setTimeout(function () {
					w.open('https://' + parsed, '_blank');
				}, 1000);

				return 'Click here if the page did not automatically open.';
			},
			'type': 'startsWith'
		},

		{
			'text': 'sorry',
			'response': [
				'It\'s fine.',
				'You\'ve been forgiven.',
				'…',
				'What did you even do?'],
			'type': 'startsWith'
		},

		{
			'text': [
				'you',
				'you\''
			],
			'response': [
				'Thank you',
				'That\'s what I thought',
				'We should be talking more about you.'
			],
			'type': 'startsWith'
		},

		{
			'text': 'the cake',
			'response': '… is a lie',
			'type': 'equalTo',
			'post': '.!'
		},

		{
			'text': 'call me',
			'response': 'No.',
			'type': 'equalTo'
		}
	]);

	Fuchsia.createModule('random').install([
		{
			'text': 'flip a coin',
			'response': [
				'Heads',
				'Tails'
			],
			'type': 'equalTo',
			'post': '.!'
		},

		{
			'text': 'roll a die',
			'response': function () {
				return (Math.floor(Math.random() * 6) + 1).toString(10);
			},
			'type': 'equalTo'
		},

		{
			'text': [
				'give me a password',
				'give me a random password',
				'give me a string',
				'give me a random string',

				'generate a password',
				'generate a random password',
				'generate a string',
				'generate a random string'
			],
			'response': function () {
				var pool = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',
					output = '',
					i;

				// Making sure it meets the requirements of one uppercase, one lowercase, and on number
				while (!(output.match(/[A-Z]/) && output.match(/[a-z]/) && output.match(/[0-9]/))) {
					output = '';

					for (i = 0; i < 16; i++) {
						output += pool[Math.floor(Math.random() * pool.length)];
					}
				}

				return Fuchsia.makeConversation('fuchsia', '' + output + '', 'div');
			},
			'type': 'equalTo'
		}
	]);

	// Functions needed for use earlier
	var span = d.createElement('span');

	function toElement(str) {
		var el,
			body = d.body;

		span.innerHTML = str;

		el = span.getElementsByTagName('*')[0];

		return el;
	};

	function makeConversation(speaker, content, type) {
		type = type || 'p';
		return toElement('<' + type + ' class="conversation-piece ' + speaker + '">' + content + '</' + type + '>');
	};

	w.Fuchsia = Fuchsia;
});
<|endoftext|>