<commit_before>
/*
  This script will initialize a local Mongo database
  on your machine so you can do development work.

  IMPORTANT: You should make sure the

      local_database_name

  variable matches its value in app.js  Otherwise, you'll have
  initialized the wrong database.
*/

var mongoose = require('mongoose');
var models = require('./models');

// Connect to the Mongo database, whether locally or on Heroku
// MAKE SURE TO CHANGE THE NAME FROM 'lab7' TO ... IN OTHER PROJECTS
var local_database_name = 'UCSDRentals';
var local_database_uri  = 'mongodb://localhost/' + local_database_name
var database_uri = process.env.MONGOLAB_URI || local_database_uri
mongoose.connect(database_uri);

// Do the initialization here

// Step 1: load the JSON data

// Step 2: Remove all existing documents
var users = require('./user.json');

// Step 2: Remove all existing documents
models.User
  .find()
  .remove()
  .exec(onceClear); // callback to continue at

// Step 3: load the data from the JSON file
function onceClear(err) {
  if(err) console.log(err);

  // loop over the projects, construct and save an object from each one
  // Note that we don't care what order these saves are happening in...
  var to_save_count = users.length;
  for(var i=0; i<users.length; i++) {

    var json = users[i];
    console.log(json);
    var u = new models.User(json);

    u.save(function(err, u) {
      if(err) console.log(err);
      to_save_count--;
      console.log(to_save_count + ' left to save');
      if(to_save_count <= 0) {
        console.log('DONE');
        // The script won't terminate until the
        // connection to the database is closed
        mongoose.connection.close()
      }
    });
  }
}
<commit_msg>test to figure out heroku<commit_after>
/*
  This script will initialize a local Mongo database
  on your machine so you can do development work.

  IMPORTANT: You should make sure the

      local_database_name

  variable matches its value in app.js  Otherwise, you'll have
  initialized the wrong database.
*/

var mongoose = require('mongoose');
var models = require('./models');

// Connect to the Mongo database, whether locally or on Heroku
// MAKE SURE TO CHANGE THE NAME FROM 'lab7' TO ... IN OTHER PROJECTS
var local_database_name = 'UCSDRentals';
var local_database_uri  = 'mongodb://localhost/' + local_database_name
var database_uri = process.env.MONGOLAB_URI || local_database_uri
mongoose.connect(database_uri);

// Do the initialization here

// Step 1: load the JSON data

// Step 2: Remove all existing documents
var users = require('./user.json');
var form = require('./forms.json');

// Step 2: Remove all existing documents
models.User
  .find()
  .remove()
  .exec(onceClear); // callback to continue at

// Step 3: load the data from the JSON file
function onceClear(err) {
  if(err) console.log(err);

  // loop over the projects, construct and save an object from each one
  // Note that we don't care what order these saves are happening in...
  var to_save_count = users.length;
  for(var i=0; i<users.length; i++) {

    var json = users[i];
    console.log(json);
    var u = new models.User(json);

    u.save(function(err, u) {
      if(err) console.log(err);
      to_save_count--;
      console.log(to_save_count + ' left to save');
      if(to_save_count <= 0) {
        console.log('DONE');
        // The script won't terminate until the
        // connection to the database is closed
        mongoose.connection.close()
      }
    });
  }
}
<|endoftext|>


<commit_before>/*
* When on the webworks site, tries to figure out
* what page it is on in order to decide which script
* to inject
*
*
* note: "p" in the courses object is short for "problems", and
* "a" is short for "average" - single letters are used to reduce
* space in storage.sync (courses object has a size cap of 8kb)
*/

// because chrome.tabs.getCurrent(function(tab) can only be run from background pages, use window.location.href instead
var url = window.location.href;

// get the CLASS, ASSIGNMENT, and PROBLEM that WeBWorK is currently on
var CLASS, ASSIGNMENT, PROBLEM;
var captured = /math\.webwork\.rochester\.edu\/webwork2(\/(\w+))?(\/(\w+))?(\/(\w+))?/.exec(url);
try {   // if the main directory isn't "webwork2", then throw error (not on the WeBWorK website)
CLASS  = captured[2];
ASSIGNMENT = captured[4];
PROBLEM = captured[6];
} catch (e) {
  // fail silently - this block is here mainly because I don't want a huge chain of "if-else"s
}

var courses, preferences;

if (ASSIGNMENT !== "hardcopy" && ASSIGNMENT !== "options") {

  /*
  * load the courses object from background.js
  */
  chrome.runtime.sendMessage({greeting:"requestAll"}, function (reply) {

    // check that the message was successfully received
    var lastError = chrome.runtime.lastError;
    if (lastError) {
      console.log(lastError.message);
      return;
    }

    // initialize these objects with their values from storage
    courses = reply.courses;
    preferences = reply.preferences;

    // add the preferences to the body
    var script = document.createElement('script');
    script.textContent = "var preferences="+JSON.stringify(preferences)+";";
    (document.head||document.documentElement).appendChild(script);
    script.parentNode.removeChild(script);

    // do some error checking for new users (who won't have a defined course variable in storage)
    if (courses === null | courses === undefined)
    courses = {};

    // add the class to the courses object if it isn't already there
    if (CLASS) {
      if (courses[CLASS] === undefined) {
        courses[CLASS] = {};
      }
    }

    // change the lastclass preference to this class if they are different
    if (preferences.lastclass === undefined || (preferences.lastclass !== CLASS && CLASS !== undefined)) {
      preferences.lastclass = CLASS;

      // update background.js preferences info
      chrome.runtime.sendMessage({greeting:"updatePreferences", information:preferences}, function (reply) {
        if (lastError) {
          console.log(lastError.message);
          return;
        }
      });
    }

    // if the courses object was updated (we'll track that with this variable), save the changes
    var updateCourses = false;

    /*
    * Add all necessary elements to each input box.
    * Previously, this was done using jQuery in the
    * beginning of the problems.js file
    */
    if (PROBLEM) {

      // get all input boxes
      var inputs = document.querySelectorAll("input.codeshard");

      for (var i = 0; i < inputs.length; i++) {
        // cache id
        var id = inputs[i].getAttribute("id");
        // set minimum width to equal initial width
        inputs[i].style.minWidth = getComputedStyle(inputs[i])["width"];
        // create container for input boxes
        var container = document.createElement("div");
        container.setAttribute("class", "input-container");
        // add MathJax preview box
        container.innerHTML = '

';

        // add temporary element (future location of the input tag)
        var tempAnchor = document.createElement("a")
        container.appendChild(tempAnchor);
        // create highlight div
        var highlight = document.createElement("div")
        highlight.setAttribute("class", "highlight")
        highlight.setAttribute("id", id+"highlight");
        // set min-width
        highlight.style.minWidth = getComputedStyle(inputs[i])["width"];
        // append highlight div to container
        container.appendChild(highlight);
        // create errors div
        var errors = document.createElement("div")
        errors.setAttribute("class", "errors")
        errors.setAttribute("id", id+"errors");
        // append error div to container
        container.appendChild(errors);

        // add note container div information (ONLY IF NOTES ARE ENABLED)
        if (preferences.notes) {
            var noteID = (/([\d|_]{4,})/g).exec(id)[1]; // note ID is the numerical/underscore part of the input box ID
            noteID = noteID.replace(/^0+/, ""); // remove leading zeroes

            container.innerHTML += '

';
        }

        // add container to page
        inputs[i].parentNode.replaceChild(container, inputs[i]);
        // add input box to container
        container.replaceChild(inputs[i], container.getElementsByTagName("a")[0]);

      }

      /*
      * Get the notes for that problem from storage
      *
      * parameters correspond to problem number
      *
      * 15fallmath150 {
      *    1: "Blah blah"
      *    3: "More notes"
      *    7: "Even more notes.  Ain't life wonderful?"
      * }
      *
      */
      if (preferences.notes) {
        var noteName = CLASS+"_"+ASSIGNMENT+"_"+PROBLEM+"_notes";
        var notes;
        chrome.storage.sync.get(noteName, function(items) {
          var lastError = chrome.runtime.lastError;
          if (lastError) {
            console.log(lastError.message);
            return;
          }
          if (items[noteName] === undefined) { // no notes for that page
            notes = {};
          } else { // at least one note
            notes = items[noteName];
            console.log(noteName);
            console.log(notes);
          }

          // add event listener to note-adder
          var adders = document.getElementsByClassName("note-adder");
          for (var i = 0; i < adders.length; i++) { // iterate over them and check if there is a matching note
            // add note contents if they exist
            if (notes !== undefined) {
                // get id and see if it matches
                var xmarkID = adders[i].nextSibling.getElementsByClassName("note-xmark")[0].id;
                xmarkID = xmarkID.substring(0, xmarkID.length-8);
                console.log(xmarkID);

              if (notes[xmarkID] !== undefined) { // add note content to the corresponding div
                adders[i].nextSibling.getElementsByClassName("body")[0].innerText = notes[xmarkID];
                adders[i].parentNode.parentNode.className += " has-note"; // input and adder button yellow if it already has a note
              }
            }

            // add event listeners
            adders[i].addEventListener("click", showNote, false); // show note
            adders[i].nextSibling.getElementsByClassName("note-xmark")[0].addEventListener("click", hideNote, false); // hide note
          }

          function showNote() {
            this.nextSibling.style.display = "inline-block"; // show note
            this.style.display = "none"; // hide "note-adder"
          }

          function hideNote() {
            this.parentNode.style.display = "none"; // hide "note"

            var thisContainer = this.parentNode.parentNode.parentNode;
            var thisAdder = this.parentNode.previousSibling;
            thisAdder.style.display = "none"; // show "note-adder"

            // problem# + "hidenote"
            var problemNumber = this.id.substr(0, this.id.length-8);

            var noteText = this.parentNode.getElementsByClassName("body")[0].innerText;

            // TODO: edge case where notes[n] is null and noteText = ""
            if (notes[problemNumber] !== noteText) {
              // if note is empty, reset to undefined
              if (noteText === "") {
                delete notes[problemNumber];
                // remove coloring from corresponding container div
                thisContainer.className = thisContainer.className.replace(/(?:^|\s)has-note(?!\S)/g , '')
              } else {
                // color in
                thisContainer.className += " has-note"; // color yellow for existing notes
                // save note
                notes[problemNumber] = noteText;
              }

              // if notes is empty, delete from storage as well
              if (Object.keys(notes).length === 0) {
                chrome.storage.sync.remove([noteName], function() {
                });
              } else { // save to storage
                chrome.storage.sync.set({[noteName]: notes}, function() {
                });
              }

            }

          }

        }); // notes get

      } // preferences.notes end

    }

    if (PROBLEM && courses[CLASS][ASSIGNMENT]["a"] < 100) {

      // check the "you got x% right" at the bottom, update the corresponding problems array index if different
      var percentage = /is \d+%/.exec(document.getElementsByClassName("scoreSummary")[0].children[0].innerText);

      // problems that have not yet been attempted don't display the percentage of questions answered correctly
      if (percentage !== null) {
        percentage = parseInt(percentage[0].replace(/\D/g, ""));

        // compare to the percentage in the courses object.  Use the ABS thing because the page rounds to the whole number, not down
        if (Math.abs(courses[CLASS][ASSIGNMENT]["p"][PROBLEM-1] - percentage) > 1) {
          courses[CLASS][ASSIGNMENT]["p"][PROBLEM-1] = percentage;

          // recalculate average
          var avg = 0;
          for (var i = 0; i < courses[CLASS][ASSIGNMENT]["p"].length; i++) {
            avg += courses[CLASS][ASSIGNMENT]["p"][i];
          }
          // update average
          courses[CLASS][ASSIGNMENT]["a"] = Math.floor(avg/courses[CLASS][ASSIGNMENT]["p"].length);

          // if average = 100, then delete the problems array
          if (courses[CLASS][ASSIGNMENT]["a"] === 100) {
            delete courses[CLASS][ASSIGNMENT]["p"];
          }
          updateCourses = true;

        }
      }

    } else if (ASSIGNMENT) {
      // add the problem list to the assignment
      var tableRows = document.getElementsByClassName("problem_set_table")[0];

      // check if the element actually exists (ex. doesn't exist if the user has an expired session)
      if (tableRows !== undefined) {

        tableRows = tableRows.children[1].children;

        // check if the assignment even exists (same code as below)
        if (courses[CLASS][ASSIGNMENT] === undefined) {
          courses[CLASS][ASSIGNMENT] = {
            "p": [],  // one-indexed array where the key is the percentage completed of a problem (index is the problem name)
            "a": 0  // average of all the values inside of the problems [] array
          };
          updateCourses = true;
        }

        if (courses[CLASS][ASSIGNMENT]["a"] < 100) { // don't execute if the assignment is 100% complete

        var problem_array = [];
        var total = 0;
        // fill out the problem array with the correct values
        for (var i = 1; i < tableRows.length; i++) { // skip the first row (header)
          // get the completion percentage
          var percentage = parseInt(tableRows[i].children[4].innerText, 10);
          total += percentage;
          // update the assignment's percentage array
          problem_array.push(percentage);
        }
        // check if there are any differences between the two arrays; if there are, then update the courses object with the new array
        if (problem_array.length !== courses[CLASS][ASSIGNMENT]["p"].length) {
          courses[CLASS][ASSIGNMENT]["p"] = problem_array;
          courses[CLASS][ASSIGNMENT]["a"] = Math.floor(total / problem_array.length);
          updateCourses = true;
        } else {
          for (var i = 0; i < problem_array.length; i++) {
            if (problem_array[i] !== courses[CLASS][ASSIGNMENT]["p"][i]) {
              courses[CLASS][ASSIGNMENT]["p"] = problem_array;
              courses[CLASS][ASSIGNMENT]["a"] = Math.floor(total / problem_array.length);
              updateCourses = true;
              break;
            }
          }
        }
      }
    }

  } else if (CLASS) {

    // add the assignment list to the options
    var tableRows = document.getElementsByClassName("problem_set_table")[0];

    // check if the element actually exists (ex. doesn't exist if the user has an expired session)
    if (tableRows !== undefined) {
      tableRows = tableRows.children[1].children;

      for (var i = 1; i < tableRows.length; i++) { // skip the first row (header)
        // get the assignent name (replace spaces with underscores)
        var assignmentName = tableRows[i].children[1].innerText.replace(/ /g, "_");

        // if the assignment doesn't exist in the courses object, add it
        if (courses[CLASS][assignmentName] === undefined) {
          courses[CLASS][assignmentName] = {
            "p": [],  // one-indexed array where the key is the percentage completed of a problem (index is the problem name)
            "a": 0  // average of all the values inside of the problems [] array
          };
          updateCourses = true;
        } else {

          // only give a percentage if the course has problems in it
          // if the average is 100, then the array doesn't exist
          if (courses[CLASS][assignmentName]["a"] === 100) {
            if (courses[CLASS][assignmentName]["p"] !== undefined) {
              delete courses[CLASS][assignmentName]["p"]; // delete problems array, we already know each problem is 100% complete
              updateCourses = true;
            }
            tableRows[i].children[2].innerHTML += '100';

          } else if (courses[CLASS][assignmentName]["p"].length > 0) {
            // choose the class depending on the percentage
            var className;

            if (courses[CLASS][assignmentName]["a"] < 70) {
              className = "WWdanger";
            } else if (courses[CLASS][assignmentName]["a"] < 100) {
              className = "WWwarning";
            }
            tableRows[i].children[2].innerHTML += '' +courses[CLASS][assignmentName]["a"]+'';
          }
        }

      }
    }
  }

  // if changes were made to the "courses" object, save them to storage.sync
  if (updateCourses) {

    // send updated courses to background.js
    chrome.runtime.sendMessage({greeting:"updateCourses", information:courses}, function (reply) {
      if (lastError) {
        console.log(lastError.message);
        return;
      }
    });
  }

  /*
  * Create the script in preparation for injection
  */

  var s = document.createElement('script');
  if (PROBLEM) {
    s.src = chrome.extension.getURL('problem.js'); // for answer previews and input expanding

  } else if (ASSIGNMENT) {
    s.src = chrome.extension.getURL('assignment.js'); // for showing how much is completed

  } else if (CLASS) {
    s.src = chrome.extension.getURL('class.js'); // for showing due dates
  }
  // remove from DOM when loaded as security precaution
  s.onload = function () {
    this.parentNode.removeChild(this);
  };
  (document.head || document.documentElement).appendChild(s);

}); // end of requestAll

}
<commit_msg>removed unnecessary captures from URL string<commit_after>/*
* When on the webworks site, tries to figure out
* what page it is on in order to decide which script
* to inject
*
*
* note: "p" in the courses object is short for "problems", and
* "a" is short for "average" - single letters are used to reduce
* space in storage.sync (courses object has a size cap of 8kb)
*/

// because chrome.tabs.getCurrent(function(tab) can only be run from background pages, use window.location.href instead
var url = window.location.href;

// get the CLASS, ASSIGNMENT, and PROBLEM that WeBWorK is currently on
var CLASS, ASSIGNMENT, PROBLEM;
var captured = /math\.webwork\.rochester\.edu\/webwork2(?:\/(\w+))?(?:\/(\w+))?(?:\/(\w+))?/.exec(url);
try {   // if the main directory isn't "webwork2", then throw error (not on the WeBWorK website)
CLASS  = captured[1];
ASSIGNMENT = captured[2];
PROBLEM = captured[3];
} catch (e) {
  // fail silently - this block is here mainly because I don't want a huge chain of "if-else"s
}

var courses, preferences;

if (ASSIGNMENT !== "hardcopy" && ASSIGNMENT !== "options") {

  /*
  * load the courses object from background.js
  */
  chrome.runtime.sendMessage({greeting:"requestAll"}, function (reply) {

    // check that the message was successfully received
    var lastError = chrome.runtime.lastError;
    if (lastError) {
      console.log(lastError.message);
      return;
    }

    // initialize these objects with their values from storage
    courses = reply.courses;
    preferences = reply.preferences;

    // add the preferences to the body
    var script = document.createElement('script');
    script.textContent = "var preferences="+JSON.stringify(preferences)+";";
    (document.head||document.documentElement).appendChild(script);
    script.parentNode.removeChild(script);

    // do some error checking for new users (who won't have a defined course variable in storage)
    if (courses === null | courses === undefined)
    courses = {};

    // add the class to the courses object if it isn't already there
    if (CLASS) {
      if (courses[CLASS] === undefined) {
        courses[CLASS] = {};
      }
    }

    // change the lastclass preference to this class if they are different
    if (preferences.lastclass === undefined || (preferences.lastclass !== CLASS && CLASS !== undefined)) {
      preferences.lastclass = CLASS;

      // update background.js preferences info
      chrome.runtime.sendMessage({greeting:"updatePreferences", information:preferences}, function (reply) {
        if (lastError) {
          console.log(lastError.message);
          return;
        }
      });
    }

    // if the courses object was updated (we'll track that with this variable), save the changes
    var updateCourses = false;

    /*
    * Add all necessary elements to each input box.
    * Previously, this was done using jQuery in the
    * beginning of the problems.js file
    */
    if (PROBLEM) {

      // get all input boxes
      var inputs = document.querySelectorAll("input.codeshard");

      for (var i = 0; i < inputs.length; i++) {
        // cache id
        var id = inputs[i].getAttribute("id");
        // set minimum width to equal initial width
        inputs[i].style.minWidth = getComputedStyle(inputs[i])["width"];
        // create container for input boxes
        var container = document.createElement("div");
        container.setAttribute("class", "input-container");
        // add MathJax preview box
        container.innerHTML = '

';

        // add temporary element (future location of the input tag)
        var tempAnchor = document.createElement("a")
        container.appendChild(tempAnchor);
        // create highlight div
        var highlight = document.createElement("div")
        highlight.setAttribute("class", "highlight")
        highlight.setAttribute("id", id+"highlight");
        // set min-width
        highlight.style.minWidth = getComputedStyle(inputs[i])["width"];
        // append highlight div to container
        container.appendChild(highlight);
        // create errors div
        var errors = document.createElement("div")
        errors.setAttribute("class", "errors")
        errors.setAttribute("id", id+"errors");
        // append error div to container
        container.appendChild(errors);

        // add note container div information (ONLY IF NOTES ARE ENABLED)
        if (preferences.notes) {
            var noteID = (/([\d|_]{4,})/g).exec(id)[1]; // note ID is the numerical/underscore part of the input box ID
            noteID = noteID.replace(/^0+/, ""); // remove leading zeroes

            container.innerHTML += '

';
        }

        // add container to page
        inputs[i].parentNode.replaceChild(container, inputs[i]);
        // add input box to container
        container.replaceChild(inputs[i], container.getElementsByTagName("a")[0]);

      }

      /*
      * Get the notes for that problem from storage
      *
      * parameters correspond to problem number
      *
      * 15fallmath150 {
      *    1: "Blah blah"
      *    3: "More notes"
      *    7: "Even more notes.  Ain't life wonderful?"
      * }
      *
      */
      if (preferences.notes) {
        var noteName = CLASS+"_"+ASSIGNMENT+"_"+PROBLEM+"_notes";
        var notes;
        chrome.storage.sync.get(noteName, function(items) {
          var lastError = chrome.runtime.lastError;
          if (lastError) {
            console.log(lastError.message);
            return;
          }
          if (items[noteName] === undefined) { // no notes for that page
            notes = {};
          } else { // at least one note
            notes = items[noteName];
            console.log(noteName);
            console.log(notes);
          }

          // add event listener to note-adder
          var adders = document.getElementsByClassName("note-adder");
          for (var i = 0; i < adders.length; i++) { // iterate over them and check if there is a matching note
            // add note contents if they exist
            if (notes !== undefined) {
                // get id and see if it matches
                var xmarkID = adders[i].nextSibling.getElementsByClassName("note-xmark")[0].id;
                xmarkID = xmarkID.substring(0, xmarkID.length-8);
                console.log(xmarkID);

              if (notes[xmarkID] !== undefined) { // add note content to the corresponding div
                adders[i].nextSibling.getElementsByClassName("body")[0].innerText = notes[xmarkID];
                adders[i].parentNode.parentNode.className += " has-note"; // input and adder button yellow if it already has a note
              }
            }

            // add event listeners
            adders[i].addEventListener("click", showNote, false); // show note
            adders[i].nextSibling.getElementsByClassName("note-xmark")[0].addEventListener("click", hideNote, false); // hide note
          }

          function showNote() {
            this.nextSibling.style.display = "inline-block"; // show note
            this.style.display = "none"; // hide "note-adder"
          }

          function hideNote() {
            this.parentNode.style.display = "none"; // hide "note"

            var thisContainer = this.parentNode.parentNode.parentNode;
            var thisAdder = this.parentNode.previousSibling;
            thisAdder.style.display = "none"; // show "note-adder"

            // problem# + "hidenote"
            var problemNumber = this.id.substr(0, this.id.length-8);

            var noteText = this.parentNode.getElementsByClassName("body")[0].innerText;

            // TODO: edge case where notes[n] is null and noteText = ""
            if (notes[problemNumber] !== noteText) {
              // if note is empty, reset to undefined
              if (noteText === "") {
                delete notes[problemNumber];
                // remove coloring from corresponding container div
                thisContainer.className = thisContainer.className.replace(/(?:^|\s)has-note(?!\S)/g , '')
              } else {
                // color in
                thisContainer.className += " has-note"; // color yellow for existing notes
                // save note
                notes[problemNumber] = noteText;
              }

              // if notes is empty, delete from storage as well
              if (Object.keys(notes).length === 0) {
                chrome.storage.sync.remove([noteName], function() {
                });
              } else { // save to storage
                chrome.storage.sync.set({[noteName]: notes}, function() {
                });
              }

            }

          }

        }); // notes get

      } // preferences.notes end

    }

    if (PROBLEM && courses[CLASS][ASSIGNMENT]["a"] < 100) {

      // check the "you got x% right" at the bottom, update the corresponding problems array index if different
      var percentage = /is \d+%/.exec(document.getElementsByClassName("scoreSummary")[0].children[0].innerText);

      // problems that have not yet been attempted don't display the percentage of questions answered correctly
      if (percentage !== null) {
        percentage = parseInt(percentage[0].replace(/\D/g, ""));

        // compare to the percentage in the courses object.  Use the ABS thing because the page rounds to the whole number, not down
        if (Math.abs(courses[CLASS][ASSIGNMENT]["p"][PROBLEM-1] - percentage) > 1) {
          courses[CLASS][ASSIGNMENT]["p"][PROBLEM-1] = percentage;

          // recalculate average
          var avg = 0;
          for (var i = 0; i < courses[CLASS][ASSIGNMENT]["p"].length; i++) {
            avg += courses[CLASS][ASSIGNMENT]["p"][i];
          }
          // update average
          courses[CLASS][ASSIGNMENT]["a"] = Math.floor(avg/courses[CLASS][ASSIGNMENT]["p"].length);

          // if average = 100, then delete the problems array
          if (courses[CLASS][ASSIGNMENT]["a"] === 100) {
            delete courses[CLASS][ASSIGNMENT]["p"];
          }
          updateCourses = true;

        }
      }

    } else if (ASSIGNMENT) {
      // add the problem list to the assignment
      var tableRows = document.getElementsByClassName("problem_set_table")[0];

      // check if the element actually exists (ex. doesn't exist if the user has an expired session)
      if (tableRows !== undefined) {

        tableRows = tableRows.children[1].children;

        // check if the assignment even exists (same code as below)
        if (courses[CLASS][ASSIGNMENT] === undefined) {
          courses[CLASS][ASSIGNMENT] = {
            "p": [],  // one-indexed array where the key is the percentage completed of a problem (index is the problem name)
            "a": 0  // average of all the values inside of the problems [] array
          };
          updateCourses = true;
        }

        if (courses[CLASS][ASSIGNMENT]["a"] < 100) { // don't execute if the assignment is 100% complete

        var problem_array = [];
        var total = 0;
        // fill out the problem array with the correct values
        for (var i = 1; i < tableRows.length; i++) { // skip the first row (header)
          // get the completion percentage
          var percentage = parseInt(tableRows[i].children[4].innerText, 10);
          total += percentage;
          // update the assignment's percentage array
          problem_array.push(percentage);
        }
        // check if there are any differences between the two arrays; if there are, then update the courses object with the new array
        if (problem_array.length !== courses[CLASS][ASSIGNMENT]["p"].length) {
          courses[CLASS][ASSIGNMENT]["p"] = problem_array;
          courses[CLASS][ASSIGNMENT]["a"] = Math.floor(total / problem_array.length);
          updateCourses = true;
        } else {
          for (var i = 0; i < problem_array.length; i++) {
            if (problem_array[i] !== courses[CLASS][ASSIGNMENT]["p"][i]) {
              courses[CLASS][ASSIGNMENT]["p"] = problem_array;
              courses[CLASS][ASSIGNMENT]["a"] = Math.floor(total / problem_array.length);
              updateCourses = true;
              break;
            }
          }
        }
      }
    }

  } else if (CLASS) {

    // add the assignment list to the options
    var tableRows = document.getElementsByClassName("problem_set_table")[0];

    // check if the element actually exists (ex. doesn't exist if the user has an expired session)
    if (tableRows !== undefined) {
      tableRows = tableRows.children[1].children;

      for (var i = 1; i < tableRows.length; i++) { // skip the first row (header)
        // get the assignent name (replace spaces with underscores)
        var assignmentName = tableRows[i].children[1].innerText.replace(/ /g, "_");

        // if the assignment doesn't exist in the courses object, add it
        if (courses[CLASS][assignmentName] === undefined) {
          courses[CLASS][assignmentName] = {
            "p": [],  // one-indexed array where the key is the percentage completed of a problem (index is the problem name)
            "a": 0  // average of all the values inside of the problems [] array
          };
          updateCourses = true;
        } else {

          // only give a percentage if the course has problems in it
          // if the average is 100, then the array doesn't exist
          if (courses[CLASS][assignmentName]["a"] === 100) {
            if (courses[CLASS][assignmentName]["p"] !== undefined) {
              delete courses[CLASS][assignmentName]["p"]; // delete problems array, we already know each problem is 100% complete
              updateCourses = true;
            }
            tableRows[i].children[2].innerHTML += '100';

          } else if (courses[CLASS][assignmentName]["p"].length > 0) {
            // choose the class depending on the percentage
            var className;

            if (courses[CLASS][assignmentName]["a"] < 70) {
              className = "WWdanger";
            } else if (courses[CLASS][assignmentName]["a"] < 100) {
              className = "WWwarning";
            }
            tableRows[i].children[2].innerHTML += '' +courses[CLASS][assignmentName]["a"]+'';
          }
        }

      }
    }
  }

  // if changes were made to the "courses" object, save them to storage.sync
  if (updateCourses) {

    // send updated courses to background.js
    chrome.runtime.sendMessage({greeting:"updateCourses", information:courses}, function (reply) {
      if (lastError) {
        console.log(lastError.message);
        return;
      }
    });
  }

  /*
  * Create the script in preparation for injection
  */

  var s = document.createElement('script');
  if (PROBLEM) {
    s.src = chrome.extension.getURL('problem.js'); // for answer previews and input expanding

  } else if (ASSIGNMENT) {
    s.src = chrome.extension.getURL('assignment.js'); // for showing how much is completed

  } else if (CLASS) {
    s.src = chrome.extension.getURL('class.js'); // for showing due dates
  }
  // remove from DOM when loaded as security precaution
  s.onload = function () {
    this.parentNode.removeChild(this);
  };
  (document.head || document.documentElement).appendChild(s);

}); // end of requestAll

}
<|endoftext|>


<commit_before>var compact = require('./compact')
var createSST = require('./sst')
var mem = require('./mem')
var mkdirp = require('mkdirp')
var path = require('path')
var merge = require('pull-merge')
var u = require('./util')
var zeros = '00000000'

function pad (n) {
  n = n.toString()
  return zeros.substring(n.length) + n
}

function isEmpty (o) {
  if(null == o) return true
  for(var k in o)
    return false
  return true
}

module.exports = function (createSST, createMemtable, createManifest) {

  return function (location, opts) {
    var memtable = mem(), counter = 0, db, compacting = false, _snapshot
    var tables = tables || [memtable]
    var manifest, tables, seq

    function nextTableName(type) {
      return type + '-' + pad(++seq) + '.json'
    }
    return db = {
      //should i separate all this stuff out so that
      //you can simulate the database all in memory?
      open: function (opts, cb) {
        if(!cb) cb = opts, opts = {}
        mkdirp(location, function (err) {
          if(err) return cb(err)
          manifest = createManifest(path.join(location, 'manifest.json'))
          manifest.open(function (err) {
            if(err) return cb(err)
            //if the manifest is empty create an empty memory table.
            if(isEmpty(manifest.data)) {
              seq = 1
              var filename = path.join(location, 'log-'+pad(seq)+'.json')
              var _memtable = createMemtable(filename)
              manifest.update({tables: ['log-'+pad(seq)+'.json'], seq: seq}, function (err) {
                if(err) return cb(err)
                _memtable.open(function (err) {
                  if(err) cb(err)
                  memtable = _memtable
                  _snapshot = [memtable]
                  cb(null, db)
                })
              })
            } else {
              //open all the tables.
              var _tables = manifest.data.tables || []
              var n = tables.length
              var _seq = 0

              _tables.forEach(function (name, i) {
                var m = /^(log|sst)-(\d+)\.json$/.exec(name)
                var type = m[1], table
                _seq = Math.max(m[2], _seq)

                var create = type == 'log' ? createMemtable : createSST
                var table = tables[i] = create(path.join(location, name))

                table.open(next)
              })
              function next (err) {
                if(err) return n = -1, cb(err)
                if(--n) return
                seq = _seq + 1
                db.nextSnapshot(tables)
                memtable = tables[0]
                cb(null, db)
              }
            }
          })
        })
      },
    //get the current snapshot.
      nextSnapshot: function (ary) {
        _snapshot = ary
        return db
      },
      snapshot: function () {
        if(_snapshot) {
          tables = _snapshot; _snapshot = null
        }
        return tables
      },
      //step through all the databases, and look for next
      get: function (key, cb) {
        var tables = db.snapshot()
        ;(function next (i) {
          //if we ran out of tables, err
          //gets need to use snapshots too...
          //but since they will return from the memtable
          //synchronously they will only need to track the SSTs
          //which probably means they can all share a snapshot
          //unless there is a compaction happening.

          //just have an SST snapshot,
          //keep a count of current gets
          //and don't delete any ssts until it's freed.

          if(!tables[i]) return cb(new Error('not found'))
          tables[i].get(key, function (err, value) {
            if(err) return next(i + 1)
            return cb(null, value)
          })
        })(0)
      },
      //only write to the FIRST table.
      put: function (key, value, cb) {
        return memtable.put(key, value, function (err) {
          if(!(++counter % 1000)) db.compact()
          //db.compact()
          //maybe compact?
          //just check if the number of records added
          cb(err)
        })
      },
      createReadStream: function (opts) {
        //merge streams from all the tables
        //it's probably okay to not have a snapshot on the memtable.
        //hmm, on the other hand, it will be fairly cheap...
        //otherwise I'd need to implement a skiplist, so you can have
        //streams that handle inserts.

        //TRACK HOW MANY ITERATORS ARE USING THIS SNAPSHOT.

        //read snapshots on the memtable are very simple, because it just
        //figures out the range sync and copies it to an array
        //so that doesn't need to be tracked specially.

        var tables = db.snapshot()

        console.log('readStream',
          tables.map(function (e) { return e.location })
        )

        var stream = tables[0].createReadStream(opts)
        console.log('start', tables[0].location)
        for(var i = 1; i < tables.length; i++) {
          console.log('merge', tables[i].location)
          stream = merge(tables[i].createReadStream(opts), stream, u.compare)
        }
        return stream
      },
      compact: function (cb) {
        cb = cb || function () {}
        //make a temp snapshot for use while compacting.
        //only one compaction at a time.
        if(compacting) return cb()
        compacting = true
        // create a new memtable, to save any writes while we are compacting.
        // save it in the manifest FIRST. That way we can be sure that we don't
        // loose that data if we crash while compacting.

        //add a new memtable to the manifest
        var name = nextTableName('log')
        var tables = db.snapshot()

        function getNames (tables) {
          return tables.map(function (e) {
            if(!e.location) throw new Error(e.type + 'table is missing location')
            return path.basename(e.location)
          })
        }

        var names = getNames(tables)
        names.unshift(name)
        var _memtable = createMemtable(path.join(location, name))
        _memtable.open(function (err) {
          //uphdate the mainfest to include the new memtable AND the old one.
          //this is so we don't forget any writes.
          manifest.update({tables: names, seq: seq}, function (err) {
            if(err) return cb(err)
            if(err) return cb(err)
            //switch to the new memtable.
            var __memtable = memtable
            tables = db.snapshot()
            memtable = _memtable
            //wait for the old memtable to drain.
            tables[0].freeze(function () {
              db.nextSnapshot([memtable].concat(tables))

              //maybe the api for sst should have a write stream,
              //except it errors unles it's all in order,
              //and you can only use it once?
              var newSST = path.join(location, nextTableName('sst'))
              var _tables = tables.slice()
              _tables = compact(_tables, createSST.createStream(newSST, function (err, sst) {
                if(err) return cb(err)
                //now that we have generated the sst,
                //save the new table set in the manifest,
                //so that if the process crashes we will reload the right data.
                //hmm, maybe we could just start using it... sst table are immutable, anyway.
                //the most important thing to have right is the memtables.
                //when an sst is no longer used (been compacted + no more iterators)
                //then it's safe to delete.
                _tables = [memtable, sst].concat(_tables)
                manifest.update({tables: getNames(_tables), seq: seq}, function (err) {
                  if(err) return cb(err)
                  compacting = false
                  db.nextSnapshot(_tables)
                  if(cb) cb()
                })
              }))
            })
          })
        })
      }
    }
  }
}
<commit_msg>add del, and batch<commit_after>var compact = require('./compact')
var createSST = require('./sst')
var mem = require('./mem')
var mkdirp = require('mkdirp')
var path = require('path')
var merge = require('pull-merge')
var u = require('./util')
var zeros = '00000000'

function pad (n) {
  n = n.toString()
  return zeros.substring(n.length) + n
}

function isEmpty (o) {
  if(null == o) return true
  for(var k in o)
    return false
  return true
}

module.exports = function (createSST, createMemtable, createManifest) {

  return function (location, opts) {
    var memtable = mem(), counter = 0, db, compacting = false, _snapshot
    var tables = tables || [memtable]
    var manifest, tables, seq

    function nextTableName(type) {
      return type + '-' + pad(++seq) + '.json'
    }
    return db = {
      //should i separate all this stuff out so that
      //you can simulate the database all in memory?
      open: function (opts, cb) {
        if(!cb) cb = opts, opts = {}
        mkdirp(location, function (err) {
          if(err) return cb(err)
          manifest = createManifest(path.join(location, 'manifest.json'))
          manifest.open(function (err) {
            if(err) return cb(err)
            //if the manifest is empty create an empty memory table.
            if(isEmpty(manifest.data)) {
              seq = 1
              var filename = path.join(location, 'log-'+pad(seq)+'.json')
              var _memtable = createMemtable(filename)
              manifest.update({tables: ['log-'+pad(seq)+'.json'], seq: seq}, function (err) {
                if(err) return cb(err)
                _memtable.open(function (err) {
                  if(err) cb(err)
                  memtable = _memtable
                  _snapshot = [memtable]
                  cb(null, db)
                })
              })
            } else {
              //open all the tables.
              var _tables = manifest.data.tables || []
              var n = tables.length
              var _seq = 0

              _tables.forEach(function (name, i) {
                var m = /^(log|sst)-(\d+)\.json$/.exec(name)
                var type = m[1], table
                _seq = Math.max(m[2], _seq)

                var create = type == 'log' ? createMemtable : createSST
                var table = tables[i] = create(path.join(location, name))

                table.open(next)
              })
              function next (err) {
                if(err) return n = -1, cb(err)
                if(--n) return
                seq = _seq + 1
                db.nextSnapshot(tables)
                memtable = tables[0]
                cb(null, db)
              }
            }
          })
        })
      },
    //get the current snapshot.
      nextSnapshot: function (ary) {
        _snapshot = ary
        return db
      },
      snapshot: function () {
        if(_snapshot) {
          tables = _snapshot; _snapshot = null
        }
        return tables
      },
      //step through all the databases, and look for next
      get: function (key, cb) {
        var tables = db.snapshot()
        ;(function next (i) {
          //if we ran out of tables, err
          //gets need to use snapshots too...
          //but since they will return from the memtable
          //synchronously they will only need to track the SSTs
          //which probably means they can all share a snapshot
          //unless there is a compaction happening.

          //just have an SST snapshot,
          //keep a count of current gets
          //and don't delete any ssts until it's freed.

          if(!tables[i]) return cb(new Error('not found'))
          tables[i].get(key, function (err, value) {
            if(err) return next(i + 1)
            return cb(null, value)
          })
        })(0)
      },
      //only write to the FIRST table.
      put: function (key, value, cb) {
        return memtable.put(key, value, function (err) {
          if(!(++counter % 1000)) db.compact()
          //db.compact()
          //maybe compact?
          //just check if the number of records added
          cb(err)
        })
      },
      del: function (del, cb) {
        return memtable.del(key, function (err) {
          if(!(++counter % 1000)) db.compact()
          cb(err)
        })
      },
      batch: function (ops, cb) {
        return memtable.batch(ops, function (err) {
          if(!(++counter % 1000)) db.compact()
          cb(err)
        })
      },
      createReadStream: function (opts) {
        //merge streams from all the tables
        //it's probably okay to not have a snapshot on the memtable.
        //hmm, on the other hand, it will be fairly cheap...
        //otherwise I'd need to implement a skiplist, so you can have
        //streams that handle inserts.

        //TRACK HOW MANY ITERATORS ARE USING THIS SNAPSHOT.

        //read snapshots on the memtable are very simple, because it just
        //figures out the range sync and copies it to an array
        //so that doesn't need to be tracked specially.

        var tables = db.snapshot()

        console.log('readStream',
          tables.map(function (e) { return e.location })
        )

        var stream = tables[0].createReadStream(opts)
        console.log('start', tables[0].location)
        for(var i = 1; i < tables.length; i++) {
          console.log('merge', tables[i].location)
          stream = merge(tables[i].createReadStream(opts), stream, u.compare)
        }
        return stream
      },
      compact: function (cb) {
        cb = cb || function () {}
        //make a temp snapshot for use while compacting.
        //only one compaction at a time.
        if(compacting) return cb()
        compacting = true
        // create a new memtable, to save any writes while we are compacting.
        // save it in the manifest FIRST. That way we can be sure that we don't
        // loose that data if we crash while compacting.

        //add a new memtable to the manifest
        var name = nextTableName('log')
        var tables = db.snapshot()

        function getNames (tables) {
          return tables.map(function (e) {
            if(!e.location) throw new Error(e.type + 'table is missing location')
            return path.basename(e.location)
          })
        }

        var names = getNames(tables)
        names.unshift(name)
        var _memtable = createMemtable(path.join(location, name))
        _memtable.open(function (err) {
          //uphdate the mainfest to include the new memtable AND the old one.
          //this is so we don't forget any writes.
          manifest.update({tables: names, seq: seq}, function (err) {
            if(err) return cb(err)
            if(err) return cb(err)
            //switch to the new memtable.
            var __memtable = memtable
            tables = db.snapshot()
            memtable = _memtable
            //wait for the old memtable to drain.
            tables[0].freeze(function () {
              db.nextSnapshot([memtable].concat(tables))

              //maybe the api for sst should have a write stream,
              //except it errors unles it's all in order,
              //and you can only use it once?
              var newSST = path.join(location, nextTableName('sst'))
              var _tables = tables.slice()
              _tables = compact(_tables, createSST.createStream(newSST, function (err, sst) {
                if(err) return cb(err)
                //now that we have generated the sst,
                //save the new table set in the manifest,
                //so that if the process crashes we will reload the right data.
                //hmm, maybe we could just start using it... sst table are immutable, anyway.
                //the most important thing to have right is the memtables.
                //when an sst is no longer used (been compacted + no more iterators)
                //then it's safe to delete.
                _tables = [memtable, sst].concat(_tables)
                manifest.update({tables: getNames(_tables), seq: seq}, function (err) {
                  if(err) return cb(err)
                  compacting = false
                  db.nextSnapshot(_tables)
                  if(cb) cb()
                })
              }))
            })
          })
        })
      }
    }
  }
}
<|endoftext|>


<commit_before>// This script runs in the website context.
(function(){
  function join(array) {
    var str = '';
    for (var i = 0; i < array.length; i++) {
      if (i !== 0) str += ',';
      str += array[i];
    }
    return str;
  }

  var frameworks = {
    'ActiveJS':             { abbr: 'AJS',  version: ['ActiveSupport']                      },
    'AngularJS':            { abbr: 'ng',   version: ['angular', 'version', 'full']         },
    'Backbone.js':          { abbr: 'BB',   version: ['Backbone', 'VERSION']                },
    'Base2':                { abbr: 'Base', version: ['base2', 'version']                   },
    'Clientcide Libraries': { abbr: 'Moo',  version: ['Clientcide', 'version']              },
    'Crafty':               { abbr: 'Crf',  version: ['Crafty', 'init']                     },
    'Cufon':                { abbr: 'Cuf',  version: ['Cufon']                              },
    'D3':                   { abbr: 'D3',   version: ['d3', 'version']                      },
    'DHTMLX':               { abbr: 'DHT',  version: ['dhtmlx']                             },
    'Dojo':                 { abbr: 'Dojo', version: function() {
      return window.dojo.version.toString();
    } },
    'Ember':                { abbr: 'Emb',  version: ['Ember', 'VERSION']                   },
    'Ext JS':               { abbr: 'Ext',  version: ['Ext', 'version']                     },
    'Glow':                 { abbr: 'Glw',  version: ['glow', 'VERSION']                    },
    'JavaScriptMVC':        { abbr: 'MVC',  version: ['steal', 'fn']                        },
    'jQuery':               { abbr: 'jQ',   version: ['jQuery', 'fn', 'jquery']             },
    'jQuery UI':            { abbr: 'jQUI', version: ['$', 'ui', 'version']                 },
    'Midori':               { abbr: 'Mid',  version: ['midori', 'domReady']                 },
    'Modernizr':            { abbr: 'Mzr',  version: ['Modernizr', '_version']              },
    'MochiKit':             { abbr: 'MK',   version: ['MochiKit', 'MochiKit', 'VERSION']    },
    'MooTools A.R.T.':      { abbr: 'Moo',  version: ['ART', 'version']                     },
    'MooTools Core':        { abbr: 'Moo',  version: ['MooTools', 'version']                },
    'MooTools More':        { abbr: 'Moo',  version: ['MooTools', 'More', 'version']        },
    'Processing.js':        { abbr: 'Prc',  version: ['Processing', 'version']              },
    'Prototype':            { abbr: 'Pro',  version: ['Prototype', 'Version']               },
    'Qooxdoo':              { abbr: 'Qxd',  version: ['qx', '$$libraries', 'qx', 'version'] },
    'Raphaël':              { abbr: 'Rël',  version: ['Raphael', 'version']                 },
    'RequireJS':            { abbr: 'rjs',  version: ['requirejs', 'version']               },
    'Rico':                 { abbr: 'Ric',  version: ['Rico', 'Version']                    },
    'RightJS':              { abbr: 'Rig',  version: ['RightJS', 'version']                 },
    'Sammy.js':             { abbr: 'Sam',  version: ['Sammy', 'VERSION']                   },
    'Script.aculo.us':      { abbr: 'Scr',  version: ['Scriptaculous', 'Version']           },
    'Scripty2':             { abbr: 'Sc2',  version: ['S2', 'Version']                      },
    'Snack':                { abbr: 'Snc',  version: ['snack', 'v']                         },
    'Spine':                { abbr: 'Spi',  version: ['Spine', 'version']                   },
    'SproutCore':           { abbr: 'SpC',  version: ['SC', 'isReady']                      },
    'Spry':                 { abbr: 'Spr',  version: ['Spry', '$']                          },
    'Underscore.js':        { abbr: '_',    version: ['_', 'VERSION']                       },
    'YUI 2':                { abbr: 'YUI',  version: ['YAHOO', 'VERSION']                   },
    'YUI 3':                { abbr: 'YUI',  version: ['YUI', 'version']                     },
    'Zepto':                { abbr: 'Zept', version: ['Zepto']                              },
    'ZK':                   { abbr: 'ZK',   version: ['zk', 'version']                      }
  };

  var data = [];
  for (var name in frameworks) {
    if (frameworks.hasOwnProperty(name)) {
      var framework = frameworks[name];
      var version = null;
      if (typeof framework.version == 'function') {
        try {
          version = framework.version();
        } catch (e) { }
      } else {
        version = window;
        for (var i = 0; i < framework.version.length; i++) {
          version = version && version[framework.version[i]];
        }
      }
      if (version) {
        var info = '{"name":"' + name + '"';
        info += ',"abbr":"' + framework.abbr + '"';
        if (typeof version == 'string' && version != '%build%') {
          info += ',"version":"' + version + '"';
        }
        info += '}';
        data[data.length] = info;
      }
    }
  }
  var messageElement = document.createElement('div');
  messageElement.textContent = '[' + join(data) + ']';
  messageElement.id = 'frameworks-data';
  document.body.appendChild(messageElement);
})();
<commit_msg>adding knockout js to injection file<commit_after>// This script runs in the website context.
(function(){
  function join(array) {
    var str = '';
    for (var i = 0; i < array.length; i++) {
      if (i !== 0) str += ',';
      str += array[i];
    }
    return str;
  }

  var frameworks = {
    'ActiveJS':             { abbr: 'AJS',  version: ['ActiveSupport']                      },
    'AngularJS':            { abbr: 'ng',   version: ['angular', 'version', 'full']         },
    'Backbone.js':          { abbr: 'BB',   version: ['Backbone', 'VERSION']                },
    'Base2':                { abbr: 'Base', version: ['base2', 'version']                   },
    'Clientcide Libraries': { abbr: 'Moo',  version: ['Clientcide', 'version']              },
    'Crafty':               { abbr: 'Crf',  version: ['Crafty', 'init']                     },
    'Cufon':                { abbr: 'Cuf',  version: ['Cufon']                              },
    'D3':                   { abbr: 'D3',   version: ['d3', 'version']                      },
    'DHTMLX':               { abbr: 'DHT',  version: ['dhtmlx']                             },
    'Dojo':                 { abbr: 'Dojo', version: function() {
      return window.dojo.version.toString();
    } },
    'Ember':                { abbr: 'Emb',  version: ['Ember', 'VERSION']                   },
    'Ext JS':               { abbr: 'Ext',  version: ['Ext', 'version']                     },
    'Glow':                 { abbr: 'Glw',  version: ['glow', 'VERSION']                    },
    'JavaScriptMVC':        { abbr: 'MVC',  version: ['steal', 'fn']                        },
    'jQuery':               { abbr: 'jQ',   version: ['jQuery', 'fn', 'jquery']             },
    'jQuery UI':            { abbr: 'jQUI', version: ['$', 'ui', 'version']                 },
    'Knockout.js':          { abbr: 'ko',   version: ['ko', 'version']                      },
    'Midori':               { abbr: 'Mid',  version: ['midori', 'domReady']                 },
    'Modernizr':            { abbr: 'Mzr',  version: ['Modernizr', '_version']              },
    'MochiKit':             { abbr: 'MK',   version: ['MochiKit', 'MochiKit', 'VERSION']    },
    'MooTools A.R.T.':      { abbr: 'Moo',  version: ['ART', 'version']                     },
    'MooTools Core':        { abbr: 'Moo',  version: ['MooTools', 'version']                },
    'MooTools More':        { abbr: 'Moo',  version: ['MooTools', 'More', 'version']        },
    'Processing.js':        { abbr: 'Prc',  version: ['Processing', 'version']              },
    'Prototype':            { abbr: 'Pro',  version: ['Prototype', 'Version']               },
    'Qooxdoo':              { abbr: 'Qxd',  version: ['qx', '$$libraries', 'qx', 'version'] },
    'Raphaël':              { abbr: 'Rël',  version: ['Raphael', 'version']                 },
    'RequireJS':            { abbr: 'rjs',  version: ['requirejs', 'version']               },
    'Rico':                 { abbr: 'Ric',  version: ['Rico', 'Version']                    },
    'RightJS':              { abbr: 'Rig',  version: ['RightJS', 'version']                 },
    'Sammy.js':             { abbr: 'Sam',  version: ['Sammy', 'VERSION']                   },
    'Script.aculo.us':      { abbr: 'Scr',  version: ['Scriptaculous', 'Version']           },
    'Scripty2':             { abbr: 'Sc2',  version: ['S2', 'Version']                      },
    'Snack':                { abbr: 'Snc',  version: ['snack', 'v']                         },
    'Spine':                { abbr: 'Spi',  version: ['Spine', 'version']                   },
    'SproutCore':           { abbr: 'SpC',  version: ['SC', 'isReady']                      },
    'Spry':                 { abbr: 'Spr',  version: ['Spry', '$']                          },
    'Underscore.js':        { abbr: '_',    version: ['_', 'VERSION']                       },
    'YUI 2':                { abbr: 'YUI',  version: ['YAHOO', 'VERSION']                   },
    'YUI 3':                { abbr: 'YUI',  version: ['YUI', 'version']                     },
    'Zepto':                { abbr: 'Zept', version: ['Zepto']                              },
    'ZK':                   { abbr: 'ZK',   version: ['zk', 'version']                      }
  };

  var data = [];
  for (var name in frameworks) {
    if (frameworks.hasOwnProperty(name)) {
      var framework = frameworks[name];
      var version = null;
      if (typeof framework.version == 'function') {
        try {
          version = framework.version();
        } catch (e) { }
      } else {
        version = window;
        for (var i = 0; i < framework.version.length; i++) {
          version = version && version[framework.version[i]];
        }
      }
      if (version) {
        var info = '{"name":"' + name + '"';
        info += ',"abbr":"' + framework.abbr + '"';
        if (typeof version == 'string' && version != '%build%') {
          info += ',"version":"' + version + '"';
        }
        info += '}';
        data[data.length] = info;
      }
    }
  }
  var messageElement = document.createElement('div');
  messageElement.textContent = '[' + join(data) + ']';
  messageElement.id = 'frameworks-data';
  document.body.appendChild(messageElement);
})();
<|endoftext|>


<commit_before>var path = require('path')
var home = require('os-homedir')

var nonPrivate = require('non-private-ip')
var merge = require('deep-extend')

var RC = require('rc')

var SEC = 1e3
var MIN = 60*SEC

module.exports = function (name, override) {
  name = name || 'ssb'
  var HOME = home() || 'browser' //most probably browser
  var result = RC(name || 'ssb', merge({
    //just use an ipv4 address by default.
    //there have been some reports of seemingly non-private
    //ipv6 addresses being returned and not working.
    //https://github.com/ssbc/scuttlebot/pull/102
    party: true,
    host: nonPrivate.v4 || '',
    port: 8008,
    timeout: 0,
    pub: true,
    local: true,
    friends: {
      dunbar: 150,
      hops: 3
    },
    ws: {
      port: 8989
    },
    gossip: {
      connections: 3
    },
    connections: {
      outgoing: {
        net: [{ transform: "shs" }]
      }
    },
    path: path.join(HOME, '.' + name),
    timers: {
      connection: 0,
      reconnect: 5*SEC,
      ping: 5*MIN,
      handshake: 5*SEC
    },
    //change these to make a test network that will not connect to the main network.
    caps: {
      //this is the key for accessing the ssb protocol.
      //this will be updated whenever breaking changes are made.
      //(see secret-handshake paper for a full explaination)
      //(generated by crypto.randomBytes(32).toString('base64'))
      shs: '1KHLiKZvAvjbY1ziZEHMXawbCEIM6qwjCDm3VYRan/s=',

      //used to sign messages
      sign: null
    },
    master: [],
    logging: { level: 'notice' }
  }, override || {}))

  if (!result.connections.incoming) {
    result.connections.incoming = {
      net: [{ host: result.host, port: result.port, scope: "public", "transform": "shs" }],
      ws: [{ host: result.host, port: result.ws.port, scope: "device", "transform": "shs" }]
    }
  }
  return result
}

<commit_msg>multiple scopes<commit_after>var path = require('path')
var home = require('os-homedir')

var nonPrivate = require('non-private-ip')
var merge = require('deep-extend')

var RC = require('rc')

var SEC = 1e3
var MIN = 60*SEC

module.exports = function (name, override) {
  name = name || 'ssb'
  var HOME = home() || 'browser' //most probably browser
  var result = RC(name || 'ssb', merge({
    //just use an ipv4 address by default.
    //there have been some reports of seemingly non-private
    //ipv6 addresses being returned and not working.
    //https://github.com/ssbc/scuttlebot/pull/102
    party: true,
    host: nonPrivate.v4 || '',
    port: 8008,
    timeout: 0,
    pub: true,
    local: true,
    friends: {
      dunbar: 150,
      hops: 3
    },
    ws: {
      port: 8989
    },
    gossip: {
      connections: 3
    },
    connections: {
      outgoing: {
        net: [{ transform: "shs" }]
      }
    },
    path: path.join(HOME, '.' + name),
    timers: {
      connection: 0,
      reconnect: 5*SEC,
      ping: 5*MIN,
      handshake: 5*SEC
    },
    //change these to make a test network that will not connect to the main network.
    caps: {
      //this is the key for accessing the ssb protocol.
      //this will be updated whenever breaking changes are made.
      //(see secret-handshake paper for a full explaination)
      //(generated by crypto.randomBytes(32).toString('base64'))
      shs: '1KHLiKZvAvjbY1ziZEHMXawbCEIM6qwjCDm3VYRan/s=',

      //used to sign messages
      sign: null
    },
    master: [],
    logging: { level: 'notice' }
  }, override || {}))

  if (!result.connections.incoming) {
    result.connections.incoming = {
      net: [{ host: result.host || '::', port: result.port, scope: ["device", "local", "public"], "transform": "shs"}],
      ws: [{ host: result.host || '::', port: result.ws.port, scope: ["device", "local", "public"], "transform": "shs" }]
    }
  }

  return result
}

<|endoftext|>


<commit_before>const {assert} = require('chai');
const cp = require('child_process');
const uuid = require(`uuid`);

const containerAnalysis = require('@google-cloud/containeranalysis');
const client = new containerAnalysis.v1beta1.GrafeasV1Beta1Client();

const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'});

const uuidVal = uuid.v4();
const noteId = `test-note-${uuidVal}`;
const resourceUrl = `gcr.io/test-project/test-image-${uuidVal}`;
const subscriptionId = `occurrence-subscription-${uuidVal}`;
const timeoutSeconds = 5;

const {PubSub} = require('@google-cloud/pubsub');
const pubsub = new PubSub();
const topicName = 'container-analysis-occurrences-v1beta1';
const topic = pubsub.topic(topicName);

let projectId;
let formattedParent;
let formattedNoteName;

describe('Note tests', function() {
  before(async function() {
    // define projectId and related vars
    projectId = await client.getProjectId();
    formattedParent = `projects/${projectId}`;
    formattedNoteName = `projects/${projectId}/notes/${noteId}`;
  });
  after(async function() {
    const [allOccurrences] = await client.listOccurrences({
      parent: formattedParent,
      filter: `resourceUrl = "${resourceUrl}"`,
    });

    allOccurrences.forEach(async occurrence => {
      await client.deleteOccurrence({name: occurrence.name});
      console.log(`deleted occurrence ${occurrence.name}`);
    });

    const [allNotes] = await client.listNotes({
      parent: formattedParent,
    });

    allNotes.forEach(async note => {
      await client.deleteNote({name: note.name});
      console.log(`deleted note ${note.name}`);
    });
  });
  it('should create a note', function() {
    const output = execSync(`node createNote.js "${projectId}" "${noteId}"`);
    assert.match(output, new RegExp(`Note ${formattedNoteName} created.`));
  });

  it('should get note', function() {
    const output = execSync(`node getNote.js "${projectId}" "${noteId}"`);
    assert.match(output, new RegExp(`Note name: ${formattedNoteName}`));
  });

  it('should create occurrence', function() {
    const output = execSync(
      `node createOccurrence.js "${projectId}" "${noteId}" "${projectId}" "${resourceUrl}"`
    );
    assert.match(output, new RegExp(`Occurrence created`));
  });

  // TODO: sometimes fails, should try again if no images are found
  it('should get occurrence', async function() {
    const [occurrences] = await client.listOccurrences({
      parent: formattedParent,
    });
    assert(occurrences.length > 0);

    const occurrence = occurrences[0];
    const occurrenceId = occurrence.name.split('/')[3];
    const output = execSync(
      `node getOccurrence.js "${projectId}" "${occurrenceId}"`
    );
    assert.match(output, new RegExp(`Occurrence name: ${occurrence.name}`));
  });

  it('should get occurences for note', function() {
    const output = execSync(
      `node occurrencesForNote.js "${projectId}" "${noteId}"`
    );
    assert.match(output, /Occurrences:/);
  });

  it('should get occurrences for image', function() {
    const output = execSync(
      `node occurrencesForImage.js "${projectId}" "${resourceUrl}"`
    );
    assert.match(output, new RegExp(`Occurrences for ${resourceUrl}`));
  });

  it('should get discovery info for image', async function() {
    const discoveryNoteRequest = {
      parent: formattedParent,
      noteId: `${noteId}-discovery`,
      note: {
        discovery: {},
      },
    };

    await client.createNote(discoveryNoteRequest);

    const occurrenceRequest = {
      parent: formattedParent,
      occurrence: {
        noteName: `${formattedNoteName}-discovery`,
        discovered: {
          discovered: {
            analysisStatus: 'FINISHED_SUCCESS',
          },
        },
        resource: {
          uri: resourceUrl,
        },
      },
    };

    await client.createOccurrence(occurrenceRequest);

    const output = execSync(
      `node getDiscoveryInfo "${projectId}" "${resourceUrl}"`
    );
    assert.match(
      output,
      new RegExp(`Discovery Occurrences for ${resourceUrl}`)
    );
  });

  it('should get high severity vulnerabilities for image', async function() {
    const criticalNoteReq = {
      parent: formattedParent,
      noteId: `${noteId}-critical`,
      note: {
        vulnerability: {
          severity: 'CRITICAL',
        },
      },
    };

    await client.createNote(criticalNoteReq);

    const criticalOccurrenceReq = {
      parent: formattedParent,
      occurrence: {
        noteName: `${formattedNoteName}-critical`,
        vulnerability: {
          vulnerability: {
            severity: 'CRITICAL',
          },
        },
        resource: {
          uri: resourceUrl,
        },
      },
    };

    await client.createOccurrence(criticalOccurrenceReq);

    const output = execSync(
      `node highVulnerabilitiesForImage "${projectId}" "${resourceUrl}"`
    );

    assert.match(
      output,
      new RegExp(`High Severity Vulnerabilities for ${resourceUrl}`)
    );
  });

  it('should get all vulnerabilites for image', function() {
    const output = execSync(
      `node vulnerabilityOccurrencesForImage "${projectId}" "${resourceUrl}"`
    );
    assert.match(output, new RegExp(`All Vulnerabilities for ${resourceUrl}`));
  });

  it('should delete occurrence', async function() {
    const [occurrences] = await client.listOccurrences({
      parent: formattedParent,
    });
    assert(occurrences.length > 0);
    const occurrence = occurrences[0];
    const occurrenceId = occurrence.name.split('/')[3];

    const output = execSync(
      `node deleteOccurrence.js "${projectId}" "${occurrenceId}"`
    );
    assert.match(output, new RegExp(`Occurrence deleted.`));
  });
  it('should delete note', function() {
    const output = execSync(`node deleteNote.js "${projectId}" "${noteId}" `);
    assert.match(output, new RegExp(`Note ${formattedNoteName} deleted.`));
  });
});

// TODO: complete polling sample
xdescribe('polling', function() {
  before(async function() {
    // define project id and related vars
    projectId = await client.getProjectId();
    formattedParent = `projects/${projectId}`;
    formattedNoteName = `projects/${projectId}/notes/${noteId}`;

    const discoveryNoteRequest = {
      parent: formattedParent,
      noteId: `${noteId}-discovery-polling`,
      note: {
        discovery: {
          continuousAnalysis: 'INACTIVE',
        },
      },
    };

    await client.createNote(discoveryNoteRequest);

    const occurrenceRequest = {
      parent: formattedParent,
      occurrence: {
        noteName: `${formattedNoteName}-discovery-polling`,
        discovered: {
          discovered: {
            analysisStatus: 'FINISHED_SUCCESS',
          },
        },
      },
      resource: {
        uri: resourceUrl,
      },
    };

    await client.createOccurrence(occurrenceRequest);
  });

  after(async function() {
    const [discoveryOccurrences] = await client.listNoteOccurrences({
      name: `${formattedNoteName}-discovery-polling`,
    });
    discoveryOccurrences.forEach(async occurrence => {
      await client.deleteOccurrence({name: occurrence.name});
    });
    await client.deleteNote({name: `${formattedNoteName}-discovery-polling`});
  });

  it('should successfully poll latest discovery occurrence', function() {
    const output = execSync(
      `node pollDiscoveryOccurrenceFinished.js "${projectId}" "${resourceUrl}" "${timeoutSeconds}"`
    );
    assert.match(
      output,
      new RegExp(`Polled Discovery Occurrences for ${resourceUrl}`)
    );
  });
});

describe('pubsub', function() {
  before(async function() {
    // define project id and related vars
    projectId = await client.getProjectId();
    formattedParent = `projects/${projectId}`;
    formattedNoteName = `projects/${projectId}/notes/${noteId}`;
  });

  beforeEach(async function() {
    await topic.createSubscription(subscriptionId);
    const pubSubNoteReq = {
      parent: formattedParent,
      noteId: `${noteId}-pubsub`,
      note: {
        vulnerability: {},
      },
    };
    await client.createNote(pubSubNoteReq);
  });

  afterEach(async function() {
    await client.deleteNote({name: `${formattedNoteName}-pubsub`});
    await pubsub.subscription(subscriptionId).delete();
  });

  it('should get accurate count of occurrences from pubsub topic', async function() {
    const expectedNum = 3;
    const pubSubOccurrenceReq = {
      parent: formattedParent,
      occurrence: {
        noteName: `${formattedNoteName}-pubsub`,
        vulnerability: {
          vulnerability: {},
        },
        resource: {
          uri: resourceUrl,
        },
      },
    };

    // empty subscription
    execSync(
      `node occurrencePubSub.js "${projectId}" "${subscriptionId}" "${timeoutSeconds}"`
    );

    // make sure empty
    const empty = execSync(
      `node occurrencePubSub.js "${projectId}" "${subscriptionId}" "${timeoutSeconds}"`
    );

    assert.match(empty, new RegExp(`Polled 0 occurrences`));
    // create test occurrences
    for (let i = 0; i < expectedNum; i++) {
      const [pubSubOccurrence] = await client.createOccurrence(
        pubSubOccurrenceReq
      );
      await client.deleteOccurrence({name: pubSubOccurrence.name});
    }
    const output = execSync(
      `node occurrencePubSub.js "${projectId}" "${subscriptionId}" "${timeoutSeconds}"`
    );

    // make sure pubsub number matches
    assert.match(output, new RegExp(`Polled ${expectedNum} occurrences`));
  });
});
<commit_msg>added retry logic to get occurrence test<commit_after>const {assert} = require('chai');
const cp = require('child_process');
const uuid = require(`uuid`);

const containerAnalysis = require('@google-cloud/containeranalysis');
const client = new containerAnalysis.v1beta1.GrafeasV1Beta1Client();

const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'});

const uuidVal = uuid.v4();
const noteId = `test-note-${uuidVal}`;
const resourceUrl = `gcr.io/test-project/test-image-${uuidVal}`;
const subscriptionId = `occurrence-subscription-${uuidVal}`;
const timeoutSeconds = 5;
const retries = 5;

const {PubSub} = require('@google-cloud/pubsub');
const pubsub = new PubSub();
const topicName = 'container-analysis-occurrences-v1beta1';
const topic = pubsub.topic(topicName);

let projectId;
let formattedParent;
let formattedNoteName;

describe('Note tests', function() {
  before(async function() {
    // define projectId and related vars
    projectId = await client.getProjectId();
    formattedParent = `projects/${projectId}`;
    formattedNoteName = `projects/${projectId}/notes/${noteId}`;
  });
  after(async function() {
    const [allOccurrences] = await client.listOccurrences({
      parent: formattedParent,
      filter: `resourceUrl = "${resourceUrl}"`,
    });

    allOccurrences.forEach(async occurrence => {
      await client.deleteOccurrence({name: occurrence.name});
      console.log(`deleted occurrence ${occurrence.name}`);
    });

    const [allNotes] = await client.listNotes({
      parent: formattedParent,
    });

    allNotes.forEach(async note => {
      await client.deleteNote({name: note.name});
      console.log(`deleted note ${note.name}`);
    });
  });
  it('should create a note', function() {
    const output = execSync(`node createNote.js "${projectId}" "${noteId}"`);
    assert.match(output, new RegExp(`Note ${formattedNoteName} created.`));
  });

  it('should get note', function() {
    const output = execSync(`node getNote.js "${projectId}" "${noteId}"`);
    assert.match(output, new RegExp(`Note name: ${formattedNoteName}`));
  });

  it('should create occurrence', function() {
    const output = execSync(
      `node createOccurrence.js "${projectId}" "${noteId}" "${projectId}" "${resourceUrl}"`
    );
    assert.match(output, new RegExp(`Occurrence created`));
  });

  it('should get occurrence', async function() {
    const [occurrences] = await client.listOccurrences({
      parent: formattedParent,
    });
    assert(occurrences.length > 0);

    const occurrence = occurrences[0];
    const occurrenceId = occurrence.name.split('/')[3];
    let output;
    for (let i = 0; i < retries; i++) {
      output = execSync(
        `node getOccurrence.js "${projectId}" "${occurrenceId}"`
      );
      if (output.includes('Occurrence name:')) {
        break;
      }
    }

    assert.match(output, new RegExp(`Occurrence name: ${occurrence.name}`));
  });

  it('should get occurences for note', function() {
    const output = execSync(
      `node occurrencesForNote.js "${projectId}" "${noteId}"`
    );
    assert.match(output, /Occurrences:/);
  });

  it('should get occurrences for image', function() {
    const output = execSync(
      `node occurrencesForImage.js "${projectId}" "${resourceUrl}"`
    );
    assert.match(output, new RegExp(`Occurrences for ${resourceUrl}`));
  });

  it('should get discovery info for image', async function() {
    const discoveryNoteRequest = {
      parent: formattedParent,
      noteId: `${noteId}-discovery`,
      note: {
        discovery: {},
      },
    };

    await client.createNote(discoveryNoteRequest);

    const occurrenceRequest = {
      parent: formattedParent,
      occurrence: {
        noteName: `${formattedNoteName}-discovery`,
        discovered: {
          discovered: {
            analysisStatus: 'FINISHED_SUCCESS',
          },
        },
        resource: {
          uri: resourceUrl,
        },
      },
    };

    await client.createOccurrence(occurrenceRequest);

    const output = execSync(
      `node getDiscoveryInfo "${projectId}" "${resourceUrl}"`
    );
    assert.match(
      output,
      new RegExp(`Discovery Occurrences for ${resourceUrl}`)
    );
  });

  it('should get high severity vulnerabilities for image', async function() {
    const criticalNoteReq = {
      parent: formattedParent,
      noteId: `${noteId}-critical`,
      note: {
        vulnerability: {
          severity: 'CRITICAL',
        },
      },
    };

    await client.createNote(criticalNoteReq);

    const criticalOccurrenceReq = {
      parent: formattedParent,
      occurrence: {
        noteName: `${formattedNoteName}-critical`,
        vulnerability: {
          vulnerability: {
            severity: 'CRITICAL',
          },
        },
        resource: {
          uri: resourceUrl,
        },
      },
    };

    await client.createOccurrence(criticalOccurrenceReq);

    const output = execSync(
      `node highVulnerabilitiesForImage "${projectId}" "${resourceUrl}"`
    );

    assert.match(
      output,
      new RegExp(`High Severity Vulnerabilities for ${resourceUrl}`)
    );
  });

  it('should get all vulnerabilites for image', function() {
    const output = execSync(
      `node vulnerabilityOccurrencesForImage "${projectId}" "${resourceUrl}"`
    );
    assert.match(output, new RegExp(`All Vulnerabilities for ${resourceUrl}`));
  });

  it('should delete occurrence', async function() {
    const [occurrences] = await client.listOccurrences({
      parent: formattedParent,
    });
    assert(occurrences.length > 0);
    const occurrence = occurrences[0];
    const occurrenceId = occurrence.name.split('/')[3];

    const output = execSync(
      `node deleteOccurrence.js "${projectId}" "${occurrenceId}"`
    );
    assert.match(output, new RegExp(`Occurrence deleted.`));
  });
  it('should delete note', function() {
    const output = execSync(`node deleteNote.js "${projectId}" "${noteId}" `);
    assert.match(output, new RegExp(`Note ${formattedNoteName} deleted.`));
  });
});

// TODO: complete polling sample
xdescribe('polling', function() {
  before(async function() {
    // define project id and related vars
    projectId = await client.getProjectId();
    formattedParent = `projects/${projectId}`;
    formattedNoteName = `projects/${projectId}/notes/${noteId}`;

    const discoveryNoteRequest = {
      parent: formattedParent,
      noteId: `${noteId}-discovery-polling`,
      note: {
        discovery: {
          continuousAnalysis: 'INACTIVE',
        },
      },
    };

    await client.createNote(discoveryNoteRequest);

    const occurrenceRequest = {
      parent: formattedParent,
      occurrence: {
        noteName: `${formattedNoteName}-discovery-polling`,
        discovered: {
          discovered: {
            analysisStatus: 'FINISHED_SUCCESS',
          },
        },
      },
      resource: {
        uri: resourceUrl,
      },
    };

    await client.createOccurrence(occurrenceRequest);
  });

  after(async function() {
    const [discoveryOccurrences] = await client.listNoteOccurrences({
      name: `${formattedNoteName}-discovery-polling`,
    });
    discoveryOccurrences.forEach(async occurrence => {
      await client.deleteOccurrence({name: occurrence.name});
    });
    await client.deleteNote({name: `${formattedNoteName}-discovery-polling`});
  });

  it('should successfully poll latest discovery occurrence', function() {
    const output = execSync(
      `node pollDiscoveryOccurrenceFinished.js "${projectId}" "${resourceUrl}" "${timeoutSeconds}"`
    );
    assert.match(
      output,
      new RegExp(`Polled Discovery Occurrences for ${resourceUrl}`)
    );
  });
});

describe('pubsub', function() {
  before(async function() {
    // define project id and related vars
    projectId = await client.getProjectId();
    formattedParent = `projects/${projectId}`;
    formattedNoteName = `projects/${projectId}/notes/${noteId}`;
  });

  beforeEach(async function() {
    await topic.createSubscription(subscriptionId);
    const pubSubNoteReq = {
      parent: formattedParent,
      noteId: `${noteId}-pubsub`,
      note: {
        vulnerability: {},
      },
    };
    await client.createNote(pubSubNoteReq);
  });

  afterEach(async function() {
    await client.deleteNote({name: `${formattedNoteName}-pubsub`});
    await pubsub.subscription(subscriptionId).delete();
  });

  it('should get accurate count of occurrences from pubsub topic', async function() {
    const expectedNum = 3;
    const pubSubOccurrenceReq = {
      parent: formattedParent,
      occurrence: {
        noteName: `${formattedNoteName}-pubsub`,
        vulnerability: {
          vulnerability: {},
        },
        resource: {
          uri: resourceUrl,
        },
      },
    };

    // empty subscription
    execSync(
      `node occurrencePubSub.js "${projectId}" "${subscriptionId}" "${timeoutSeconds}"`
    );

    // make sure empty
    const empty = execSync(
      `node occurrencePubSub.js "${projectId}" "${subscriptionId}" "${timeoutSeconds}"`
    );

    assert.match(empty, new RegExp(`Polled 0 occurrences`));
    // create test occurrences
    for (let i = 0; i < expectedNum; i++) {
      const [pubSubOccurrence] = await client.createOccurrence(
        pubSubOccurrenceReq
      );
      await client.deleteOccurrence({name: pubSubOccurrence.name});
    }
    const output = execSync(
      `node occurrencePubSub.js "${projectId}" "${subscriptionId}" "${timeoutSeconds}"`
    );

    // make sure pubsub number matches
    assert.match(output, new RegExp(`Polled ${expectedNum} occurrences`));
  });
});
<|endoftext|>


<commit_before>var _; //globals

describe("About Applying What We Have Learnt", function() {

  var products;

  beforeEach(function () {
    products = [
       { name: "Sonoma", ingredients: ["artichoke", "sundried tomatoes", "mushrooms"], containsNuts: false },
       { name: "Pizza Primavera", ingredients: ["roma", "sundried tomatoes", "goats cheese", "rosemary"], containsNuts: false },
       { name: "South Of The Border", ingredients: ["black beans", "jalapenos", "mushrooms"], containsNuts: false },
       { name: "Blue Moon", ingredients: ["blue cheese", "garlic", "walnuts"], containsNuts: true },
       { name: "Taste Of Athens", ingredients: ["spinach", "kalamata olives", "sesame seeds"], containsNuts: true }
    ];
  });

  /*********************************************************************************/

  it("given I'm allergic to nuts and hate mushrooms, it should find a pizza I can eat (imperative)", function () {

    var i,j,hasMushrooms, productsICanEat = [];

    for (i = 0; i < products.length; i+=1) {
        if (products[i].containsNuts === false) {
            hasMushrooms = false;
            for (j = 0; j < products[i].ingredients.length; j+=1) {
               if (products[i].ingredients[j] === "mushrooms") {
                  hasMushrooms = true;
               }
            }
            if (!hasMushrooms) productsICanEat.push(products[i]);
        }
    }

    expect(productsICanEat.length).toBe(1);
  });

  it("given I'm allergic to nuts and hate mushrooms, it should find a pizza I can eat (functional)", function () {

      var isMushroom = function(x) { return x === "mushrooms" };

      var productsICanEat = _(products).filter(function(x){
          return (!_(x.ingredients).any(isMushroom) && !x.containsNuts);
      });

      /* solve using filter() & all() / any() */

      expect(productsICanEat.length).toBe(1);
  });

  /*********************************************************************************/

  it("should add all the natural numbers below 1000 that are multiples of 3 or 5 (imperative)", function () {

    var sum = 0;
    for(var i=1; i<1000; i+=1) {
      if (i % 3 === 0 || i % 5 === 0) {
        sum += i;
      }
    }

    expect(sum).toBe(233168);
  });

  it("should add all the natural numbers below 1000 that are multiples of 3 or 5 (functional)", function () {

    var sum = _.range(1000).reduce(function(sum, x) {
        if (x % 3 === 0 || x % 5 === 0) {
            return sum + x;
        } else {
            return sum;
        }
    });    /* try chaining range() and reduce() */

    expect(233168).toBe(sum);
  });

  /*********************************************************************************/
   it("should count the ingredient occurrence (imperative)", function () {
    var ingredientCount = { "{ingredient name}": 0 };

    for (i = 0; i < products.length; i+=1) {
        for (j = 0; j < products[i].ingredients.length; j+=1) {
            ingredientCount[products[i].ingredients[j]] = (ingredientCount[products[i].ingredients[j]] || 0) + 1;
        }
    }

    expect(ingredientCount['mushrooms']).toBe(2);
  });

  it("should count the ingredient occurrence (functional)", function () {
    var ingredientCount = { "{ingredient name}": 0 };

    /* chain() together map(), flatten() and reduce() */

      function countIngredients(productList) {
          return _(productList).chain()
              .map(function(x) {
                  return x.ingredients;
              })
              .flatten()
              .reduce(function(memo, y) {
                  return ingredientCount[y] = (ingredientCount[y] || 0) + 1;
              })
              .value();
      }

      countIngredients(products);

    expect(ingredientCount['mushrooms']).toBe(2);
  });

  /*********************************************************************************/
  /* UNCOMMENT FOR EXTRA CREDIT */
  /*
  it("should find the largest prime factor of a composite number", function () {

  });

  it("should find the largest palindrome made from the product of two 3 digit numbers", function () {

  });

  it("should find the smallest number divisible by each of the numbers 1 to 20", function () {

  });

  it("should find the difference between the sum of the squares and the square of the sums", function () {

  });

  it("should find the 10001st prime", function () {

  });
  */
});
<commit_msg>First attempt at prime factor extra credit. Thinking that a recursive call may simplify the prime function.<commit_after>var _; //globals

describe("About Applying What We Have Learnt", function() {

  var products;

  beforeEach(function () {
    products = [
       { name: "Sonoma", ingredients: ["artichoke", "sundried tomatoes", "mushrooms"], containsNuts: false },
       { name: "Pizza Primavera", ingredients: ["roma", "sundried tomatoes", "goats cheese", "rosemary"], containsNuts: false },
       { name: "South Of The Border", ingredients: ["black beans", "jalapenos", "mushrooms"], containsNuts: false },
       { name: "Blue Moon", ingredients: ["blue cheese", "garlic", "walnuts"], containsNuts: true },
       { name: "Taste Of Athens", ingredients: ["spinach", "kalamata olives", "sesame seeds"], containsNuts: true }
    ];
  });

  /*********************************************************************************/

  it("given I'm allergic to nuts and hate mushrooms, it should find a pizza I can eat (imperative)", function () {

    var i,j,hasMushrooms, productsICanEat = [];

    for (i = 0; i < products.length; i+=1) {
        if (products[i].containsNuts === false) {
            hasMushrooms = false;
            for (j = 0; j < products[i].ingredients.length; j+=1) {
               if (products[i].ingredients[j] === "mushrooms") {
                  hasMushrooms = true;
               }
            }
            if (!hasMushrooms) productsICanEat.push(products[i]);
        }
    }

    expect(productsICanEat.length).toBe(1);
  });

  it("given I'm allergic to nuts and hate mushrooms, it should find a pizza I can eat (functional)", function () {

      var isMushroom = function(x) { return x === "mushrooms" };

      var productsICanEat = _(products).filter(function(x){
          return (!_(x.ingredients).any(isMushroom) && !x.containsNuts);
      });

      /* solve using filter() & all() / any() */

      expect(productsICanEat.length).toBe(1);
  });

  /*********************************************************************************/

  it("should add all the natural numbers below 1000 that are multiples of 3 or 5 (imperative)", function () {

    var sum = 0;
    for(var i=1; i<1000; i+=1) {
      if (i % 3 === 0 || i % 5 === 0) {
        sum += i;
      }
    }

    expect(sum).toBe(233168);
  });

  it("should add all the natural numbers below 1000 that are multiples of 3 or 5 (functional)", function () {

    var sum = _.range(1000).reduce(function(sum, x) {
        if (x % 3 === 0 || x % 5 === 0) {
            return sum + x;
        } else {
            return sum;
        }
    });    /* try chaining range() and reduce() */

    expect(233168).toBe(sum);
  });

  /*********************************************************************************/
   it("should count the ingredient occurrence (imperative)", function () {
    var ingredientCount = { "{ingredient name}": 0 };

    for (i = 0; i < products.length; i+=1) {
        for (j = 0; j < products[i].ingredients.length; j+=1) {
            ingredientCount[products[i].ingredients[j]] = (ingredientCount[products[i].ingredients[j]] || 0) + 1;
        }
    }

    expect(ingredientCount['mushrooms']).toBe(2);
  });

  it("should count the ingredient occurrence (functional)", function () {
    var ingredientCount = { "{ingredient name}": 0 };

    /* chain() together map(), flatten() and reduce() */

      function countIngredients(productList) {
          return _(productList).chain()
              .map(function(x) {
                  return x.ingredients;
              })
              .flatten()
              .reduce(function(memo, y) {
                  return ingredientCount[y] = (ingredientCount[y] || 0) + 1;
              })
              .value();
      }

      countIngredients(products);

    expect(ingredientCount['mushrooms']).toBe(2);
  });

  /*********************************************************************************/
  /* UNCOMMENT FOR EXTRA CREDIT */

  it("should find the largest prime factor of a composite number", function () {
    function isPrime(n) {
      if (n >= 1 && n <= 2) {
          return true;
      } else {
        var maxTestValue = Math.ceil(Math.sqrt(n));
        for (var i = 2; i <= maxTestValue; i++) {
          if (n % i === 0) {
            return false;
          }
        }
        return true;
      }
    }

    function findPrimeNumbers(n) {
      var primesArray = [];
      for (var i = n; i > 0; i--) {
        if (isPrime(i)) {
           primesArray.push(i);
        }
      }
      return primesArray;
    }

    function findGreatestPrimeFactor(n) {
      if (isPrime(n)) {
        return console.error("You entered a prime number.")
      }

      var testNumbers = findPrimeNumbers(n);

      for (var i = 0; i < testNumbers.length; i++) {
        if (n % testNumbers[i] === 0) {
          console.log(testNumbers[i]);
          return testNumbers[i];
        }
      }
    }

    expect(findGreatestPrimeFactor(18)).toBe(3);

    expect(findGreatestPrimeFactor(3)).toBe('console.error("You entered a prime number.")');

  });

  it("should find the largest palindrome made from the product of two 3 digit numbers", function () {

    function palindromeTest(n) {
      //stringify number
      //
    }

    //multiply two arguments
    //decrement to zero
    //break when number is palindrome

  });

  it("should find the smallest number divisible by each of the numbers 1 to 20", function () {

  });

  it("should find the difference between the sum of the squares and the square of the sums", function () {

  });

  it("should find the 10001st prime", function () {

  });

});
<|endoftext|>