[
  {
    "path": ".gitignore",
    "content": "build/\n.DS_STORE\nnode_modules/\next.zip\nTODO\nGE.min.js\nGE.js\n.dir-locals.el\n\\#*\\#\nGTAGS\nGRTAGS\nGPATH\nexperiments/\n.tern-port\n.tern-project\nlog.md\nbuild.zip\nglobal.js\n"
  },
  {
    "path": ".jscsrc",
    "content": "{\n  \"preset\": \"google\",\n  \"disallowSpacesInAnonymousFunctionExpression\": null,\n  \"excludeFiles\": [\"node_modules/**\"]\n}\n"
  },
  {
    "path": ".jshintrc",
    "content": "{\n  \"node\": true,\n  \"browser\": true,\n  \"bitwise\": true,\n  \"camelcase\": true,\n  \"curly\": true,\n  \"eqeqeq\": true,\n  \"immed\": true,\n  \"indent\": 2,\n  \"latedef\": true,\n  \"noarg\": true,\n  \"quotmark\": \"single\",\n  \"undef\": true,\n  \"unused\": true,\n  \"newcap\": false,\n  \"globals\": {\n    \"Polymer\": true,\n    \"Platform\": true,\n    \"Promise\": true,\n    \"MathAndPhysics\": true,\n    \"CookieManager\": true,\n    \"Model\": true,\n    \"window\": true,\n    \"document\": true\n  }\n}\n"
  },
  {
    "path": "README.md",
    "content": "# Udacity Feedback Chrome Extension\n\nImmediate, visual feedback about any website's HTML, CSS and JavaScript.\n\n* Not sure what this is? Try the [walkthrough](http://labs.udacity.com/udacity-feedback-extension/).\n* Just want to install? Visit the [Chrome Web Store](https://chrome.google.com/webstore/detail/udacity-front-end-feedbac/melpgahbngpgnbhhccnopmlmpbmdaeoi).\n\n## Installing from Source\n\n1. Clone this repo\n2. `npm install` - install dependencies\n3. `gulp watch` or just `gulp` - build the grading engine\n4. [Load in Chrome](https://developer.chrome.com/extensions/getstarted#unpacked)\n  * Open the Extensions window (`chrome://extensions`)\n  * Check 'Developer Mode'\n  * Click 'Load unpacked extension...'\n  * Select `ext/`\n\n[**More on development**](#how-udacity-feedback-works)\n\n## Loading Tests\n\n### On sites you own\n\nAdd the following meta tag:\n\n```html\n<meta name=\"udacity-grader\" content=\"relative_path_to_tests.json\">\n```\n\nThere are two optional attributes: `libraries` and `unit-tests`. `libraries` is always optional and `unit-tests` is only necessary for JS quizzes. More on JS tests [here](#js-tests).\n\n### On sites you don't own\n\nClick on the Udacity browser action. Choose 'Load tests' and navigate to a JSON.\n\n## API\n\n### JSON\n\nTypical structure is an array of:\n\n    suite\n    |_name\n    |_code\n    |_tests\n      |_description\n      |_definition\n      | |_nodes\n      | |_collector\n      | |_reporter\n      |\n      |_[flags]\n\nExample:\n\n```javascript\n[{\n  \"name\": \"Learning Udacity Feedback\",\n  \"code\": \"This can be an encouraging message\",\n  \"tests\": [\n    {\n      \"description\": \"Test 1 has correct bg color\",\n      \"definition\": {\n        \"nodes\": \".test1\",\n        \"cssProperty\": \"backgroundColor\",\n        \"equals\": \"rgb(204, 204, 255)\"\n      }\n    }\n  ]\n},\n{\n  \"name\": \"More 'dacity Feedback\",\n  \"code\": \"Some message\",\n  \"tests\": [\n    {\n      \"description\": \"Test 2 says 'Hello, world!'\",\n      \"definition\": {\n        \"nodes\": \".test2\",\n        \"get\": \"innerHTML\",\n        \"hasSubstring\": \"^Hello, world!$\"\n      }\n    },\n    {\n      \"description\": \"Test 3 has two columns\",\n      \"definition\": {\n        \"nodes\": \".test4\",\n        \"get\": \"count\",\n        \"equals\": 2\n      }\n    },\n    {\n      \"description\": \"Test 4 has been dispatched\",\n      \"definition\": {\n        \"waitForEvent\": \"ud-test\",\n        \"exists\": true\n      },\n      \"flags\": {\n        \"noRepeat\": true\n      }\n    }\n  ]\n}]\n```\n\n*Note that the feedback JSON must be an array of objects*\n\n* `\"name\"`: the name of the suite. The word \"Test\" or \"Tests\" gets appended when this name shows up in the widget as a heading for its child tests.\n* `\"code\"`: a message to display when all tests in the suite pass. Why is it called a code? It's sometimes the code I make students copy and paste into a quiz on the Udacity site to prove they finished the quiz.\n* `\"tests\"`: an array of test objects\n  * `\"description\"`: shows up in the test widget. Try to keep titles short, as long titles don't wrap well in the current version.\n  * `\"definition\"`: an object with collector and reporter properties. More on this below.\n  * `\"flags\"`: optional flags to alter the way a test is run. The most common is `noRepeat`, which ensures that a test runs only once rather than repeatedly.\n\n### How to write a `\"definition\"`\n\nThink about this sentence as you write tests:\n\n> I want the nodes of [selector] to have [some property] that [compares to some value].\n\n#### 1) Start with `\"nodes\"`. Most* tests against the DOM need some nodes to examine. This is the start of a \"collector\".\n\n```javascript\n\"definition\": {\n  \"nodes\": \"selector\",\n  ...\n}\n```\n\n**Exceptions: collecting a user-agent string, device pixel ratio, or in conjunction with `\"waitForEvent\"`.*\n\n#### 2) Decide what value you want to collect and test.\n\n**CSS:**\n\n```javascript\n\"definition\": {\n  \"nodes\": \".anything\"\n  \"cssProperty\": \"backgroundColor\",\n  ...\n}\n```\n\nThe `\"cssProperty\"` can be the camelCase version of [any CSS property](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Properties_Reference). `\"cssProperty\"` takes advantage of `window.getComputedStyle()`.\n\n* Colors will be returned in the form of `\"rgb(255, 255, 255)\"`. Note the spaces.\n* All `width`, `margin`, etc measurements are returned as pixel values, not percentages.\n\n**Attribute:**\n\n```javascript\n\"definition\": {\n  \"nodes\": \"input\"\n  \"attribute\": \"for\",\n  ...\n}\n```\n\nAny attribute works.\n\n**Absolute Position:**\n\n```javascript\n\"definition\": {\n  \"nodes\": \".left-nav\"\n  \"absolutePosition\": \"side\",\n  ...\n}\n```\n\nSide must be one of: `top`, `left`, `bottom`, or `right`. Currently, the position returned is relative to the **viewport**.\n\n**Count, innerHTML, ChildPosition, UAString (user-agent string), DPR (device pixel ratio):**\n\n```javascript\n\"definition\": {\n  \"nodes\": \".box\"\n  \"get\": \"count\",\n  ...\n}\n```\n\nThese tests (`\"count\"`, `\"innerHTML\"`, `\"childPositions\"`, `\"UAString\"`, `\"DPR\"`) use `\"get\"` and they are the only tests that use `\"get\"`. Remember the asterix from earlier about the necessity of `\"nodes\"`? Device pixel ratios and user-agent strings are exceptions - you can `\"get\": \"UAString\"` or `\"get\": \"DPR\"` without `\"nodes\"`.\n\n\"Child position? I haven't seen anything about children.\" - a question you might be asking yourself. Let me answer it.\n\n**Children**\n\n```javascript\n\"definition\": {\n  \"nodes\": \".flex-container\",\n  \"children\": \"div\",\n  \"absolutePosition\": \"side\",\n  ...\n}\n```\n\n`\"children\"` is a deep children selector.\n\nIn this example, it was used to select all the divs inside a flex container. Now, reporters will run tests against all of the child divs, not the parent flex container.\n\n#### 3) Decide how you want to grade the values you just collected. This is a \"reporter\".\n\n**Equals**\n\n```javascript\n\"definition\": {\n  \"nodes\": \".flex\",\n  \"get\": \"count\",\n  \"equals\": 4\n}\n```\n \nor\n\n```javascript\n\"definition\": {\n  \"nodes\": \"input.billing-address\",\n  \"attribute\": \"for\",\n  \"equals\": \"billing-address\"\n}\n```\n\nor\n\n```javascript\n\"definition\": {\n  \"nodes\": \".inline\",\n  \"cssProperty\": \"display\",\n  \"equals\": [\n    \"inline\",\n    \"inline-block\"\n  ]\n}\n\n```\n\nSet the `\"equals\"` value to a string, a number, or an array of strings and numbers.\n\nThis test looks for a strict equality match of either the value or one of the values in the array. In the first example, the test passes when the count of nodes returned by the selector equals four. In the second, the `for` attribute of `<input class=\"billing-address\">` must be set to `\"billing-address\"`. In the third example, the test passes if `display` is either `inline` or `inline-block`.\n\nIf you want to compare strings and would prefer to use regex, try `\"hasSubstring\"`.\n\n**Exists**\n\n```javascript\n\"definition\": {\n  \"nodes\": \"input.billing-address\",\n  \"attribute\": \"for\",\n  \"exists\": true\n}\n```\n\nIn this example, rather than looking for a specific `for`, I'm just checking to see that it exists at all. The value doesn't matter. If `\"exists\": false`, then the test will only pass if the attribute does not exist.\n\n**Comparison**\n\n```javascript\n\"definition\": {\n  \"nodes\": \".flex\",\n  \"get\": \"count\",\n  \"isLessThan\": 4\n}\n```\n\n`\"isLessThan\"` and `\"isGreaterThan\"` share identical behavior.\n\n```javascript\n  \"definition\": {\n    \"nodes\": \".flex\",\n    \"get\": \"count\",\n    \"isInRange\": {\n      \"lower\": 4,\n      \"upper\": 10\n    }\n  }\n```\n\nSet an `\"upper\"` and a `\"lower\"` value for `\"isInRange\"`.\n\n**Substrings**\n\n```javascript\n\"definition\": {\n  \"nodes\": \".text\",\n  \"get\": \"innerHTML\",\n  \"hasSubstring\": \"([A-Z])\\w+\"\n}\n```\n\nRun regex tests against strings with `\"hasSubstring\"`. If one or more match groups are returned, the test passes.\n\n**NOTE**: you must escape `\\`s! eg. `\\wHello` will break, but `\\\\wHello` will work.\n\nYou can pass an array to `\"hasSubstring\"` if you want to match one regex out of many.\n\n```javascript\n\"definition\": {\n  \"nodes\": \".text\",\n  \"get\": \"innerHTML\",\n  \"hasSubstring\": [\"([A-Z])\\w+\", \"([a-z])\\w+\"]\n}\n```\n\nThere is an alternate syntax with optional configs for `\"hasSubstring\"`.\n\n```javascript\n\"definition\": {\n  \"nodes\": \".text\",\n  \"get\": \"innerHTML\",\n  \"hasSubstring\": {\n    \"expected\": [\n      \"([A-Z])\\\\w+\",\n      \"$another^\"\n    ],\n    \"minValues\": 1,\n    \"maxValues\": 2\n  }\n}\n```\n\nThis test checks that either one or both of the expected values are found.\n\nIf you set `\"hasSubstring\"` to an object with an array of `\"expected\"` regexes, you can optionally use `\"minValues\"` and `\"maxValues\"` to determine how many of the expected values need to match in order for the test to pass. Unless otherwise specified, only one value from the `\"expected\"` array will need to be matched in order for the test to pass.\n\n**Utility Properties - `not`, `limit`**\n\n```javascript\n\"definition\": {\n  \"nodes\": \".text\",\n  \"get\": \"innerHTML\",\n  \"not\": true,\n  \"hasSubstring\": \"([A-Z])\\\\w+\"\n}\n```\n\nSwitch behavior with `\"not\"`. A failing test will now pass and vice versa.\n\n```javascript\n\"definition\": {\n  \"nodes\": \".title\",\n  \"cssProperty\": \"marginTop\",\n  \"limit\": 1,\n  \"equals\": 10\n}\n```\n\nCurrently, the values supported by `\"limit\"` are any number >= 1, `\"all\"` (default), and `\"some\"`.\n\nRemember, by default every node collected by `\"nodes\"` or `\"children\"` must pass the test specified. To change that, use `\"limit\"`. If it is any number, `0 < numberCorrect <= limit` values must pass in order for the test to pass. If more than one value passes, the test fails. In the case of `\"some\"`, one or more values must pass in order for the test to pass.\n\n**Flags**\n\n```javascript\n\"definition\": {\n  \"nodes\": \".small\",\n  \"cssProperty\": \"borderLeft\",\n  \"equals\": 10\n},\n\"flags\": {\n  \"noRepeat\": true\n}\n```\n\nOptions here currently include `\"noRepeat\"` and `\"alwaysRun\"`.\n\nBy default, a test runs every 1000ms until it either passes or encounters an error. If `\"noRepeat\"` is set, the test only runs once when the widget loads and does not rerun every 1000ms. If `\"alwaysRun\"`, the test continues to run even after it passes.\n\n###<a name=\"js-tests\"></a> JavaScript Tests\n\n```javascript\n\"definition\": {\n  \"waitForEvent\": \"custom-event\",\n  \"exists\": true\n}\n```\n\nFor security reasons, you can only run JavaScript tests against pages that you control. You can trigger tests by dispatching custom events from inside your application or from a script linked in the `unit-tests` attribute of the meta tag. Set `\"waitForEvent\"` to a custom event. As soon as the custom event is detected, the test passes.\n\nExample of a custom event:\n\n```javascript\nwindow.dispatchEvent(new CustomEvent('ud-test', {'detail': 'passed'}));\n```\n\nI like to use the [jsgrader library](https://github.com/udacity/js-grader) for writing JS tests because it supports grading checkpoints (logic to say \"stop grading if this test fails\"). You can use it too by setting `libraries=\"jsgrader\"` in the meta tag.].\n\n### Test States and Debugging\n\n![wrong answer, right answer, error](images/wrong-right-error.png)\n\nGreen tests with ✓ have passed, red tests with ✗ have failed and yellow tests with ?? have some kind of error. If there is an error, run `UdacityFEGradingEngine.debug();` from the console to see why the yellow tests are erring.\n\nYou can find an options page in chrome://extensions. Use the options page to see and modify the list of domains on which the extension will run.\n\n## How Udacity Feedback Works\n\nAt the core of Udacity Feedback is the grading engine. The grading engine performs two tasks: collecting information from the DOM and reporting on it. Each test creates its own instance of the grading engine which queries the DOM once a second (unless otherwise specified).\n\n### Overview of the source code:\n\n* **TA** (Teaching Assistant). The TA orchestrates the DOM querying and comparison logic of the grading engine. There is a collection aspect (src/js/TACollectors.js) and a reporting aspect (src/js/TAReporters.js). Collectors pull info from the DOM. Reporters are responsible for the logic of evaluating the information. The TA executes tests as a series of async methods pulled from a Queue.\n* **Gradebook**. Every TA has an instance of a Gradebook, which determines the pass/fail state of a test. Some tests have multiple parts (eg. examining every element of some class to ensure that all have a blue background - each element is a part of the test). The Gradebook compares the parts to the comparison functions as set by the TA and decides if the test has passed or failed.\n* **Target**. A Target represents a single piece of information pulled from the DOM. *Almost* every Target has an associated `element` and some `value`. Targets may include child Targets. Tests that result in multiple pieces of information create a tree of Targets (sometimes called a 'Bullseye' in comments).\n* **Suite** and **ActiveTest**. An individual test (ie. one line in the widget) is an instance of an ActiveTest. ActiveTests are organized into Suites. Each Suite comes with its own name, which is displayed above its set of tests in the widget.\n* **Registrar**. This file contains the logic for creating new tests when the Feedback is turned on and removing tests when the Feedback is turned off.\n* The `<test-widget>` and everything inside of it were built as custom elements with HTML imports.\n\n### Development Workflow\n\n1. Run `gulp watch` from `/`\n2. Make changes.\n3. Open `/sample/index.html` to run regression testing.\n4. If you're adding a new feature:\n  * Add new passing and failing tests to `/sample/tests.json` (and modify `/sample/index.html` if necessary).\n  * Update this README to reflect changes (include examples!).\n5. Submit a pull request!\n\nDid you read this far? You're awesome :)\n\n # Archival Note \n This repository is deprecated; therefore, we are going to archive it. However, learners will be able to fork it to their personal Github account but cannot submit PRs to this repository. If you have any issues or suggestions to make, feel free to: \n- Utilize the https://knowledge.udacity.com/ forum to seek help on content-specific issues. \n- Submit a support ticket along with the link to your forked repository if (learners are) blocked for other reasons. Here are the links for the [retail consumers](https://udacity.zendesk.com/hc/en-us/requests/new) and [enterprise learners](https://udacityenterprise.zendesk.com/hc/en-us/requests/new?ticket_form_id=360000279131)."
  },
  {
    "path": "chromium/README.md",
    "content": "## Chromium interface\n### Description\nThis directory contains files needed to build the extension for Chromium based browsers (Google Chrome).\n\n### Prerequisites\nChrome natively support the WebExtensions API. Really old versions may even be supported.\n\n### License\nThis directory and the whole project is subject to the [GPLv3 License](../license).\n"
  },
  {
    "path": "chromium/browser_action/intro.js",
    "content": "/**\n * @fileOverview This file contains the Chromium opening statements for the browser action script prepended to the main file.\n * @name intro.js<browser_action>\n * @author Etienne Prud’homme\n * @license GPLv3\n */\n\n// intro.js<browser_action> ends here\n"
  },
  {
    "path": "chromium/browser_action/outro.js",
    "content": "/**\n * @fileOverview This file contains the Chromium closing statements for the browser action script appended to the main file.\n * @name outro.js<browser_action>\n * @author Etienne Prud’homme\n * @license GPLv3\n */\n\n// outro.js<browser_action> ends here\n// browser_action.js ends here\n"
  },
  {
    "path": "chromium/inject/intro.js",
    "content": "/**\n * @fileOverview This file contains the Chromium opening statements for the content script prepended to the main file.\n * @name intro.js<inject>\n * @author Etienne Prud’homme\n * @license GPLv3\n */\n\n// intro.js<browser_action> ends here\n"
  },
  {
    "path": "chromium/inject/outro.js",
    "content": "/**\n * @fileOverview This file contains the Chromium closing statements for the content script appended to the main file.\n * @name intro.js<inject>\n * @author Etienne Prud’homme\n * @license GPLv3\n */\n\n// outro.js<inject> ends here\n// inject.js ends here\n"
  },
  {
    "path": "chromium/manifest.json",
    "content": "{\n  \"name\": \"Udacity Front End Feedback\",\n  \"short_name\": \"Udacity Feedback\",\n  \"version\": \"0.3.0\",\n  \"manifest_version\": 2,\n  \"description\": \"Immediate, visual feedback about any website's HTML, CSS and JavaScript\",\n  \"homepage_url\": \"http://github.com/udacity/frontend-grading-engine\",\n  \"icons\": {\n    \"16\": \"icons/icon.png\",\n    \"32\": \"icons/Icon-32.png\",\n    \"48\": \"icons/Icon-48.png\",\n    \"64\": \"icons/Icon-64.png\",\n    \"128\": \"icons/Icon-128.png\"\n  },\n  \"options_page\": \"app/options/index.html\",\n  \"browser_action\": {\n    \"default_icon\": \"icons/Icon-48.png\",\n    \"default_title\": \"Udacity Feedback\",\n    \"default_popup\": \"app/browser_action/browser_action.html\"\n  },\n  \"permissions\": [\n    \"tabs\",\n    \"storage\"\n  ],\n  \"content_scripts\": [\n    {\n      \"matches\": [\n        \"http://*/*\",\n        \"https://*/*\",\n        \"file://*/*\"\n      ],\n      \"js\": [\n        \"app/js/inject.js\"\n      ]\n    }\n  ],\n  \"web_accessible_resources\": [\n    \"app/js/*.js\",\n    \"app/js/libs/GE.js\",\n    \"app/js/libs/jsgrader.js\",\n    \"app/templates/templates.js\",\n    \"lib/components.js\"\n  ]\n}\n"
  },
  {
    "path": "chromium/options/intro.js",
    "content": "/**\n * @fileOverview This file contains the Chromium opening statements for the options page script prepended to the main file.\n * @name intro.js<options>\n * @author Etienne Prud’homme\n * @license GPLv3\n */\n\nvar browserName = 'Chrome';\n\n// intro.js<options> ends here\n"
  },
  {
    "path": "chromium/options/outro.js",
    "content": "/**\n * @fileOverview This file contains the Chromium closing statements for the options page script appended to the main file.\n * @name outro.js<options>\n * @author Etienne Prud’homme\n * @license GPLv3\n */\n\n// outro.js<options> ends here\n// options.js ends here\n\n"
  },
  {
    "path": "firefox/README.md",
    "content": "## Firefox interface\n### Description\nThis directory contains files needed to build the extension for Firefox based browsers (may include IceWeasel or IceCat).\n\nWhile the WebExtensions API is well supported in Chromium, Firefox needs to have specific quirks.\n\n### Incompatibilities\nBecause Firefox doesn’t yet support some features and that backward compatibility was preferred, here are some issues:\n\n* Firefox doesn’t support the `sync` `StorageArea` (i.e. `chrome.storage.sync.*`). A wrapper was made to instead `local` `StorageArea`.\n  - Before version 48, Firefox didn’t support the `chrome.storage` API in _content scripts_. The above wrapper is replaced with a message channel between the _event page_ (background page) and the _content script_.\n* Before version 48, Firefox didn’t support the _options page_ (or `options\\_ui`). An icon is added in the _action page_ to access a page to modify the settings. That’s currently the only way to access the options prior to version 48.\n\n* Firefox and Chromium don’t seem to handle promises the same way. For example, Firefox couldn’t load the JSON tests before the execution of unit tests.\n\n### Prerequisites\nFirefox 45 or higher is needed to support WebExtensions.\n\n### Building\n* TODO\n\n## License\nThis directory and the whole project is subject to the [GPLv3 License](../license).\n"
  },
  {
    "path": "firefox/background.js",
    "content": "/*global chrome */\n\n/**\n * @fileOverview This file adds support for the {@link chrome.storage.local} API in Firefox. This API isn’t implemented until Firefox version 48 for content-scripts.\n * @name background.js<firefox>\n * @author Etienne Prud’homme\n * @license GPLv3\n */\n\nchrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {\n  // debugger;\n  // console.group();\n  // console.log(\"sendResponse = \", sendResponse.toString());\n  // console.log(\"sender = \", sender);\n  // console.log(\"message = \", message);\n  // console.groupEnd();\n\n  if(!message)  {\n    Promise.reject();\n  }\n\n  switch(message.type) {\n  case 'chrome.storage.local.get':\n    chrome.storage.local.get(message.data, function(response) {\n      // debugger;\n      sendResponse(response);\n    });\n    break;\n\n  case 'chrome.storage.local.set':\n    chrome.storage.local.set(message.data, function(response) {\n      // debugger;\n      response = chrome.runtime.lastError ? {status: 1, error: chrome.runtime.lastError.message} : {status: 0};\n      sendResponse(response);\n    });\n    break;\n  };\n  return true;\n});\n\n// background.js<firefox> ends here\n"
  },
  {
    "path": "firefox/browser_action/intro.js",
    "content": "/*global chrome */\n\n/**\n * @fileOverview This file contains the Firefox opening statements for the browser action script prepended to the main file.\n * @name intro.js<browser_action>\n * @author Etienne Prud’homme\n * @license GPLv3\n */\n\nchrome.runtime.openOptionsPage = function() {\n  chrome.tabs.create({url: chrome.extension.getURL('app/options/index.html')});\n};\n\n// intro.js<browser_action> ends here\n"
  },
  {
    "path": "firefox/browser_action/outro.js",
    "content": "/**\n * @fileOverview This file contains the Firefox closing statements for the content script appended to the main file.\n * @name outro.js<browser_action>\n * @author Etienne Prud’homme\n * @license GPLv3\n */\n\n// outro.js<browser_action> ends here\n// browser_action.js ends here\n"
  },
  {
    "path": "firefox/inject/intro.js",
    "content": "/*global chrome */\n\n/**\n * @fileOverview This file contains the Firefox opening statements for the content script prepended to the main file.\n * @name intro.js<inject>\n * @author Etienne Prud’homme\n * @license GPLv3\n */\n\n// chrome = browser;\nchrome.storage = {\n  sync: {\n    /**\n     * Gets one or more items from storage.\n     * @param {string|string[]|object} [keys] - A single key to get, list of keys to get, or a dictionary specifying default values (see description of the object). An empty list or object will return an empty result object. Pass in null to get the entire contents of storage\n     * @param {function} callback - Callback with storage items, or on failure (in which case runtime.lastError will be set).\n     */\n    get: function(keys, callback) {\n      // debugger;\n      // console.log(callback);\n      // console.log(callback.toString());\n      var message = {};\n      message.data = keys;\n      message.type = 'chrome.storage.local.get';\n\n      chrome.runtime.sendMessage(null, message, {}, localHandleGet);\n\n      function localHandleGet(response) {\n        // debugger;\n        // console.log('localHandleGet');\n        callback(response);\n      }\n    },\n    set: function(object, callback) {\n      // debugger;\n      // console.log(\"chrome.storage.sync.set object = \", object);\n      var message = {};\n\n      message.type = 'chrome.storage.local.set';\n      message.data = object;\n      chrome.runtime.sendMessage(null, message, {}, localHandleSet);\n      function localHandleSet(response) {\n        // debugger;\n        // console.log('localHandleSet');\n        if(response.status) {\n          throw new Error('Error: ' + response.message);\n        }\n        callback();\n      }\n    }\n  }\n};\n\n// intro.js<inject> ends here\n"
  },
  {
    "path": "firefox/inject/outro.js",
    "content": "/**\n * @fileOverview This file contains the Firefox closing statements for the content script appended to the main file.\n * @name intro.js<inject>\n * @author Etienne Prud’homme\n * @license GPLv3\n */\n\n// outro.js<inject> ends here\n// inject.js ends here\n"
  },
  {
    "path": "firefox/manifest.json",
    "content": "{\n  \"name\": \"Udacity Front End Feedback\",\n  \"version\": \"0.3.0\",\n  \"applications\": {\n    \"gecko\": {\n      \"id\": \"udacityfeedback@udacity.com\",\n      \"strict_min_version\": \"45.0\"\n    }\n  },\n  \"manifest_version\": 2,\n  \"description\": \"Immediate, visual feedback about any website's HTML, CSS and JavaScript\",\n  \"homepage_url\": \"http://github.com/udacity/frontend-grading-engine\",\n  \"icons\": {\n    \"16\": \"icons/icon.png\",\n    \"32\": \"icons/Icon-32.png\",\n    \"48\": \"icons/Icon-48.png\",\n    \"64\": \"icons/Icon-64.png\",\n    \"128\": \"icons/Icon-128.png\"\n  },\n  \"options_ui\": {\n    \"page\": \"app/options/index.html\"\n  },\n  \"browser_action\": {\n    \"default_icon\": \"icons/Icon-48.png\",\n    \"default_title\": \"Udacity Feedback\",\n    \"default_popup\": \"app/browser_action/browser_action.html\"\n  },\n  \"background\": {\n    \"scripts\": [\"background.js\"]\n  },\n  \"permissions\": [\n    \"tabs\",\n    \"storage\"\n  ],\n  \"content_scripts\": [\n    {\n      \"matches\": [\n        \"http://*/*\",\n        \"https://*/*\",\n        \"file://*/*\"\n      ],\n      \"js\": [\n        \"app/js/inject.js\"\n      ]\n    }\n  ],\n  \"web_accessible_resources\": [\n    \"app/css/common.css\",\n    \"app/css/fonts/fontawesome-webfont.ttf\",\n    \"app/js/libs/GE.js\",\n    \"app/js/libs/jsgrader.js\",\n    \"app/templates/templates.js\",\n    \"lib/components.js\"\n  ]\n}\n"
  },
  {
    "path": "firefox/options/intro.js",
    "content": "/*global chrome, browser */\n\n/**\n * @fileOverview This file contains the Firefox opening statements for the options page script prepended to the main file.\n * @name intro.js<options>\n * @author Etienne Prud’homme\n * @license GPLv3\n */\n\nvar browserName = 'Firefox';\n\nchrome = browser;\nchrome.storage = {\n  sync: {\n    /**\n     * Gets one or more items from storage.\n     * @param {string|string[]|object} [keys] - A single key to get, list of keys to get, or a dictionary specifying default values (see description of the object). An empty list or object will return an empty result object. Pass in null to get the entire contents of storage\n     * @param {function} callback - Callback with storage items, or on failure (in which case runtime.lastError will be set).\n     * @returns {}\n     */\n    get: function(keys, callback) {\n      // debugger;\n      // console.log(callback);\n      // console.log(callback.toString());\n      var message = {};\n      message.data = keys;\n      message.type = 'chrome.storage.local.get';\n\n      chrome.runtime.sendMessage(null, message, {}, localHandleGet);\n\n      function localHandleGet(response) {\n        // debugger;\n        // console.log('localHandleGet');\n        callback(response);\n      }\n    },\n    set: function(object, callback) {\n      // debugger;\n      // console.log(\"chrome.storage.sync.set object = \", object);\n      var message = {};\n\n      message.type = 'chrome.storage.local.set';\n      message.data = object;\n      chrome.runtime.sendMessage(null, message, {}, localHandleSet);\n      function localHandleSet(response) {\n        // debugger;\n        // console.log('localHandleSet');\n        if(response.status) {\n          throw new Error('Error: ' + response.message);\n        }\n        callback();\n      }\n    }\n  }\n};\n\n// intro.js<options> ends here\n"
  },
  {
    "path": "firefox/options/outro.js",
    "content": "/**\n * @fileOverview This file contains the Firefox closing statements for the options page script appended to the main file.\n * @name outro.js<options>\n * @author Etienne Prud’homme\n * @license GPLv3\n */\n\n// outro.js<options> ends here\n// options.js ends here\n"
  },
  {
    "path": "gulpfile.js",
    "content": "var gulp = require('gulp');\nvar gulpsync = require('gulp-sync')(gulp);\nvar watch = require('gulp-watch');\nvar concat = require('gulp-concat');\nvar debug = require('gulp-debug');\nvar batch = require('gulp-batch');\n// var uglify = require('gulp-uglify');\nvar clean = require('gulp-clean');\nvar mv = require('mv');\n\nvar currentBrowser;\n\nvar build = './build/%target%/ext/';\n\nvar log = function(message) {\n  console.log('\\x1b[37;46m####       ' + message + '\\x1b[0;m');\n};\n\nfunction setBrowser(browser) {\n  currentBrowser = browser;\n  return log('Set ' + currentBrowser + ' as the current browser');\n}\n\nvar pageFiles = {\n  gradingEngine: {\n    src: [\n      'src/js/intro.js',\n      'src/js/helpers.js',\n      'src/js/Queue.js',\n      'src/js/Target.js',\n      'src/js/GradeBook.js',\n      'src/js/TACollectors.js',\n      'src/js/TAReporters.js',\n      'src/js/ActiveTest.js',\n      'src/js/Suite.js',\n      'src/js/registrar.js',\n      'src/js/outro.js'\n    ],\n    libraries: {\n      src: 'src/app/js/libs/*.js',\n      dest: build + 'app/js/libs/'\n    },\n    concat: 'GE.js',\n    dest: build + 'app/js/libs/'\n  },\n  libraries: {\n    src: 'lib/*',\n    dest: build + 'lib/'\n  },\n  background: {\n    js: {\n      src: [\n        '%target%/background.js'\n      ],\n      concat: 'background.js'\n    },\n    dest: build\n  },\n  inject: {\n    src: [\n      '%target%/inject/intro.js',\n      'src/app/js/inject/helpers.js',\n      'src/app/js/inject/StateManager.js',\n      'src/app/js/inject/inject.js',\n      '%target%/inject/outro.js'\n    ],\n    concat: 'inject.js',\n    dest: build + 'app/js/'\n  },\n  templates: {\n    src: [\n      'src/app/test_widget/font.js',\n      'src/app/test_widget/test_suite.js',\n      'src/app/test_widget/test_results.js',\n      'src/app/test_widget/active_test.js',\n      'src/app/test_widget/test_widget.js'\n    ],\n    concat: 'templates.js',\n    dest: build + 'app/templates/'\n  },\n  // Safari background script\n  globalPage: {\n    js: {\n      src: [\n        '%target%/background/helpers.js',\n        '%target%/background/registry.js',\n        '%target%/background/adapter.js',\n        '%target%/background/adapterListener.js',\n        '%target%/background/background.js'\n      ],\n      concat: 'background.js'\n    },\n    html: {\n      src: [\n        '%target%/background/background.html'\n      ],\n      concat: 'background.html'\n    },\n    dest: build\n  }\n};\n\nvar gradingEngine = pageFiles.gradingEngine;\n// Third-party libraries\nvar libraries = pageFiles.libraries;\nvar geLibs = gradingEngine.libraries;\nvar background = pageFiles.background;\nvar global = pageFiles.globalPage;\nvar inject = pageFiles.inject;\nvar templates = pageFiles.templates;\n\nvar browserPageFiles = {\n  pageAction: {\n    html: 'src/app/browser_action/browser_action.html',\n    js: {\n      src: [\n        '%target%/browser_action/intro.js',\n        'src/app/browser_action/browser_action.js',\n        '%target%/browser_action/outro.js'\n      ],\n      concat: 'browser_action.js'\n    },\n    dest: build + 'app/browser_action/'\n  },\n  pageOptions: {\n    html: 'src/app/options/index.html',\n    js: {\n      src: [\n        '%target%/options/intro.js',\n        'src/app/options/options.js',\n        '%target%/options/outro.js'\n      ],\n      concat: 'options.js'\n    },\n    dest: build + 'app/options/'\n  }\n};\nvar pageAction = browserPageFiles.pageAction;\nvar pageOptions = browserPageFiles.pageOptions;\n\nvar iconFiles = {\n  src: [\n    'src/icons/icon.png',\n    'src/icons/Icon-32.png',\n    'src/icons/Icon-48.png',\n    'src/icons/Icon-64.png',\n    'src/icons/Icon-128.png'\n  ],\n  dest: build + 'icons/'\n};\n\nvar styleFiles = {\n  src: [\n    'src/app/css/common.css',\n    'src/app/css/fonts.css',\n    'src/app/css/ui.css',\n    'src/app/css/options.css'\n  ],\n  dest: build + 'app/css/'\n};\n\nvar fontFiles = {\n  src: 'src/app/css/fonts/fontawesome-webfont.ttf',\n  dest: build + 'app/css/fonts/'\n};\n\n// Files to watch\nvar allFiles = gradingEngine.src.concat(templates.src, inject.src, background.js.src, global.js.src);\n\n// \"GE\" = Build the GradingEngine library.\ngulp.task('GE', function() {\n  return gulp.src(gradingEngine.src)\n    .pipe(concat(gradingEngine.concat))\n    .pipe(gulp.dest(gradingEngine.dest))\n    .pipe(debug({title: 'built the grading engine:'}));\n});\n\n// \"GE_libs\" = Copy libraries of the Grading Engine.\ngulp.task('GE_libs', function() {\n  return gulp.src(geLibs.src)\n    .pipe(gulp.dest(geLibs.dest))\n    .pipe(debug({title: 'copied grading engine libraries:'}));\n});\n\n// \"libraries\" = Copy third-party libraries.\ngulp.task('libraries', function() {\n  return gulp.src(libraries.src)\n    .pipe(gulp.dest(libraries.dest))\n    .pipe(debug({title: 'copied libraries:'}));\n});\n\n// \"templates\" = Generate the native templates. There were\n// previously Web Templates.\ngulp.task('templates', function() {\n  return gulp.src(templates.src)\n    .pipe(concat(templates.concat))\n    .pipe(gulp.dest(templates.dest))\n    .pipe(debug({title: 'built templates: '}));\n});\n\n// \"inject\" = Generate the inject script for the current browser and copy.\ngulp.task('inject', function() {\n  var files = inject.src.map(function(x) {\n    return x.replace('%target%', currentBrowser);\n  });\n  return gulp.src(files)\n    .pipe(concat(inject.concat))\n    .pipe(gulp.dest(inject.dest))\n    .pipe(debug({title: 'built inject.js:'}));\n});\n\n/*** PAGEACTION ***/\n// \"_pageAction_html\" = Copy HTML options page.\ngulp.task('_pageAction_html', function() {\n  return gulp.src(pageAction.html)\n    .pipe(gulp.dest(pageAction.dest))\n    .pipe(debug({title: 'copied action page:'}));\n});\n\n// \"_pageAction_js\" = Generate the pageAction script for the current browser and copy.\ngulp.task('_pageAction_js', function() {\n  var files = pageAction.js.src.map(function(x) {\n    return x.replace('%target%', currentBrowser);\n  });\n  return gulp.src(files)\n    .pipe(concat(pageAction.js.concat))\n    .pipe(gulp.dest(pageAction.dest))\n    .pipe(debug({title: 'built action page script:'}));\n});\n\n// \"pageAction\" = Copy the `browser_action` files.\ngulp.task('pageAction', ['_pageAction_html', '_pageAction_js']);\n/*** PAGEACTION ends here ***/\n\n/*** PAGEOPTIONS ***/\n// \"_pageOptions_html\" = Copy HTML options page.\ngulp.task('_pageOptions_html', function() {\n  return gulp.src(pageOptions.html)\n    .pipe(gulp.dest(pageOptions.dest))\n    .pipe(debug({title: 'copied options page:'}));\n});\n\n// \"_pageOptions_js\" = Generate the pageAction script for the current browser and copy.\ngulp.task('_pageOptions_js', function() {\n  var files = pageOptions.js.src.map(function(x) {\n    return x.replace('%target%', currentBrowser);\n  });\n  return gulp.src(files)\n    .pipe(concat(pageOptions.js.concat))\n    .pipe(gulp.dest(pageOptions.dest))\n    .pipe(debug({title: 'built options page script:'}));\n});\n\n// \"pageOptions\" = Copy the options page.\ngulp.task('pageOptions', ['_pageOptions_html', '_pageOptions_js']);\n/*** PAGEOPTIONS ends here ***/\n\n\n// \"icons\" = Copy icons.\ngulp.task('icons', function() {\n  if(currentBrowser === 'safari') {\n    iconFiles.src.push('safari/toolbar_icon.png');\n    iconFiles.dest = build;\n  }\n  return gulp.src(iconFiles.src)\n    .pipe(gulp.dest(iconFiles.dest))\n    .pipe(debug({title: 'copied icons:'}));\n});\n\n// \"styles\" = Copy styles.\ngulp.task('styles', function() {\n  return gulp.src(styleFiles.src)\n    .pipe(gulp.dest(styleFiles.dest))\n    .pipe(debug({title: 'copied styles:'}));\n});\n\n// \"fonts\" = Copy fonts.\ngulp.task('fonts', function() {\n  return gulp.src(fontFiles.src)\n    .pipe(gulp.dest(fontFiles.dest))\n    .pipe(debug({title: 'copied fonts:'}));\n});\n\n// \"assets\" = Executes tasks for static assets.\ngulp.task('assets', ['icons', 'styles', 'fonts']);\n\n// \"app\" = Executes tasks for the app (view).\ngulp.task('app', ['templates', 'inject', 'pageAction', 'pageOptions', 'assets']);\n\n// \"extension\" = Executes tasks that are mostly not browser specific.\ngulp.task('extension', ['app', 'GE', 'GE_libs', 'libraries']);\n\n// \"background-script\" = Copy the background script for the\n// `currentBrowser` (if any).\ngulp.task('background-script', function() {\n  var _background = currentBrowser === 'safari' ? global : background;\n  _background.js.src = _background.js.src.map(function(x) {\n    return x.replace('%target%', currentBrowser);\n  });\n  log(_background);\n  return gulp.src(_background.js.src)\n    .pipe(concat(_background.js.concat))\n    .pipe(gulp.dest(_background.dest))\n    .pipe(debug({title: 'copied ' + currentBrowser + '’s background script:'}));\n});\n\n// \"background-page\" = Copy the background page for the\n// `currentBrowser` (if any).\ngulp.task('background-page', function() {\n  var _background = currentBrowser === 'safari' ? global : background;\n  _background.html.src = _background.html.src.map(function(x) {\n    return x.replace('%target%', currentBrowser);\n  });\n  return gulp.src(_background.html.src)\n    .pipe(concat(_background.html.concat))\n    .pipe(gulp.dest(_background.dest))\n    .pipe(debug({title: 'copied ' + currentBrowser + '’s background page:'}));\n});\n\n// \"manifest\" = Copy the manifest for the current browser\ngulp.task('manifest', function() {\n  // Safari doesn’t have a `manifest.json`, but an `Info.plist`\n  var manifest = currentBrowser === 'safari' ? 'Info.plist' : 'manifest.json';\n  return gulp.src(currentBrowser + '/' + manifest)\n    .pipe(gulp.dest(build))\n    .pipe(debug({title: 'copied ' + currentBrowser +'’s manifest:'}));\n});\n\n// \"_chromium\" = Sets currentBrowser to chromium.\ngulp.task('_chromium', function() {\n  return setBrowser('chromium');\n});\n\n// \"_firefox\" = Sets currentBrowser to firefox\ngulp.task('_firefox', function() {\n  return setBrowser('firefox');\n});\n\n// \"_safari\" = Sets currentBrowser to safari\ngulp.task('_safari', function() {\n  return setBrowser('safari');\n});\n\n// \"move-build\" = Move build files to its target directory.\ngulp.task('move-build', function() {\n  var browserBuild = build.replace('%target%/ext/', currentBrowser + '/');\n  mv(build.replace('ext/', ''), browserBuild, {mkdirp: true}, function(err) {\n    console.log(err);\n  });\n  return log('Moved ' + currentBrowser + ' files to: ' + browserBuild);\n});\n\n// \"chromium\" = Run chromim dependencies to build the extension.\ngulp.task('chromium', gulpsync.sync(['_chromium', ['manifest', 'extension'], 'move-build']));\n\n// \"firefox\" = Run Firefox dependencies to build the extension.\ngulp.task('firefox', gulpsync.sync(['_firefox', ['manifest', 'background-script', 'extension'], 'move-build']));\n\n// \"safari\" = Run Safari dependencies to build the extension.\ngulp.task('safari', gulpsync.sync(['_safari', ['manifest', 'background-script', 'background-page', 'extension'], 'move-build']));\n\n// \"clean\" = Clean the build directory. Otherwise `mv` would throw an error.\ngulp.task('clean', function() {\n  log('Cleaned the build directory');\n  return gulp.src('./build/', {read: false})\n    .pipe(clean())\n    .pipe(debug({title: 'cleaned ' + build}));\n});\n\ngulp.task('default', gulpsync.sync(['clean', 'firefox', 'chromium', 'safari']));\n\ngulp.task('watch', function() {\n  gulp.start('default');\n  watch(allFiles, batch(function(events, done) {\n    gulp.start('default', done);\n  }));\n});\n"
  },
  {
    "path": "lib/components.js",
    "content": "/*global MutationObserver */\n/**\n * @fileOverview This file contains the /components/ module for emulating Web Components behavior.\n * @name components.js<src>\n * @author Etienne Prud’homme\n * @version 1.0.0\n * @link https://github.com/notetiene/components\n * @license GPLv3\n */\nvar components=function(){var e={},t=document.createRange();t.selectNode(document.body);var r=function(t,r,n){if(t.constructor!==String||\"\"===t)throw new Error(\"Cannot register the component. The name must be a String.\");if(r.constructor!==String||\"\"===r)throw new Error(\"Cannot register \"+t+\" component. The template must be a String.\");if(void 0!==e[t]&&e.hasOwnProperty(t))throw new Error(t+\" is an already registered component.\");var o=n||{};Object.defineProperty(e,t,{enumerable:!1,configurable:!1,writable:!1,value:{template:r,proto:o}})},n=function(r){if(!e.hasOwnProperty(r))throw new Error(\"“\"+r+\"” is not a registered component\");for(var n=e[r],o=t.createContextualFragment(n.template),a=null,i=0,c=o.childNodes.length;i<c;i++)if(8!==o.childNodes[i].nodeType){a=o.childNodes[i];break}if(null===a)throw new Error(\"The “\"+r+\"” component doesn’t contain a valid node.\");var l=n.proto.attachedCallback;if(l instanceof Function){var s=new MutationObserver(function(e){for(var t=0,r=e.length;t<r;t++)\"childList\"===e[t].type&&0===o.childNodes.length&&l.call(a)});s.observe(o,{childList:!0})}var u=n.proto.attributeChangedCallback;if(u instanceof Function){var d=new MutationObserver(function(e){for(var t=0,r=e.length;t<r;t++)\"attributes\"===e[t].type&&u.call(a)});d.observe(a,{attributes:!0})}return o};return{registerElement:r,createElement:n}}();"
  },
  {
    "path": "license",
    "content": "Copyright (c) 2015 Cameron Pittman\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and\nassociated documentation files (the \"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\nfollowing conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial\nportions of the Software.\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT\nNOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. I\nNO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHEHERIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE\nOR THE USE OR OTHER DEALINGS IN THE SOFTWARE."
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"frontend-grading-engine\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Udacity Front-End Grading Engine\",\n  \"main\": \"Gruntfile.js\",\n  \"dependencies\": {},\n  \"devDependencies\": {\n    \"gulp\": \"^3.9.0\",\n    \"gulp-batch\": \"^1.0.5\",\n    \"gulp-clean\": \"^0.3.2\",\n    \"gulp-concat\": \"^2.6.0\",\n    \"gulp-debug\": \"^2.0.1\",\n    \"gulp-install\": \"^0.4.0\",\n    \"gulp-sync\": \"^0.1.4\",\n    \"gulp-uglify\": \"^1.4.2\",\n    \"gulp-watch\": \"^4.3.5\",\n    \"mv\": \"^2.1.1\"\n  },\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/udacity/frontend-grading-engine.git\"\n  },\n  \"author\": \"Cameron Pittman\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/udacity/frontend-grading-engine/issues\"\n  },\n  \"homepage\": \"https://github.com/udacity/frontend-grading-engine\"\n}\n"
  },
  {
    "path": "safari/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n    <dict>\n        <key>Builder Version</key>\n        <string>11601.7.7</string>\n        <key>CFBundleDisplayName</key>\n        <string>Udacity Feedback</string>\n        <key>CFBundleIdentifier</key>\n        <string>com.udacity.frontend-grading-engine</string>\n        <key>CFBundleInfoDictionaryVersion</key>\n        <string>6.0</string>\n        <key>CFBundleShortVersionString</key>\n        <string>0.3.0</string>\n        <key>CFBundleVersion</key>\n        <string>0.3.0</string>\n        <key>Update From Gallery</key>\n        <true/>\n        <key>Chrome</key>\n        <dict>\n            <key>Global Page</key>\n            <string>background.html</string>\n            <key>Popovers</key>\n            <array>\n                <dict>\n                    <key>Filename</key>\n                    <string>app/browser_action/browser_action.html</string>\n                    <key>Identifier</key>\n                    <string>browserActionPage</string>\n                </dict>\n            </array>\n            <key>Toolbar Items</key>\n            <array>\n                <dict>\n                    <key>Identifier</key>\n                    <string>actionPageButton</string>\n                    <key>Image</key>\n                    <string>toolbar_icon.png</string>\n                    <key>Include By Default</key>\n                    <true/>\n                    <key>Label</key>\n                    <string>Udacity Feedback</string>\n                    <key>Popover</key>\n                    <string>browserActionPage</string>\n                    <key>Tool Tip</key>\n                    <string>Udacity Feedback</string>\n                </dict>\n            </array>\n        </dict>\n        <key>Content</key>\n        <dict>\n            <key>Scripts</key>\n            <dict>\n                <key>End</key>\n                <array>\n                    <string>app/js/inject.js</string>\n                </array>\n            </dict>\n        </dict>\n        <key>DeveloperIdentifier</key>\n        <string>AT7S4C746C</string>\n        <key>ExtensionInfoDictionaryVersion</key>\n        <string>1.0</string>\n        <key>Permissions</key>\n        <dict>\n            <key>Website Access</key>\n            <dict>\n                <key>Include Secure Pages</key>\n                <true/>\n                <key>Level</key>\n                <string>All</string>\n            </dict>\n        </dict>\n    </dict>\n</plist>\n"
  },
  {
    "path": "safari/README.md",
    "content": "## Safari Interface\n### Description\nThis directory contains files needed to build the extension for Safari. The goal is to make a WebExtension [adapter](https://en.wikipedia.org/wiki/Adapter_pattern) to reduce modification of the current code base.\n\n### Architecture\n#### Execution Context\n##### Injected Scripts\nThe extension API of Safari differs substantially from the WebExtension API. The extension architecture is similar to other browsers in that it allows scripts (injected script) to be injected with a limited API access. In that matter, it could be compared to _content scripts_. There’s one script instance per tab (depending on injection condition). Only injected scripts can have access to the DOM while getting a different global execution context other than the `window` object.\n\n##### Global Page\nThe extension allows to have an execution context with full access to the safari API (global page). However, this global execution context doesn’t have access to a webpage content (which is injected scripts’ role). The role of a _global page_ is to share its access of the API on demand. Injected scripts have to send a serialized message to the global page to trigger a custom action. Because it’s a message passing system, passed functions won’t be executed in their canonical way (not in their String representation).\n\n#### User Interface Components\nSafari has UI components that are similar to what WebExtension provides (e.g. _browser action_), but outside of the _browser action_ component, they differ significantly in their behaviour.\nPopovers have the same behaviour as _browser action_ page would. The global page _global executing context_ can be accessed with the `safari.extension.globalPage.contentWindow` namespace. To avoid making two adapters, the _global page_ adapter will be used.\n\n#### Safari Incompatibilities\n##### Storage\nSafari doesn’t support extension storage. Instead, we need to use the `safari.extension.settings` property to set an inner object representing the storage object to use.\n##### Tabs and Windows\nSafari doesn’t provide a method to uniquely identify a window or a tab. The adapter adds a module called `registry` that assign an ID to each window or tab. It also provides several functions to retrieve a list of tabs or windows.\n### License\nThis directory and the whole project is subject to the [GPLv3 License](../license).\n"
  },
  {
    "path": "safari/background/REAMDE.md",
    "content": "## Safari Global Page\n\nThe files in this directory get concatenated into `global.js`. It is somehow\nsimilar to what the WebExtensions background page does.\n\nBecause the Safari uses its own extension API, most of the work to port this\nextension to Safari is in providing a WebExtensions adapter.\n"
  },
  {
    "path": "safari/background/adapter.js",
    "content": "/*global registry, safari, extensionLog */\n\n/**\n * @fileOverview This file contains the adaptee (Adapter inner working) for emulating the WebExtension API.\n * @name adapter.js<background>\n * @author Etienne Prud’homme\n * @license GPLv3\n *\n * Injected Scripts don’t have access to the `chrome.*` API with the exception\n * of:\n * * `extension` (`getURL`, `inIncognitoContext`, `lastError`, `onRequest`,\n *    `sendRequest`)\n * * `i18n`\n * * `runtime` (`connect`, `getManifest`, `getURL`, `id`, `onConnect`,\n *    `onMessage`, `sendMessage`)\n * * `storage`\n *\n * This is wĥy this background script is created.\n */\n\n/**\n * Adaptee that translates chrome method behavior to safari.\n * @namespace\n * @property {error} wrapper.runtime.lastError - Set for the lifetime of a callback if an ansychronous extension api has resulted in an error. If no error has occured lastError will be undefined.\n */\nvar wrapper = {\n  storage: {\n    sync: {\n      /**\n       * Emulates the chrome storage behavior (getter) by using the {@link safari.extension.settings} mechanism.\n       * @param {string|string[]|object} keys - A single key to get, list of keys to get, or a dictionary specifying default values (see description of the object). An empty list or object will return an empty result object. Pass in null to get the entire contents of storage.\n       * @todo transform to a Promise\n       * @returns {object} Object with items in their key-value mappings.\n       * @throws {error} Error in the {@link keys} argument and sets {@link wrapper.runtime.lastError}.\n       */\n      get: function(keys) {\n        var i, len, key, items = {};\n        try {\n          if(!keys) {\n            if(keys === null) {\n              items = safari.extension.settings;\n            } else {\n              // Only `null` can return values, otherwise it’s an empty Object\n              items = {};\n            }\n          } else if(keys instanceof String || typeof keys === 'string') {\n            items[keys] = safari.extension.settings[keys];\n          } else if(keys instanceof Array && keys.length > 0) {\n            items = {};\n\n            for(i=0, len=keys.length; i<len; i++) {\n              key = keys[i];\n              if(!(key instanceof String || typeof key === 'string')) {\n                extensionLog(new Error('An item of the `keys` array wasn’t a String'));\n              }\n              items[key] = safari.extension.settings[key];\n            }\n          } else {\n            // Otherwise it can be any Objects with properties as keys.\n            items = {};\n            // Only a coincidence if they got the same names.\n            var value, keysArray = Object.keys(keys);\n\n            if(keysArray.length === 0) {\n              extensionLog(new Error('The `keys` object does not contain any property on its own'));\n            }\n\n            for(i=0, len=keysArray.length; i<len; i++) {\n              key = keysArray[i];\n              value = safari.extension.settings[key];\n              // Return the default value if the key isn’t present in settings\n              items[key] = value !== undefined ? value : keys[key];\n            }\n          }\n        } catch(e) {\n          wrapper.runtime.lastError = e;\n          items = -1;\n        }\n        return items;\n      },\n      /**\n       * Emulates the chrome storage behavior (setter) by using the {@link safari.extension.settings} mechanism.\n       * @param {} keys - An object which gives each key/value pair to update storage with. Any other key/value pairs in storage will not be affected.\n       * Primitive values such as numbers will serialize as expected. Values with a typeof `object` and `function` will typically serialize to `{}`, with the exception of `Array` (serializes as expected), Date, and Regex (serialize using their `String` representation).\n       * @returns {int} 0 on success and -1 on error.\n       * @throws {error} Error in the {@link keys} argument and sets {@link wrapper.runtime.lastError}.\n       */\n      set: function(keys) {\n        try {\n          if(!keys || keys instanceof String || typeof keys === 'string' || keys instanceof Array) {\n            extensionLog(new Error('The `keys` argument is not a valid Object with keys/properties'));\n          }\n\n          var key, i, len, keysArray = Object.keys(keys);\n\n          if(keysArray.length === 0) {\n            extensionLog(new Error('The `keys` object does not contain any property on its own'));\n          }\n\n          for(i=0, len=keysArray.length; i<len; i++) {\n            key = keysArray[i];\n            safari.extension.settings[key] = keys[key];\n          }\n        } catch (e) {\n          wrapper.runtime.lastError = e;\n          return -1;\n        }\n        return 0;\n      }\n    }\n  },\n  runtime: {\n    lastError: null\n  },\n  tabs: {\n    /**\n     * Sends a single message to the content script(s) in the specified tab,\n     * with an optional callback to run when a response is sent back. The\n     * {@link injected.runtime.onMessage} event is fired in each content script\n     * running in the specified tab for the current extension.\n     * @param {int} tabId - The tab to send the message to.\n     * @param {*} message - Any object that can be serialized.\n     * @returns {Promise} A promise to be fulfilled when it has been received.\n     */\n    sendMessage: function(tabId, message, options, channel) {\n      try {\n        var tab = registry.getTabById(tabId);\n\n        channel = channel || Math.floor(Math.random() * 100000000);\n        tab.page.dispatchMessage('injected.runtime.onMessage', JSON.stringify({message: message, channel: channel}));\n      } catch(e) {\n        return Promise.reject(e.message);\n      }\n      return new Promise(function(resolve, reject) {\n        tab.addEventListener('message', function handler(event) {\n          var message = JSON.parse(event.message);\n          // The injected script response\n          if(event.name === 'injected.runtime.onMessage~response' &&\n             parseInt(message.channel) === (0 - channel)) {\n            tab.removeEventListener('message', handler, false);\n            resolve(message.response);\n          }\n        }, false);\n      });\n    },\n\n    /**\n     * Gets all tabs that have the specified properties, or all tabs if no\n     * properties are specified.\n     * @param {object} queryInfo\n     * @param {bool} [queryInfo.active] - TODO Whether the tabs are active in\n     * their windows. (Does not necessarily mean the window is focused.)\n     * @param {bool} [queryInfo.currentWindow] - TODO Whether the tabs are in\n     * the /current window/. Note: the current window doesn’t mean it’s the\n     * active one. It means that the window is currently executing.\n     * @returns {int|Object[]} Result of the query of -1 on error.\n     */\n    query: function(queryInfo) {\n      var windows, tabs;\n      try {\n        windows = safari.application.browserWindows;\n        tabs = [];\n\n        if(Object.prototype.toString.call(queryInfo) === '[object Object]') {\n          // queryInfo.currentWindow\n          if(queryInfo.currentWindow) {\n            /** Because there’s no way I know to select the window currently\n             * running in Safari, the active window (or\n             * {@link lastFocusedWindow} one if null) will be used instead. If\n             * someone successfully thriggers an action page that isn’t focused,\n             * it’s an undefined behavior.\n             */\n            windows = registry.getActiveWindow();\n            if(windows === null) {\n              windows = registry.getLastFocused();\n            }\n            // Put it in an array\n            windows = [windows];\n          }\n\n          // queryInfo.active\n          if(queryInfo.active === true) {\n            tabs = makeTabType(activeTabs(windows));\n          } else {\n            tabs = makeTabType(getTabs(windows));\n          }\n        } else {\n          extensionLog(new Error('No valid query is specified'));\n        }\n\n        /**\n         * Gets all active {@link SafariBrowserTab} from given an array\n         * {@link SafariBrowserWindow}.=\n         * @param {SafariBrowserWindow[]} windows - Windows to get all active\n         * tabs.\n         * @returns {SafariBrowserTabs[]} Array of active tabs.\n         */\n        function activeTabs(windows) {\n          var resultTabs = [], index, i, len;\n\n          for(i=0, len=windows.length; i<len; i++) {\n            // It makes a copy of the object\n            resultTabs.push(windows[i].activeTab);\n          }\n          return resultTabs;\n        }\n\n        /**\n         * Gets all tabs from given windows.\n         * @param {SafariBrowserWindow[]} windows - An array of\n         * {@link SafariBrowserWindow}.\n         * @returns {SafariBrowserTab[]} List of tabs from {@link windows}.\n         */\n        function getTabs(windows) {\n          var i, len, u, u_len, windowTabs, index, resultTabs = [];\n          for(i=0, len=windows.length; i<len; i++) {\n            windowTabs = windows[i].tabs;\n            for(u=0, u_len=windowTabs.length; u<u_len; u++) {\n              resultTabs.push(windowTabs[u]);\n            }\n          }\n          return resultTabs;\n        }\n\n        /**\n         * Makes a Tab type.\n         * @param {SafariBrowserTab[]} tabs - Array of SafariBowserTab.\n         * @returns {Tab[]} Chrome formatted Tab type.\n         */\n        function makeTabType(tabs){\n          var resultTabs = [], i, len, currentTab, tab;\n\n          for(i=0, len=tabs.length; i<len; i++) {\n            tab = tabs[i];\n            currentTab = {\n              id: tab.id\n              // All other parts may change\n            };\n            resultTabs.push(currentTab);\n          }\n          return resultTabs;\n        }\n      } catch(e) {\n        wrapper.runtime.lastError = e;\n        return -1;\n      }\n      return tabs;\n    }\n  }\n};\n\n// adapter.js<background> ends here\n"
  },
  {
    "path": "safari/background/adapterListener.js",
    "content": "/*global wrapper, safari */\n\n/**\n * @fileOverview This file contains the adapter listener (i.e. message\n * passing part) for injected scripts since most of the adaptee\n * methods need higher priviledge (but allowed from a global page).\n * @name adapterListener.js<background>\n * @author Etienne Prud’homme\n * @license GPLv3\n */\n\n// Listens to the client adapter\nsafari.application.addEventListener('message', function(event) {\n  var status = -1;\n  var message = JSON.parse(event.message);\n\n  // Safari uses ev.name for the name of the event while using\n  // /message/ for communication between scripts.\n  switch(event.name) {\n  case 'wrapper.storage.sync.get':\n    // Returns -1 on error otherwise the response\n    status = wrapper.storage.sync.get(message.keys);\n    respondBack('injected.storage.sync.get', status);\n    break;\n  case 'wrapper.storage.sync.set':\n    // Returns -1 on error otherwise the response\n    status = wrapper.storage.sync.set(message.keys);\n    respondBack('injected.storage.sync.set', status);\n    break;\n  case 'wrapper.runtime.sendMessage':\n    // TODO\n    // Returns -1 on error otherwise the response\n    status = wrapper.runtime.sendMessage();\n    respondBack('injected.runtime.sendMessage', status);\n    break;\n  case 'wrapper.tabs.query':\n    // Returns -1 on error otherwise the responsenn\n    status = wrapper.tabs.query(message.query);\n\n    // Note: The docs don’t officially specify throwing lastError\n    respondBack('injected.tabs.query', status);\n    break;\n  }\n\n  /**\n   * Function that sends back the result of the request and also take\n   * cares of status codes.\n   * @param {string} channel - The name of the request receiver.\n   * @param {int|Object} status - The response of a query. On error,\n   * it should be `-1`.\n   */\n  function respondBack(channel, status) {\n    var response;\n    if(status === -1) {\n      response = {name: 'error', response: wrapper.runtime.lastError.message};\n    } else {\n      response = {name: 'ok', response: status};\n    }\n    event.target.page.dispatchMessage(channel, JSON.stringify(response));\n  }\n  // Since its lifetime is for a callback\n  wrapper.runtime.lastError = undefined;\n}, false);\n\n// adapterListener.js<background> ends here\n"
  },
  {
    "path": "safari/background/background.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <title>Background Page</title>\n    <meta charset=\"utf-8\">\n    <script src=\"background.js\"></script>\n  </head>\n  <body></body>\n</html>\n"
  },
  {
    "path": "safari/background/background.js",
    "content": "/*global safari, SafariBrowserTab, SafariBrowserWindow, wrapper, extensionLog */\n\n/**\n * @fileOverview This file adds support for the Chrome API in the global page\n * script context.\n * @name background.js<safari>\n * @author Etienne Prud’homme\n * @license GPLv3\n */\n\n// Initializes the logs if not created\nsafari.extension.settings.logs = safari.extension.settings.logs || [];\n\n/**\n * Chrome adapter module for the global page context.\n * @returns {object} The chrome namespace.\n * @throws {Error} TO FIX. We should set `lastError` instead.\n */\nvar global = (function() {\n  var exports = {\n    tabs: {\n      /**\n       * Sends a single message to the content script(s) in the specified tab,\n       * with an optional callback to run when a response is sent back. The\n       * {@link global.runtime.onMessage} event is fired in each content script\n       * running in the specified tab for the current extension.\n       * @param {int} tabId - The tab to send the message to.\n       * @param {*} message - Any object that can be serialized.\n       * @param {object} [options]\n       * @param {int} [options.frameId] - Send a message to a specific frame\n       * identified by {@link frameId} instead of all frames in the tabn.\n       * @param {global.tabs.sendMessage~responseCallback} [responseCallback] -\n       * Function called when there’s a response. Note: The response can be any\n       * object.\n       */\n      sendMessage: function(tabId, message, options, responseCallback) {\n        var channel = Math.floor(Math.random() * 100000000);\n        wrapper.tabs.sendMessage(tabId, message, options, channel)\n          .then(function(response) {\n            if(typeof(responseCallback) === typeof(Function)) {\n              responseCallback(response);\n            }\n          }).catch(function(reason) {\n            extensionLog(reason);\n          });\n      },\n      /**\n       * @namespace\n       * @property {int} [id] - The ID of the tab. Tab IDs are unique within a\n       * browser session. Under some circumstances a Tab may not be assigned an\n       * ID, for example when querying foreign tabs using the sessions API, in\n       * which case a session ID may be present.\n\n       * @property {int} index - The zero-based index of the tab within its\n       * window.\n       * @property {int} windowId - The ID of the window the tab is contained\n       * within.\n       * @property {int} [openerTabId] - The ID of the tab that opened this tab,\n       * if any. This property is only present if the opener tab still exists.\n       * @property {bool} highlighted - Whether the tab is highlighted.\n       * @property {bool} active - Whether the tab is active in its\n       * window. (Does not necessarily mean the window is focused.)\n       * @property {bool} pinned - Whether the tab is pinned.\n       * @property {string} [url] - The URL the tab is displaying. This property\n       * is only present if the extension’s manifest includes the “tabs”\n       * permission.\n       * @property {string} [title] - The title of the tab. This property is\n       * only present if the extension’s manifest includes the “tabs”\n       * permission.\n       * @property {string} [favIconUrl] - The URL of the tab's favicon. This\n       * property is only present if the extension's manifest includes the\n       * \"tabs\" permission. It may also be an empty string if the tab is\n       * loading.\n       * @property {string} [status] - Either loading or complete.\n       * @property {bool} incognito - Whether the tab is in an incognito window.\n       * @property {int} width - The width of the tab in pixels.\n       * @property {int} height - The height of the tab in pixels.\n       * @property {string} sessionId - The session ID used to uniquely identify\n       * a Tab obtained from the sessions API.\n       */\n      Tab: {\n        id: null,\n        index: null,\n        windowId: null,\n        openerTabId: null,\n        highlighted: null,\n        active: null,\n        pinned: null,\n        url: null,\n        title: null,\n        favIconUrl: null,\n        status: null,\n        incognito: null,\n        width: null,\n        height: null,\n        sessionId: null\n      },\n      /**\n       * Whether the tabs have completed loading.\n       * @readonly\n       * @enum {string}n\n       */\n      tabStatus: {\n        loading: 'loading',\n        complete: 'complete'\n      },\n      /**\n       * The type of window.\n       * @readonly\n       * @enum {string}\n       */\n      windowType: {\n        normal: 'normal',\n        popup: 'popup',\n        panel: 'panel',\n        app: 'app',\n        devtool: 'devtool'\n      },\n      /**\n       * Gets all tabs that have the specified properties, or all tabs if no\n       * properties are specified.\n       * @param {object} queryInfo\n       * @param {bool} [queryInfo.active] - Whether the tabs are active in their\n       * windows.\n       * @todo @param {bool} [queryInfo.pinned] - Whether the tabs are pinned.\n       * @todo @param {bool} [queryInfo.highlighted] - Whether the tabs are\n       * highlighted.\n       * @param {bool} [queryInfo.currentWindow] - Whether the tabs are in the\n       * /current window/.\n       * @todo @param {bool} [queryInfo.lastFocusedWindow] - Whether the tabs\n       * are in the last focused window.\n       * @todo @param {tabStatus} [queryInfo.status] - Whether the tabs have\n       * completed loading.\n       * @todo @param {string} [queryInfo.title] - Match page titles against a\n       * pattern.\n       * @todo @param {string|string[]} [queryInfo.url] - Match tabs against one\n       * or more /URL patterns/. Note that fragment identifiers are not matched.\n       * @param {int} [queryInfo.windowId] - The ID of the parent window, or\n       * {@link global.windows.WINDOW_ID_CURRENT} for the current window.\n       * @todo @param {windowType} [queryInfo.windowType] - The type of window\n       * the tabs are in.\n       * @todo @param {int} [queryInfo.index] - The position of the tabs within\n       * their windows.\n       * @param {global.tabs.query~callback} callback - Threats returned tabs.\n       */\n      query: function(queryInfo, callback) {\n        try {\n          var values = wrapper.tabs.query(queryInfo);\n          if(typeof(callback) === typeof(Function)) {\n            callback(values);\n          } else {\n            console.warn('No callback function is provided');\n          }\n        }\n        catch(e) {\n          throw e;\n        }\n      }\n    },\n    runtime: {\n      /**\n       * Get keys from the `Info.plist` file. Only `version` is currently supported.\n       * @returns {Object} Object containing the manifest properties.\n       */\n      getManifest: function() {\n        return {\n          version: safari.extension.displayVersion\n        };\n      },\n      lastError: null,\n      openOptionsPage: function() {\n        // Find the active popover\n        var popovers = safari.extension.popovers;\n\n        // TODO: Find the last active popover\n        for(var i=popovers.length; --i >= 0;) {\n          // If none is found to be visible, te index 0 is taken\n          if(popovers[i].visible === true || i === 0) {\n            // Note: contentWindow is referring to the popover window itself\n            popovers[i].contentWindow.location.href = safari.extension.baseURI + 'app/options/index.html';\n          }\n        }\n      }\n    },\n    storage: {\n      sync: {\n          /**\n           * Gets one or more items from storage.\n           * @param {string|string[]|object} [keys] - A single key to get, list\n           * of keys to get, or a dictionary specifying default values (see\n           * description of the object). An empty list or object will return an\n           * empty result object. Pass in null to get the entire contents of\n           * storage.\n           * @param {injected.storage.sync.get~callback} callback - Callback\n           * with storage items, or on failure (in which case\n           * {@link injected.runtime.lastError} will be set).\n           * @returns {object} Object with items in their key-value mappings.\n           */\n          get: function(keys, callback) {\n            var values = wrapper.storage.sync.get(keys);\n            if(typeof (callback) === typeof(Function)) {\n              callback(values);\n            }\n          },\n          /**\n           * Sets multiple items.\n           * @param {object} keys - An object which gives each key/value pair to\n           * update storage with. Any other key/value pairs in storage will not\n           * be affected.\n           *\n           * Primitive values such as numbers will serialize as expected. Values\n           * with a typeof `object` and `function` will typically serialize to\n           * `{}`, with the exception of `Array` (serializes as expected), Date,\n           * and Regex (serialize using their `String` representation).\n           * @param {injected.storage.sync.set~callback} [callback] - Callback\n           * on success, or on failure (in which case\n           * {@link injected.runtime.lastError} will be set).\n           */\n          set: function(keys, callback) {\n            wrapper.storage.sync.set(keys);\n            if(typeof(callback) === typeof(Function)) {\n              callback();\n            }\n          }\n      }\n    }\n  };\n\n  // The module was intialized\n  exports.initialized = true;\n  return exports;\n})();\n\nvar chrome = global;\n\n// background.js<safari>\n"
  },
  {
    "path": "safari/background/helpers.js",
    "content": "/*global safari */\n\n/**\n * @fileOverview This file adds utility functions for the Safari global page.\n * @name helpers.js<background>\n * @author Etienne Prud’homme\n * @license GPL\n */\n\n/**\n * Store logging informations in the extension settings.\n * @param {string|error} message - The message to log as a String or an Error.\n * @throws {Error} Error in the arguments of the function (not a String nor an\n * Error).\n */\nfunction extensionLog(log) {\n  // Cache logs to append a single log\n  var logs = safari.extension.settings.logs;\n  var stack, logMessage;\n\n  if(log instanceof Error) {\n    logMessage = log.message;\n    stack = log.stack;\n  } else if (logMessage instanceof String || typeof logMessage === 'string') {\n    logMessage = log;\n    stack = new Error().stack;\n  } else {\n    // Log error of itself\n    extensionLog('Invalid log type: ' + log.toString());\n    throw new Error('Extension logging error');\n  }\n\n  // Adding the new log\n  logs.push({\n    message: logMessage,\n    stack: stack,\n    timestamp: Date.now() / 1000\n  });\n\n  // Record the new logs\n  safari.extension.settings.logs = logs;\n  // This should be in the Background script and shouldn’t conflict with page\n  // scripts\n  console.warn(log);\n\n  // Actually throw that error\n  if(log instanceof Error) {\n    throw log;\n  }\n}\n\n// helpers.js<background> ends here\n"
  },
  {
    "path": "safari/background/registry.js",
    "content": "/**\n * @fileOverview This adds a module to record windows and tabs in\n * Safari. Otherwise, there’s no way to select a tab (or window) with an ID.\n * @name registry.js<background>\n * @author Etienne Prud’homme\n * @license GPLv3\n */\n\n/**\n * Registers Tabs and Windows.\n */\nvar registry = (function() {\n  var _windows = {\n    activeWindow: null,\n    lastFocusedWindow: null\n  };\n  var _tabs = {};\n  var exports = {};\n\n  /**\n   * Returns registered windows from {@link _windows}.\n   * @returns {SafariBrowserWindow[]} Registered windows.\n   */\n  exports.getWindows = function() {\n    return _windows;\n  };\n\n  /**\n   * Returns registered tabs from {@link _tabs}.\n   * @returns {SafariBrowserTab[]} Registered tabs.\n   */\n  exports.getTabs = function() {\n    return _tabs;\n  };\n\n  /**\n   * Returns the window registered as `active`. It may not conform to the Chrome\n   * specs.\n   * @returns {SafariBrowserWindow} The active window.\n   */\n  exports.getActiveWindow = function() {\n    return _windows.activeWindow;\n  };\n\n  /**\n   * Returns the last window that had focus (activated from Safari\n   * specifications).\n   * @returns {SafariBrowserWindow} The last window that had focus.\n   */\n  exports.getLastFocused = function() {\n    return _windows.lastFocusedWindow;\n  };\n\n  /**\n   * Returns the {@link SafariBrowserTab} corresponding to a given ID.\n   * @param {string|int} id - The ID of the registered tab.\n   * @returns {SafariBrowserTab} The tab that has the given ID or -1 on error.\n   */\n  exports.getTabById = function(id) {\n    var tab;\n    try {\n      if(_tabs.hasOwnProperty(id)) {\n        tab = _tabs[id];\n      } else {\n        extensionLog('Invalid tab id: ' + id);\n      }\n    } catch(e) {\n      return -1;\n    }\n    return tab;\n  };\n  /**\n   * Returns a random property that isn’t found in an Object.\n   * @param {object} obj - Object to find uniqueness of a property name.\n   * @param {object} [options] - Options for generating the property.\n   * @param {int} [options.precision=100000000] - Number that will be multiplied\n   * to a random number between 0 and 1.\n   * @param {int|string} [options.prefix=0] - Number or string that will add the\n   * property to itself. It may add the number vlaue or concatenate the String.\n   * @returns {int} Unique Identifier.\n   */\n  function getUniqueProperty(obj, options) {\n    var prop,\n        _options = options || {},\n        precision = _options.precision || 100000000,\n        prefix = _options.prefix || 0;\n\n    do {\n      prop = prefix + Math.floor(Math.random() * precision);\n    } while(obj.hasOwnProperty(prop) === true);\n    return prop;\n  }\n\n  // Windows\n  /**\n   * Register a given window by assigning a new random id. When the window is\n   * closed, it removes the id from available windows.\n   * @todo Check if tabs from the registry are also removed when the window is\n   * closed.\n   * @param {SafariBrowserWindow} _window - The new window to register.\n   */\n  function registerWindow(_window) {\n    var id = '';\n    if(_window.id === undefined) {\n      id = getUniqueProperty(_windows);\n      // Registered windows\n      _windows[id] = _window;\n      _window.id = id;\n\n      // _window.addEventListener('close', function handler() {\n      //   _window.removeEventListener('close', handler, false);\n      //   delete _windows[id];\n      // }, false);\n    }\n  }\n\n  /**\n   * Removes the given {@link SafariBrowserWindow} from the registered windows\n   * in {@link _windows}.\n   * @param {SafariBrowserWindow} _window - The window to remove.\n   */\n  function removeWindow(_window) {\n    var id = _window.id;\n    delete _windows[id];\n  }\n\n  /**\n   * Register all available windows with a new random unique id. Its purpose is\n   * to be called on the extension startup.\n   */\n  function registerWindows() {\n    var browserWindows = safari.application.browserWindows;\n    var id, activeWindow;\n\n    for(var i=0, len=browserWindows.length; i<len; i++) {\n      registerWindow(browserWindows[i]);\n    }\n    activeWindow = safari.application.activeBrowserWindow;\n    _windows.activeWindow = activeWindow;\n    _windows.lastFocusedWindow = activeWindow;\n  }\n  // Windows ends here\n\n  // Tabs\n\n  /**\n   * Register a given tab by assigning a new random id in the tabs\n   * registry. When the tab is closed, it removes the id from the tabs registry.\n   * @param {SafariBrowserTab} _tab - The new tab to register.\n   */\n  function registerTab(_tab) {\n    var id;\n    if(_tab.id === undefined) {\n      id = getUniqueProperty(_tabs);\n      // Registered tabs\n      _tabs[id] = _tab;\n      _tab.id = id;\n\n      // // Removes the id from {@link _tabs}\n      // _tab.addEventListener('close', function handler() {\n      //   _tab.removeEventListener('close', handler, false);\n      //   delete _tabs[id];\n      // }, false);\n    }\n  }\n\n  /**\n   * Removes the given {@link SafariBrowserTab} from the registered windows in\n   * {@link _tabs}.\n   * @param {SafariBrowserTab} tab - The Tab to remove.\n   */\n  function removeTab(tab) {\n    var id = tab.id;\n    delete _tabs[id];\n  }\n\n  /**\n   * Search for {@link SafariBrowserTab} without an id and set a new random\n   * unique id.\n   */\n  function registerTabs() {\n    var status = 0,\n        windows = safari.application.browserWindows;\n\n    var i, u, tabsLen, windowsLen, windowTabs;\n    // Concat tabs from different windows\n\n    // For each window\n    for(i=0, windowsLen=windows.length; i<windowsLen; i++) {\n      windowTabs = windows[i].tabs;\n      // For each tabs in the window\n      for(u=0, tabsLen=windowTabs.length; u<tabsLen; u++) {\n        registerTab(windowTabs[u]);\n      }\n    }\n  }\n  // Tabs ends here\n\n  // There’s no way to specify for windows or tabs (it must be guessed). It\n  // seems that when a window is created it first fires the event for the tab\n  // and then the window.\n  safari.application.addEventListener('open', function(ev) {\n    // If a new window was created\n    if(ev.target instanceof SafariBrowserWindow) {\n      registerWindow(ev.target);\n    } else if (ev.target instanceof SafariBrowserTab) {\n      registerTab(ev.target);\n    } else {\n      extensionLog('Got something else than a Tab or Window');\n    }\n  }, true);\n\n  safari.application.addEventListener('close', function(ev) {\n    // If a window is about to close\n    if(ev.target instanceof SafariBrowserWindow) {\n      removeWindow(ev.target);\n    } else if (ev.target instanceof SafariBrowserTab) {\n      // If a tab is about to close\n      removeTab(ev.target);\n    } else {\n      extensionLog('Got something else than a Tab or Window');\n    }\n  }, true);\n\n  safari.application.addEventListener('activate', function(ev) {\n    if(ev.target instanceof SafariBrowserWindow) {\n      _windows.activeWindow = ev.target;\n      // TODO: What about when it’s closed?\n      _windows.lastFocusedWindow = ev.target;\n    }\n  }, true);\n\n  safari.application.addEventListener('deactivate', function(ev) {\n    if(ev.target instanceof SafariBrowserWindow) {\n      _windows.activeWindow = null;\n    }\n    console.log(ev);\n  }, true);\n\n  registerTabs();\n  registerWindows();\n  return exports;\n})();\n\n// registry.js<background> ends here\n"
  },
  {
    "path": "safari/browser_action/intro.js",
    "content": "/**\n * @fileOverview This file contains the opening statements of\n * `browser_action.js` for the Safari Browser. With this file, a function will\n * wrap the original `browser_action.js`. It prevents executing the code until\n * the `chrome` namespace is fully loaded.\n * @name intro.js<action_page>\n * @author Etienne Prud’homme\n * @license GPLv3\n */\n\nvar chrome;\n\n/**\n * Blocks execution until the Chrome namespace is fully loaded.\n */\n/* jshint ignore:start */\nfunction waitChromeNS() {\n/* jshint ignore:end */\n\n\n// intro.js<popover> ends here\n"
  },
  {
    "path": "safari/browser_action/outro.js",
    "content": "/*global waitChromeNS, chrome, safari, checkSiteStatus */\n\n/**\n * @fileOverview This file contains the Safari closing statements for the\n * browser action page appended to the main file. This file contains a function\n * executed each 100ms to check if the `chrome` module/namespace is fully\n * loaded. If it’s already initialized, it assign the _globalPage_ namespace as\n * `chrome`, otherwise it initializes it.\n * @name outro.js<browser_action>\n * @author Etienne Prud’homme\n * @license GPLv3\n */\n\n  var main = document.getElementById('main');\n  main.style.width = '400px';\n\n  var label = document.getElementById('ud-label-loader');\n  label.remove();\n\n  safari.application.addEventListener('popover', function() {\n    checkSiteStatus();\n  });\n  /* jshint ignore:start */\n}\n/* jshint ignore:end */\n\nvar handler = window.setInterval(function() {\n  try {\n    // If the module isn’t initialized, intialize it\n    if(typeof(safari.extension.globalPage.contentWindow.chrome) === typeof(Function)) {\n      chrome = safari.extension.globalPage.contentWindow.chrome();\n      window.clearInterval(handler);\n      waitChromeNS();\n    } else {\n      // If the module is initialized, assign the module\n      if(safari.extension.globalPage.contentWindow.chrome.initialized === true) {\n        chrome = safari.extension.globalPage.contentWindow.chrome;\n        window.clearInterval(handler);\n        waitChromeNS();\n      } else {\n        return;\n      }\n    }\n  } catch(e) {\n    return;\n  }\n}, 100);\n\n// outro.js<browser_action> ends here\n// browser_action.js ends here\n"
  },
  {
    "path": "safari/inject/intro.js",
    "content": "/*global safari */\n\n/**\n * @fileOverview This file contains the opening statements of `inject.js` for\n * Safari.\n * @name intro.js<safari>\n * @author Etienne Prud’homme\n * @license GPLv3\n */\n\n/* jshint ignore:start */\n// Injected scripts in Safari get also injected in iFrames\nif (window.top === window) {\n  /* jshint ignore: end*/\n  var injected = (function(){\n    var pageListener = [];\n    /**\n     * @namespace\n     * @property {object} injected.runtime.lastError - This will be defined\n     * during an API method callback if there was an error\n     * @property {string} [injected.runtime.lastError.message] - Details about\n     * the error which occurred.\n     */\n    var exports =  {\n      runtime: {\n        /**\n         * Sends a single message to event listeners within the extension/app or\n         * a different extension/app. Similar to\n         * {@link injected.runtime.onMessage} but only sends a single message,\n         * with an optional response. If sending to your extension, the\n         * {@link injected.runtime.onMessage} event will be fired in each page,\n         * or {@link injected.runtime.onMessageExternal}, if a different\n         * extension. Note that extensions cannot send messages to content\n         * scripts using this method. To send messages to content scripts, use\n         * {@link injected.tabs.sendMessage.}\n         * @param {string} [extensionId] - The ID of the extension to send the\n         * message to. If `undefined` or `null`, the current extension is used.\n         * @param {*} message - The message to sent.\n         * @param {object} [options]\n         * @todo @param {bool} [options.includeTlsChannelId] - Whether the TLS\n         * channel ID will be passed into onMessageExternal for processes that\n         * are listening for the connection event.\n         * @param {injected.runtime.sendMessage~callback} [callback] - Function\n         * called when there’s a response. Note: The response can be any object.\n         */\n        sendMessage: function(extensionId, message, options, callback) {\n\n        },\n        lastError: null,\n        /**\n         * An object containing information about the script context that sent a\n         * message or request.\n         * @namespace\n         * @property {injected.tabs.Tab} [tab] - The {@link injected.tabs.Tab}\n         * which opened the connection, if any. This property will only be\n         * present when the connection was opened from a tab (including content\n         * scripts), and only if the receiver is an extension, not an app.\n         */\n        MessageSender: {\n          tab: null,\n          frameId: null\n          // id: null,\n          // url: null,\n          // tlsChannelId: null\n        },\n        onMessage: {\n          /**\n           * Fired when a message is sent from either an extension process or a\n           * content script.\n           * @param {injected.runtime.onMessage.addListener~callback} callback -\n           */\n          addListener: function(callback) {\n            pageListener.push(callback);\n          }\n        }\n      },\n      extension: {\n        /**\n         * Converts a relative path within an extension install directory to a\n         * fully-qualified URL.\n         * @param {string} path - A path to a resource within an extension\n         * expressed relative to its install directory.\n         * @returns {string} The fully-qualified URL.\n         */\n        getURL: function(url) {\n          return safari.extension.baseURI + url;\n        }\n      },\n      storage: {\n        sync: {\n          /**\n           * Gets one or more items from storage.\n           * @param {string|string[]|object} [keys] - A single key to get, list\n           * of keys to get, or a dictionary specifying default values (see\n           * description of the object). An empty list or object will return an\n           * empty result object. Pass in null to get the entire contents of\n           * storage.\n           * @param {injected.storage.sync.get~callback} callback - Callback\n           * with storage items, or on failure (in which case\n           * {@link injected.runtime.lastError} will be set).\n           * @returns {object} Object with items in their key-value mappings.\n           */\n          get: function(keys, callback) {\n            askAdapter('wrapper.storage.sync.get', {keys: keys})\n              .then(function(values) {\n                if(callback instanceof Function) {\n                  console.log('In `injected.storage.sync.get` returning: ' + values.toString());\n                  callback(values);\n                }\n              }).catch(function(error) {\n                throw new Error(error);\n              });\n          },\n          /**\n           * Sets multiple items.\n           * @param {object} keys - An object which gives each key/value pair to\n           * update storage with. Any other key/value pairs in storage will not\n           * be affected.\n           *\n           * Primitive values such as numbers will serialize as expected. Values\n           * with a typeof `object` and `function` will typically serialize to\n           * `{}`, with the exception of `Array` (serializes as expected), Date,\n           * and Regex (serialize using their `String` representation).\n           * @param {injected.storage.sync.set~callback} [callback] - Callback\n           * on success, or on failure (in which case\n           * {@link injected.runtime.lastError} will be set).\n           */\n          set: function(keys, callback) {\n            // Send the request\n            askAdapter('wrapper.storage.sync.set', {keys: keys})\n              .then(function() {\n                if(callback instanceof Function) {\n                  callback();\n                }\n              }).catch(function(error) {\n                throw new Error(error);\n              });\n          }\n        }\n      }\n    };\n\n    /**\n     * Serialize an Object to be supported by Safari when sent as JSON.\n     * @param {object} obj - Any object that will be converted to JSON. It\n     * supports RegExp and Date.\n     * @returns {string} The JSON string.\n     */\n    function serialize(obj) {\n      // var topObject = true;\n\n      return JSON.stringify(obj, function(key, value) {\n        // if(topObject) {\n        //   topObject = false;\n        //   return value;\n        // }\n\n        if (value instanceof String || value instanceof RegExp || value instanceof Date) {\n          return value.toString();\n        } else if(value instanceof Array) {\n          return value;\n        }\n        //  else if(value instanceof Object && !topObject) {\n        //   return {};\n        // }\n\n        return value;\n      });\n    }\n\n    /**\n     * Sends a message to the adapter function and return a Promise that\n     * resolves when the response is received.\n     * @param {} channel\n     * @param {} message\n     * @returns {Promise} A Promise that resolves when the response is received.\n     */\n    function askAdapter(channel, message) {\n      return new Promise(function(resolve, reject) {\n        // Register the response receiver before sending the message (else it\n        // won’t be fired)\n        safari.self.addEventListener('message', function responseHandler(ev) {\n          var data = JSON.parse(ev.message);\n          channel = channel.replace('wrapper.', 'injected.');\n          // Remove self since just ask --> response\n          safari.self.removeEventListener('message', responseHandler);\n          if(ev.name === channel) {\n            if(data.name === 'ok') {\n              resolve(data.response);\n            } else if(data.name === 'error') {\n              // runtime.lastError\n              reject(data.response);\n            } else {\n              reject('The Global Page sent an invalid response');\n            }\n          }\n        }, false);\n        sendMessageToAdapter(channel, message);\n      });\n    }\n\n    function sendMessageToAdapter(channel, message) {\n      var JSONmessage = serialize(message);\n      safari.self.tab.dispatchMessage(channel, JSONmessage);\n    }\n\n    // The injected script receives messages\n    safari.self.addEventListener('message', function handler(event) {\n      var data = JSON.parse(event.message);\n      // To prevent listening to the same event. It may be useless, but Safari\n      // always have weird behavior.\n      var channel = 0 - parseInt(data.channel);\n\n      /**\n       * Set to true when a listener call {@link sendResponse}. The Chrome\n       * specs only allow a call to that function.\n       */\n      var activeResponse = false;\n\n      // The injected script receives messages from a sendMessage method\n      if(event.name === 'injected.runtime.onMessage' &&\n         pageListener.length > 0) {\n        // For each listener, pass the message\n        for(var i=0, len=pageListener.length; i<len; i++) {\n          // TODO: Add support to the MessageSender field\n          pageListener[i](data.message, undefined, sendResponse);\n        }\n\n        // If no listeners called sendResponse\n        if(activeResponse !== true) {\n          sendResponse();\n        }\n      }\n\n      /**\n       * Sends a response from the listener. Can only be called once.\n       * @param {*} response - Any JSON-ifiable objects.\n       */\n      function sendResponse(response) {\n        if(activeResponse !== true) {\n          activeResponse = true;\n          safari.self.tab.dispatchMessage('injected.runtime.onMessage~response', JSON.stringify({response: response, channel: channel}));\n        }\n      }\n    }, false);\n\n    return exports;\n    /**\n     * Callback when there’s a message sent to the extension channel (can be\n     * both the extension or a /content-script/).\n     * @callback injected.runtime.onMessage.addListener~callback\n     * @param {*} message - The message sent by the calling script.\n     * @param {MessageSender} sender - The sender.\n     * @param {function} sendResponse - Function to call (at most once) when\n     * there’s a response. The argument should be any JSON-ifiable object. If\n     * there’s more than one {@link injected.runtime.onMessage} listener in the\n     * same document, then only one may send a response.\n     */\n\n    /**\n\n     * Callback  to  pass   the  received  a  response   when  executing\n     * {@link injected.runtime.senMessage}.\n     * @callback injected.runtime.sendMessage~responseCallback\n\n     * @param {*} response - The JSON response object sent by the handler of the\n     * message. If an error occurs while connecting to the extension, the\n     * callback will be called with no arguments and\n     * {@link injected.runtime.lastError} will be set to the error message.\n     */\n\n    /**\n     * Callback when getting storage items, or on failure (in which case\n     * {@link injected.runtime.lastError} will be set).\n     * @callback injected.storage.sync.get~callback\n     * @param {object} items - Object with items in their key-value mappings.\n     */\n\n    /**\n     * Callback when setting storage items, or on failure (in which case\n     * {@link injected.runtime.lastError} will be set).\n     * @callback injected.storage.sync.set~callback\n     */\n\n    /**\n     * Callback to process tabs returned by {@link injected.tabs.query}.\n     * @callback injected.tabs.query~callback\n     * @param {Tab[]} results - The results of the tabs query.\n     */\n\n    /**\n     * Callback to pass the received a response when executing\n     * {@link injected.tabs.senMessage}.\n     * @callback injected.tabs.sendMessage~responseCallback\n\n     * @param {*} response - The JSON response object sent by the handler of the\n     * message. If an error occurs while connecting to the extension, the\n     * callback will be called with no arguments and\n     * {@link injected.runtime.lastError} will be set to the error message.\n     */\n  })();\n\n  chrome = injected;\n\n// intro.js<safari> ends here\n"
  },
  {
    "path": "safari/inject/outro.js",
    "content": "/**\n * @fileOverview This file contains the closing statements of `inject.js` for\n * Safari.\n * @name outro.js<Safari>\n * @author Etienne Prud’homme\n * @license GPLv3\n */\n\n/* jshint ignore:start */\n}\n/* jshint ignore:end */\n\n// outro.js<safari> ends here\n// inject.js<safari> ends here\n"
  },
  {
    "path": "safari/options/intro.js",
    "content": "/**\n * @fileOverview This file contains the Firefox opening statements for the options page script prepended to the main file.\n * @name intro.js<options>\n * @author Etienne Prud’homme\n * @license GPLv3\n */\n\nvar chrome;\n\nvar browserName = 'Safari';\n/**\n * Blocks execution until the Chrome namespace is fully loaded.\n */\n/* jshint ignore:start */\nfunction waitChromeNS() {\n/* jshint ignore:end */\n\n// intro.js<options> ends here\n"
  },
  {
    "path": "safari/options/outro.js",
    "content": "/*global waitChromeNS, chrome, safari */\n\n/**\n * @fileOverview This file contains the Firefox closing statements for the options page script appended to the main file.\n * @name outro.js<options>\n * @author Etienne Prud’homme\n * @license GPLv3\n */\n\n  var backButton = document.getElementById('back-button');\n  backButton.style.display = 'block';\n\n  backButton.addEventListener('click', function handler(event) {\n    window.history.back();\n  });\n\n  // When the popover is closed (it actually loses focus, but it’s still there)\n  window.addEventListener('blur', function() {\n    window.location.reload();\n  });\n/* jshint ignore:start */\n}\n/* jshint ignore:end */\n\nvar handler = window.setInterval(function() {\n  try {\n    // If the module isn’t initialized, intialize it\n    if(typeof(safari.extension.globalPage.contentWindow.chrome) === typeof(Function)) {\n      chrome = safari.extension.globalPage.contentWindow.chrome();\n      window.clearInterval(handler);\n      waitChromeNS();\n    } else {\n      // If the module is initialized, assign the module\n      if(safari.extension.globalPage.contentWindow.chrome.initialized === true) {\n        chrome = safari.extension.globalPage.contentWindow.chrome;\n        window.clearInterval(handler);\n        waitChromeNS();\n      } else {\n        return;\n      }\n    }\n  } catch(e) {\n    return;\n  }\n}, 100);\n\n// outro.js<options> ends here\n// options.js ends here\n"
  },
  {
    "path": "sample/index.html",
    "content": "<!doctype html>\n<head>\n  <title>Sample Tests</title>\n  <meta name=\"udacity-grader\" content=\"test.json\" libraries=\"jsgrader\" unit-tests=\"unit-tests.js\">\n  <meta charset=\"UTF-8\">\n  <style>\n    body {\n      width: 100%;\n    }\n    .box {\n      background-color: #fcc;\n    }\n    .flex-container {\n      display: flex;\n      flex-wrap: wrap;\n    }\n    .flex {\n      margin-right: 10px;\n      margin-bottom: 10px;\n    }\n\n    .flex:last-of-type {\n      margin-right: 0px;\n    }\n\n    .flex1 {\n      background-color: #ffc;\n      min-height: 30px;\n      min-width: calc( (100% - 10px) / 4);\n    }\n    .flex2 {\n      background-color: #fcc;\n      min-height: 30px;\n      min-width: calc( (100% - 10px) / 4);\n    }\n    .flex3 {\n      background-color: #cff;\n      min-height: 30px;\n      min-width: calc( (100% - 10px) / 4);\n    }\n    .flex4 {\n      background-color: #fcf;\n      min-height: 30px;\n      min-width: calc( (100% - 10px) / 4);\n    }\n    .flex5 {\n      background-color: #cfc;\n      min-height: 30px;\n      min-width: calc( (100% - 10px) / 4);\n    }\n    .three-quarters {\n      width: 75%;\n    }\n    #udacity {\n      height: 100px;\n      width: auto;\n    }\n    .box:nth-child(even) {\n      background-color: #cfc;\n    }\n    .abs {\n      position: absolute;\n      top: 30px;\n      left: 0px;\n    }\n    .box4 {\n      position: absolute;\n      /* Not all user-agents will make it 8px wide (font) */\n      width: 8px;\n      left: calc(100% - 8px);\n      /*bottom: 0;*/\n    }\n    .center-box-container {\n      background-color: #fcf;\n      width: 300px;\n      height: 50px;\n    }\n    .center {\n      width: 100px;\n      margin-left: auto;\n      margin-right: auto;\n      text-align: center;\n    }\n    .output {\n      background: #ddd !important;\n      border: 1px solid black;\n      height: 5em;\n      overflow-y: scroll;\n      font-family: monospace;\n      padding: 0px 8px;\n    }\n    .flex-container {\n      display: flex;\n      justify-content: space-between;\n    }\n  </style>\n<head>\n<body>\n  <h1>Grading Engine Test!</h1>\n  <img id=\"udacity\" src=\"udacity.jpg\" alt=\"udacity\">\n  <div class=\"box box1 three-quarters\">75% width</div>\n  <div class=\"box box2\">b</div>\n  <div class=\"box box3 innerHTML\">this is the correct innerHTML</div>\n  <div class=\"box box4\">d</div>\n  <div class=\"box box5\" test>has test attr</div>\n  <div class=\"box box6\">f</div>\n  <div class=\"box box7 abs\">looking at this one’s abs pos</div>\n  <div class=\"box box8\">h</div>\n  <div class=\"box box9\">i</div>\n  <div class=\"box box10\">j</div>\n  <div class=\"center-box-container\">\n    <div class=\"box box11 center\">center</div>\n  </div>\n  <p>Hello, I’m a <code>p</code> tag.</p>\n  <div class=\"flex-container\">\n    <div class=\"flex flex1\"></div>\n    <div class=\"flex flex2\"></div>\n    <div class=\"flex flex3\"></div>\n    <div class=\"flex flex4\">This box is not the last child</div>\n    <div class=\"flex flex5\">Last child of this container</div>\n  </div>\n  <div class=\"box output\">INIT</div>\n  <script>\n    function getDateTime() {\n      var d = new Date();\n      var date = '';\n\n      var year = d.getFullYear().toString();\n      var month = (+d.getMonth() + 1).toString();\n      var day = d.getDate().toString();\n      var hours = d.getHours().toString();\n      var minutes = d.getMinutes().toString();\n      var seconds = d.getSeconds().toString();\n\n      if (month.length < 2) {\n        month = '0' + month;\n      }\n      if (day.length < 2) {\n        month = '0' + month;\n      }\n      if (hours.length < 2) {\n        month = '0' + month;\n      }\n      if (minutes.length < 2) {\n        month = '0' + month;\n      }\n      if (seconds.length < 2) {\n        month = '0' + month;\n      }\n      date = year + month + day + hours + minutes + seconds;\n      return date;\n    }\n    function log(string) {\n      let div = document.createElement('div');\n      div.classList.add('flex-container');\n      let textSpan = document.createElement('span');\n      textSpan.innerText = string;\n\n      let dateSpan = document.createElement('span');\n      dateSpan.innerText = getDateTime();\n      div.appendChild(textSpan);\n      div.appendChild(dateSpan);\n\n      output.insertBefore(div, output.firstChild);\n    }\n    const output = document.querySelector('.output');\n    window.addEventListener('ud-test-pass', e => log(e.detail));\n  </script>\n</body>\n"
  },
  {
    "path": "sample/test.json",
    "content": "[{\n  \"name\": \"Meta Info\",\n  \"code\": \"Got the meta stuff\",\n  \"tests\": [\n    {\n      \"description\": \"&lt;meta&gt; has name set to udacity-grader\",\n      \"definition\": {\n        \"nodes\": \"meta\",\n        \"limit\": 1,\n        \"attribute\": \"name\",\n        \"equals\": \"udacity-grader\"\n      }\n    },\n    {\n      \"description\": \"&lt;meta&gt; has a content tag with a link to json\",\n      \"definition\": {\n        \"nodes\": \"meta\",\n        \"limit\": 1,\n        \"attribute\": \"content\",\n        \"hasSubstring\": \".json\"\n      },\n      \"flags\": {\n        \"optional\": true\n      }\n    }\n  ]\n},\n{\n  \"name\": \"These should pass\",\n  \"code\": \"you should see this\",\n  \"tests\": [\n    {\n      \"description\": \"There are 19 divs\",\n      \"definition\": {\n        \"nodes\": \"div\",\n        \"get\": \"count\",\n        \"equals\": 19\n      }\n    },\n    {\n      \"description\": \"Width check - 75% of page width is between 1 and 10000 px\",\n      \"definition\": {\n        \"nodes\": \".three-quarters\",\n        \"cssProperty\": \"width\",\n        \"isInRange\": {\n          \"lower\": 1,\n          \"upper\": 10000\n        }\n      }\n    },\n    {\n      \"description\": \"There is a Udacity logo\",\n      \"definition\": {\n        \"nodes\": \"img#udacity\",\n        \"exists\": true\n      }\n    },\n    {\n      \"description\": \"One div has test attr\",\n      \"definition\": {\n        \"nodes\": \"div\",\n        \"limit\": 1,\n        \"attribute\": \"test\",\n        \"exists\": true\n      }\n    },\n    {\n      \"description\": \"The innerHTML div has correct innerHTML\",\n      \"definition\": {\n        \"nodes\": \"div.innerHTML\",\n        \"get\": \"innerHTML\",\n        \"equals\": \"this is the correct innerHTML\"\n      }\n    },\n    {\n      \"description\": \"The UA string has Mozilla in it\",\n      \"definition\": {\n        \"get\": \"UAString\",\n        \"hasSubstring\": \"Mozilla\"\n      }\n    },\n    {\n      \"description\": \"page body is bigger than 400px\",\n      \"definition\": {\n        \"nodes\": \"body\",\n        \"cssProperty\": \"width\",\n        \"isGreaterThan\": 400\n      }\n    },\n    {\n      \"description\": \"the random div is in the right spot\",\n      \"definition\": {\n        \"nodes\": \".abs\",\n        \"absolutePosition\": \"top\",\n        \"equals\": 30\n      }\n    },\n    {\n      \"description\": \"the random div has absolute position left of 0\",\n      \"definition\": {\n        \"nodes\": \".abs\",\n        \"absolutePosition\": \"left\",\n        \"equals\": 0\n      }\n    },\n    {\n      \"description\": \"the right div is on the far right\",\n      \"definition\": {\n        \"nodes\": \".box4\",\n        \"absolutePosition\": \"right\",\n        \"equals\": \"max\"\n      }\n    },\n    {\n      \"description\": \"the box with just a b in it has a b in it\",\n      \"definition\": {\n        \"nodes\": \".box2\",\n        \"get\": \"innerHTML\",\n        \"equals\": [\"b\", \"d\"]\n      }\n    },\n    {\n      \"description\": \"listening to events\",\n      \"definition\": {\n        \"waitForEvent\": \"ud-test\",\n        \"exists\": true\n      }, \"flags\": {\n        \"noRepeat\": true\n      }\n    },\n    {\n      \"description\": \"DPR is equal to 2 (optional)\",\n      \"definition\": {\n        \"get\": \"DPR\",\n        \"equals\": 2\n      },\n      \"flags\": {\n        \"optional\": true\n      }\n    },\n    {\n      \"description\": \"All divs have class box OR flex\",\n      \"definition\": {\n        \"nodes\": \"div\",\n        \"attribute\": \"class\",\n        \"hasSubstring\": {\n          \"expected\": [\".*flex.*\", \".*box.*\"]\n        }\n      }\n    },\n    {\n      \"description\": \"Some divs have class box\",\n      \"definition\": {\n        \"nodes\": \"div\",\n        \"limit\": \"some\",\n        \"attribute\": \"class\",\n        \"hasSubstring\": \".*box.*\"\n      }\n    },\n    {\n      \"description\": \"The output box is showing events resulting from tests passing\",\n      \"definition\": {\n        \"nodes\": \".output\",\n        \"get\": \"innerHTML\",\n        \"exists\": true\n      }\n    },\n    {\n      \"description\": \"The center box is on the middle\",\n      \"definition\": {\n        \"nodes\": \".center\",\n        \"cssProperty\": \"marginLeft\",\n        \"equals\": \"100px\"\n      }\n    },\n    {\n      \"description\": \"The center box doesn’t have a margin at bottom\",\n      \"definition\": {\n        \"nodes\": \".center\",\n        \"cssProperty\": \"marginBottom\",\n        \"equals\": \"0px\"\n      }\n    },\n    {\n      \"description\": \"The green box is the last child of “.flex-container”\",\n      \"definition\": {\n        \"nodes\": \".flex-container\",\n        \"children\": \".flex:last-child\",\n        \"attribute\": \"class\",\n        \"hasSubstring\": \"flex5\"\n      }\n    },\n    {\n      \"description\": \"The magenta box is not the last child of “.flex-container”\",\n      \"definition\": {\n        \"nodes\": \".flex-container\",\n        \"children\": \".flex:last-child\",\n        \"attribute\": \"class\",\n        \"not\": true,\n        \"hasSubstring\": \"flex4\"\n      }\n    },\n      {\n      \"description\": \"The number of “.flex-container:last-child” is 0\",\n      \"definition\": {\n        \"nodes\": \".flex-container\",\n        \"children\": \".flex-4:last-child\",\n        \"get\": \"count\",\n        \"equals\": 0\n      }\n    }\n  ]\n},\n{\n  \"name\": \"These should fail\",\n  \"code\": \"it’s bad if you see this\",\n  \"tests\": [\n    {\n      \"description\": \"There are 15 divs (just delete one)\",\n      \"definition\": {\n        \"nodes\": \"div\",\n        \"get\": \"count\",\n        \"equals\": 15\n      }\n    },\n    {\n      \"description\": \"Width check - 75% of page width is between 900 and 1000 px (just resize)\",\n      \"definition\": {\n        \"nodes\": \".three-quarters\",\n        \"cssProperty\": \"width\",\n        \"isInRange\": {\n          \"lower\": 800,\n          \"upper\": 900\n        }\n      }\n    },\n    {\n      \"description\": \"No Udacity logo (delete the Udacity logo)\",\n      \"definition\": {\n        \"nodes\": \"img#udacity\",\n        \"exists\": false\n      }\n    },\n    {\n      \"description\": \"No divs have test attr\",\n      \"definition\": {\n        \"nodes\": \"div\",\n        \"limit\": 1,\n        \"attribute\": \"test\",\n        \"exists\": false\n      }\n    },\n    {\n      \"description\": \"The innerHTML div has incorrect innerHTML\",\n      \"definition\": {\n        \"nodes\": \"div.innerHTML\",\n        \"get\": \"innerHTML\",\n        \"not\": true,\n        \"equals\": \"this is the correct innerHTML\"\n      }\n    },\n    {\n      \"description\": \"The UA string has iPad in it\",\n      \"definition\": {\n        \"get\": \"UAString\",\n        \"hasSubstring\": \"iPad\"\n      }\n    },\n    {\n      \"description\": \"page body is less than 400px\",\n      \"definition\": {\n        \"nodes\": \"body\",\n        \"cssProperty\": \"width\",\n        \"isLessThan\": 400\n      }\n    },\n    {\n      \"description\": \"the random div is in the wrong spot\",\n      \"definition\": {\n        \"nodes\": \".abs\",\n        \"absolutePosition\": \"left\",\n        \"equals\": 401\n      }\n    },\n    {\n      \"description\": \"the box with just a b in it doesn’t have a c or a p in it\",\n      \"definition\": {\n        \"nodes\": \".box2\",\n        \"get\": \"innerHTML\",\n        \"equals\": [\"c\", \"p\"]\n      }\n    },\n    {\n      \"description\": \"the random div has absolute position left greater than 1\",\n      \"definition\": {\n        \"nodes\": \".abs\",\n        \"absolutePosition\": \"left\",\n        \"isGreaterThan\": 1\n      }\n    },\n    {\n      \"description\": \"DPR is equal to 0.5\",\n      \"definition\": {\n        \"get\": \"DPR\",\n        \"equals\": 0.5\n      },\n      \"flags\": {\n        \"optional\": true\n      }\n    },\n    {\n      \"description\": \"All divs have class box AND flex\",\n      \"definition\": {\n        \"nodes\": \"div\",\n        \"attribute\": \"class\",\n        \"hasSubstring\": {\n          \"expected\": [\".*flex.*\", \".*box.*\"],\n          \"minValues\": 2\n        }\n      }\n    },\n    {\n      \"description\": \"The output box is not showing events resulting from tests passing\",\n      \"definition\": {\n        \"nodes\": \".output\",\n        \"get\": \"innerHTML\",\n        \"hasSubstring\": \"$^\"\n      }\n    },\n    {\n      \"description\": \"The magenta box is the last child of “.flex-container”\",\n      \"definition\": {\n        \"nodes\": \".flex-container\",\n        \"children\": \".flex:last-child\",\n        \"attribute\": \"class\",\n        \"hasSubstring\": \"flex4\"\n      }\n    }\n  ]\n},\n{\n  \"name\": \"These tests should err\",\n  \"code\": \"ERROR ERROR\",\n  \"tests\": [\n    {\n      \"description\": \"absolute positions\",\n      \"definition\": {\n        \"nodes\": \"body\",\n        \"absolutePositions\": \"left\",\n        \"equals\": 1\n      }\n    },\n    {\n      \"description\": \"bad counts\",\n      \"definition\": {\n        \"nodes\": \"body\",\n        \"get\": \"counts\",\n        \"equals\": 1\n      }\n    }\n  ]\n},\n{\n  \"name\": \"This should err\",\n  \"code\": \"ERROR ERROR\",\n  \"tests\": [\n    {\n      \"description\": \"absolute positionsss\",\n      \"definitions\": {\n        \"nodes\": \"body\",\n        \"absolutePositions\": \"left\",\n        \"equals\": 1\n      }\n    }\n  ]\n},\n{\n  \"name\": \"Just one\",\n  \"code\": \"thing\",\n  \"tests\": [\n    {\n      \"description\": \"There is a body?\",\n      \"definition\": {\n        \"nodes\": \"body\",\n        \"get\": \"count\",\n        \"equals\": 1\n      }\n    }\n  ]\n}]\n"
  },
  {
    "path": "sample/unit-tests.js",
    "content": "/**\n * @fileOverview This file contains unit tests to be loaded.\n * @name unit-tests.js<sample>\n * @author Cameron Pittman\n * @license GPLv3\n */\n\nconsole.log('dispatch event');\nwindow.dispatchEvent(new CustomEvent('ud-test', {'detail': 'passed'}));\n\n// unit-test.js<sample> ends here\n"
  },
  {
    "path": "src/app/README.md",
    "content": "# User interface (view)\n## Description\nThis directory contains files needed to implements the user-interface. It doesn’t contain grading logic (it’s what we can call the Front-End interface).\n\n## License\nThis directory and the whole project is subject to the [GPLv3 License](../license).\n"
  },
  {
    "path": "src/app/browser_action/browser_action.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <style type=\"text/css\">\n     #main {\n         padding: 1em;\n         height: 100%;\n         width: 800px;\n         font-family: Helvetica, Ubuntu, Arial, sans-serif;\n     }\n     .alert {\n         color: #78f;\n         display: none;\n     }\n     .loader {\n         margin-bottom: 1em;\n     }\n     .loader-description {\n         margin-bottom: 1em;\n     }\n     .autorun.disabled {\n         color: #ccc;\n     }\n     #ud-label-loader.disabled {\n         color: #ccc;\n     }\n     .warning-block {\n         width: 80%;\n         color: #e00;\n         font-weight: bold;\n     }\n     .warning-icon {\n         color: #e9d236;\n     }\n    </style>\n    <link rel=\"stylesheet\" href=\"../css/common.css\" />\n    <link rel=\"stylesheet\" href=\"../css/fonts.css\" />\n    <link rel=\"stylesheet\" href=\"../css/ui.css\" />\n    <meta charset=\"UTF-8\">\n  </head>\n  <body>\n    <div id=\"main\">\n      <h3>Udacity Feedback Settings<span id=\"configs\" class=\"button fa\" title=\"Configure\">&#xf013;</span></h3>\n      <div class=\"loader\">\n        <div class=\"loader-description\">\n          Want to write tests? Here’s the <a href=\"https://github.com/udacity/frontend-grading-engine\" target=\"_blank\">API</a>.\n        </div>\n        <label id=\"ud-label-loader\" for=\"ud-file-loader\"><strong>Load tests from file</strong>\n          <input id=\"ud-file-loader\" type=\"file\" accept=\".json\">\n        </label>\n        <div class=\"alert\"></div>\n      </div>\n      <div class=\"autorun\">\n        <div class=\"warning-block\" style=\"display: none\"><span class=\"button fa warning-icon\">&#xf071</span><span id=\"warning-text\"></div>\n        <form>\n          <label for=\"allow-feedback\">Allow feedback on this domain\n            <input id=\"allow-feedback\" type=\"checkbox\" value=\"yes\">\n          </label>\n        </form>\n      </div>\n    </div>\n    <script src=\"browser_action.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "src/app/browser_action/browser_action.js",
    "content": "/*global FileReader, chrome */\n\n/**\n * @fileOverview This file contains the browser_action logic.\n * @name browser_action.js<browser_action>\n * @author Cameron Pittman\n * @author Etienne Prud’homme\n * @license GPLv3\n */\n\n// http://html5rocks.com/en/tutorials/file/dndfiles/\n/**\n * This function DOESN’T WORK because the browser action closes when the window looses focus. Handle the Drag-and-drop of custom JSON files.\n * @param {DragEvent} evt - The Drag-and-drop event.\n */\nfunction handleFileSelect(evt) {\n  var files = evt.target.files;\n  var file = files[0];\n  var reader = new FileReader();\n  var alert = document.querySelector('.alert');\n  alert.style.display = 'block';\n\n  reader.onload = function (file) {\n    sendDataToTab(file.target.result, 'json');\n  };\n\n  reader.onerror = function (e) {\n    alert.style.display = 'block';\n    alert.textContent = 'Error. Cannot load file.';\n    console.log(e);\n  };\n\n  if (file.type && (file.type.match('application/json') || file.type.match('text/json'))) {\n    alert.textContent = 'JSON found!';\n    reader.readAsText(file);\n  } else {\n    alert.textContent = 'File found';\n    alert.style.color = '#a48700';\n    reader.readAsText(file);\n  }\n}\n\n/**\n * Custom function for sending messages to the current tab.\n * @param {*} data - Any message or data that can be serialized\n * @param {string} type - The type of the message.\n * @param {function} [callback] - The function that will receive the response.\n */\nfunction sendDataToTab(data, type, callback) {\n  // debugger;\n  // get the current tab then send data to it\n  chrome.tabs.query({active: true, currentWindow: true}, fireOffData);\n\n  // actually post data to a tab\n  /**\n   * Sends the message to the current tab.\n   * @param {chrome.tabs.Tab[]} arrayOfTabs - An array of tabs.\n   */\n  function fireOffData (arrayOfTabs) {\n    var activeTab = arrayOfTabs[0];\n    var activeTabId = activeTab.id;\n    var message = {'data': data, 'type': type};\n    chrome.tabs.sendMessage(activeTabId, message, {}, function (response) {\n      if (callback) {\n        callback(response);\n      }\n    });\n  }\n}\n\nvar allowFeedback = document.querySelector('#allow-feedback');\nallowFeedback.onchange = function () {\n  if (!this.checked) {\n    sendDataToTab('off', 'on-off');\n  } else if (this.checked) {\n    sendDataToTab('on', 'on-off');\n  }\n};\n\ndocument.querySelector('#ud-file-loader').addEventListener('change', handleFileSelect, false);\n\n/**\n * Adds a custom warning message and disable the checkbox.\n * @param {string} message - The custom message.\n * @param {string} type - The type of warning.\n * @param {object} options - Object containing options.\n * @param {bool} options.enableCheckbox - When using the `checkbox`,\n * {@link type}, it enables toggling the checkbox. Otherwise it does nothing.\n * @param {bool} options.checked - When using the `checkbox` {@link type}, it\n * checks the checkbox. Otherwise it does nothing.\n * @param {bool} options.removeFileInput - When using the `fileInput`\n * {@link type}, it removes the file input.\n * @param {bool} options.disableFileInput - When using the `fileInput`,\n * {@link type}, it disables the file input.\n */\nfunction addWarning(message, type, options) {\n  options = options || {};\n\n  var fileInput, label;\n  var form = document.getElementsByClassName('autorun')[0];\n  document.getElementById('warning-text').textContent = message;\n  document.getElementsByClassName('warning-block')[0].style.display = 'block';\n\n  if(type === 'disable') {\n    document.getElementsByClassName('loader')[0].remove();\n  } else if(type === 'checkbox') {\n    if(options.enableCheckbox !== true) {\n      form.classList.add('disabled');\n      allowFeedback.disabled = true;\n    }\n    if(options.checked === true) {\n      allowFeedback.checked = true;\n    }\n  } else if(type === 'fileInput') {\n    fileInput = document.getElementById('ud-file-loader');\n\n    if(options.removeFileInput === true) {\n      label = document.getElementById('ud-label-loader');\n      label.remove();\n    } else if(options.disableFileInput === true) {\n      fileInput.disabled = false;\n    } else {\n      label = document.getElementById('ud-label-loader');\n      label.classList.add('disabled');\n      fileInput.disabled = true;\n    }\n  }\n}\n\n/**\n * Makes checkbox `checked` if the website is allowed.\n */\nfunction checkSiteStatus () {\n  // talk to background script\n  sendDataToTab(true, 'background-wake', function (response) {\n    switch(response) {\n    case true:\n      allowFeedback.checked = true;\n      break;\n    case false:\n      allowFeedback.checked = false;\n      break;\n    case 'chrome_local_exception':\n      addWarning('Chrome doesn’t support loading local files automatically', 'checkbox', {enableCheckbox: false, checked: false});\n      break;\n    case 'unknown_protocol':\n      addWarning('Unsupported protocol. Supported protocols are: http, https and (local) file', 'checkbox', {enableCheckbox: false, checked: false});\n      break;\n    case 'invalid_origin':\n      addWarning('The linked JSON page isn’t at the same origin and directory as the document', 'checkbox', {enableCheckbox: false, checked: false});\n      break;\n    case undefined:\n      // response is undefined if there’s no content-script active (so it’s an unsupported URL scheme)\n      addWarning('Unsupported URL scheme. Supported URL schemes are: http://, https://, or file://', 'disable', {});\n      break;\n    default:\n      break;\n    }\n  });\n}\n\n/**\n * Adds the gear EventListener for opening configurations.\n */\nfunction initDisplay() {\n  var configs = document.getElementById('configs');\n  configs.addEventListener('click', function handler() {\n    chrome.runtime.openOptionsPage();\n  });\n}\n\n// Firefox dev edition seems to load a browser action script asynchronously (while having the async property set to false). Pretending it’s not a bug, that may be a workaround for future Firefox releases.\nwindow.addEventListener('DOMContentLoaded', function(event) {\n  checkSiteStatus();\n  initDisplay();\n});\n\n// browser_action.js<browser_action> ends here\n"
  },
  {
    "path": "src/app/css/common.css",
    "content": "/**\n * This file was taken in part from uBlock Origin. It contains styles common\n * to the extension.\n */\n\n* {\n  box-sizing: border-box;\n}\n\nbody {\n  background-color: #fafbfc;\n  color: #4f4f4f;\n  font: 14px/1.3 sans-serif;\n}\n\na {\n  color: #02b3e4;\n  text-decoration: none;\n  font-weight: 600;\n}\n\ncode {\n  background-color: #f9f2f4;\n  border-radius: 4px;\n  color: #c7254e;\n  font-family: Lucida Console,Monaco,Courier,monospace;\n}\n\n/* common.css<css> ends here */"
  },
  {
    "path": "src/app/css/fonts/OFL.txt",
    "content": "Copyright (c) <dates>, <Copyright Holder> (<URL|email>),\nwith Reserved Font Name <Reserved Font Name>.\nCopyright (c) <dates>, <additional Copyright Holder> (<URL|email>),\nwith Reserved Font Name <additional Reserved Font Name>.\nCopyright (c) <dates>, <additional Copyright Holder> (<URL|email>).\n\nThis Font Software is licensed under the SIL Open Font License, Version 1.1.\nThis license is copied below, and is also available with a FAQ at:\nhttp://scripts.sil.org/OFL\n\n\n-----------------------------------------------------------\nSIL OPEN FONT LICENSE Version 1.1 - 26 February 2007\n-----------------------------------------------------------\n\nPREAMBLE\nThe goals of the Open Font License (OFL) are to stimulate worldwide\ndevelopment of collaborative font projects, to support the font creation\nefforts of academic and linguistic communities, and to provide a free and\nopen framework in which fonts may be shared and improved in partnership\nwith others.\n\nThe OFL allows the licensed fonts to be used, studied, modified and\nredistributed freely as long as they are not sold by themselves. The\nfonts, including any derivative works, can be bundled, embedded, \nredistributed and/or sold with any software provided that any reserved\nnames are not used by derivative works. The fonts and derivatives,\nhowever, cannot be released under any other type of license. The\nrequirement for fonts to remain under this license does not apply\nto any document created using the fonts or their derivatives.\n\nDEFINITIONS\n\"Font Software\" refers to the set of files released by the Copyright\nHolder(s) under this license and clearly marked as such. This may\ninclude source files, build scripts and documentation.\n\n\"Reserved Font Name\" refers to any names specified as such after the\ncopyright statement(s).\n\n\"Original Version\" refers to the collection of Font Software components as\ndistributed by the Copyright Holder(s).\n\n\"Modified Version\" refers to any derivative made by adding to, deleting,\nor substituting -- in part or in whole -- any of the components of the\nOriginal Version, by changing formats or by porting the Font Software to a\nnew environment.\n\n\"Author\" refers to any designer, engineer, programmer, technical\nwriter or other person who contributed to the Font Software.\n\nPERMISSION & CONDITIONS\nPermission is hereby granted, free of charge, to any person obtaining\na copy of the Font Software, to use, study, copy, merge, embed, modify,\nredistribute, and sell modified and unmodified copies of the Font\nSoftware, subject to the following conditions:\n\n1) Neither the Font Software nor any of its individual components,\nin Original or Modified Versions, may be sold by itself.\n\n2) Original or Modified Versions of the Font Software may be bundled,\nredistributed and/or sold with any software, provided that each copy\ncontains the above copyright notice and this license. These can be\nincluded either as stand-alone text files, human-readable headers or\nin the appropriate machine-readable metadata fields within text or\nbinary files as long as those fields can be easily viewed by the user.\n\n3) No Modified Version of the Font Software may use the Reserved Font\nName(s) unless explicit written permission is granted by the corresponding\nCopyright Holder. This restriction only applies to the primary font name as\npresented to the users.\n\n4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font\nSoftware shall not be used to promote, endorse or advertise any\nModified Version, except to acknowledge the contribution(s) of the\nCopyright Holder(s) and the Author(s) or with their explicit written\npermission.\n\n5) The Font Software, modified or unmodified, in part or in whole,\nmust be distributed entirely under this license, and must not be\ndistributed under any other license. The requirement for fonts to\nremain under this license does not apply to any document created\nusing the Font Software.\n\nTERMINATION\nThis license becomes null and void if any of the above conditions are\nnot met.\n\nDISCLAIMER\nTHE FONT SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT\nOF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE\nCOPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nINCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL\nDAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM\nOTHER DEALINGS IN THE FONT SOFTWARE.\n"
  },
  {
    "path": "src/app/css/fonts.css",
    "content": "/**\n * This file contains custom fonts for the extension.\n */\n\n@font-face {\n  font-family: 'FontAwesome';\n  font-weight: normal;\n  font-style: normal;\n  src: url('fonts/fontawesome-webfont.ttf') format('truetype');\n}\n\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: normal;\n  font-weight: 400;\n  src: local('Source Sans Pro'), local('SourceSansPro-Regular'), url('fonts/SourceSansPro-Regular.ttf') format('truetype');\n}\n\n/* fonts.css<css> ends here */"
  },
  {
    "path": "src/app/css/options.css",
    "content": "/**\n * This file contains styles for the options page.\n */\n\ntable {\n  border: 3px solid #2c3b48;\n  border-spacing: 0;\n  color: #444;\n  line-height: 37px;\n  margin: 0 auto;\n  width: 100%;\n  max-width: 620px;\n}\n\n.whitelist-title {\n  background-color: #2c3b48;\n  border: none;\n  color: #fff;\n}\n\ntbody tr:hover {\n  background-color: #cce2e9;\n}\n\n.whitelist-type th {\n  background-color: #7d97ad;\n  /* border-bottom: 3px solid #ccc; */\n  color: #2c3b48;\n  padding-left: 1em;\n  text-align: left;\n}\n\n.whitelist-row td {\n  border-bottom: 1px solid #00b4e4;\n}\n\n.whitelist-placeholder {\n  text-align: center;\n}\n.whitelist-placeholder:hover {\n  background: none;\n}\n\n.chromium-message {\n  text-align: left;\n  padding: 1em 1em 0 1em;\n  line-height: 1em;\n}\n\ntbody .whitelist-row:last-child td {\n  border-bottom: none;\n}\n\n.entry {\n  padding-left: 0.5em;\n}\n\n#add-entry input {\n  width: 100%;\n  height: 100%;\n}\n\n.remove {\n  text-align: right;\n}\n\n.hiddenFileInput {\n  height: 0;\n  visibility: hidden;\n  width: 0;\n}\n\n#back-button {\n  display: none;\n  left: .5em;\n  position: absolute;\n  top: .5em;\n}\n\nmain, footer {\n  border: 3px solid #2c3b48;\n  border-spacing: 0;\n  color: #444;\n  line-height: 37px;\n  margin-left: auto;\n  margin-right: auto;\n  margin-top: 2em;\n  width: 100%;\n  max-width: 620px;\n\n}\n\n.title {\n  background-color: #2c3b48;\n  border: none;\n  color: #fff;\n  font-weight: 700;\n  margin: 0;\n  text-align: center;\n}\n\n.description {\n  background-color: #7d97ad;\n  color: #2c3b48;\n  font-weight: 700;\n  padding-left: 1em;\n  margin: 0;\n  text-align: left;\n}\n\n.description a {\n  color: #2c3b48;\n}\n\n.about {\n  line-height: 2em;\n  padding: 0 1em;\n  text-align: left;\n}\n\n/* options.css<css> ends here */"
  },
  {
    "path": "src/app/css/ui.css",
    "content": "/**\n * This file contains the User Interface styles of the extension.\n */\n\nbutton.custom {\n  padding: 0.6em 1em;\n  border: 1px solid transparent;\n  border-color: #ccc #ccc #bbb #bbb;\n  border-radius: 3px;\n  background-color: hsl(216, 0%, 75%);\n  background-image: linear-gradient(#f2f2f2, #dddddd);\n  background-repeat: repeat-x;\n  color: #000;\n  opacity: 0.8;\n}\n\nbutton.custom.disabled,\nbutton.custom[disabled] {\n  border-color: #ddd #ddd hsl(36, 0%, 85%);\n  background-color: hsl(36, 0%, 72%);\n  background-image: linear-gradient(#f2f2f2, #dddddd);\n  color: #666;\n  opacity: 0.6;\n  pointer-events: none;\n}\n\nbutton.custom:hover {\n  opacity: 1.0;\n}\n\nbutton.important {\n  padding: 0.6em 1em;\n  border: 1px solid transparent;\n  border-color: #ffcc7f #ffcc7f hsl(36, 100%, 73%);\n  border-radius: 3px;\n  background-color: hsl(36, 100%, 75%);\n  background-image: linear-gradient(#ffdca8, #ffcc7f);\n  background-repeat: repeat-x;\n  color: #222;\n  opacity: 0.8;\n}\n\nbutton.important:hover {\n  opacity: 1.0;\n}\n\n/* Not to be confused with button */\n.button {\n  border: none;\n  box-sizing: border-box;\n  cursor: pointer;\n  display: inline-block;\n  font-size: 150%;\n  margin: 0;\n  padding: 8px;\n}\n\n.fa {\n  display: inline-block;\n  font-family: FontAwesome;\n  font-style: normal;\n  font-weight: normal;\n  line-height: 1;\n  vertical-align: middle;\n}\n\n/* ui.css<css> ends here */"
  },
  {
    "path": "src/app/js/inject/StateManager.js",
    "content": "/*global removeFileNameFromPath, importFeedbackWidget, injectGradingEngine, loadLibraries, loadJSONTestsFromFile, registerTestSuites, turnOn, waitForTestRegistrations, loadUnitTests, chrome, injectedElementsOnPage, injectIntoDocument, importComponentsLibrary, removeInjectedFromDocument, removeFromDocument */\n\n/**\n * @fileOverview This file contains the StateManager Class.\n * @name StateManager.js<inject>\n * @author Cameron Pittman\n * @author Etienne Prud’homme\n * @license GPLv3\n * @todo Add a warning if the widget fails to initialize.\n */\n\n/**\n * State of the current Document.\n * @returns {Promise}\n * @throws {Error} An error coming from a Promise.\n */\nfunction StateManager() {\n  this.whitelist = {remote: [], local: []};\n  this.hostIsAllowed = false;\n  this.host = window.location.origin;\n  this.isChromium = window.navigator.vendor.toLocaleLowerCase().indexOf('google') !== -1;\n\n  if(this.host.search(/^(?:https?:)\\/\\/[^\\s\\.]/) !== -1)\n  {\n    this.type = 'remote';\n  } else if(this.host === 'null' || this.host.search('file://') !== -1) {\n    if(window.location.protocol === 'file:') {\n      this.host = removeFileNameFromPath(window.location.pathname);\n      this.type = 'local';\n    } else {\n      throw new Error('Unknown URL formatting error');\n    }\n  } else {\n    throw new Error('Unknown URL formatting error');\n  }\n\n  this.geInjected = false;\n\n  var currentlyInjecting = false;\n\n  /**\n   * Run a sequence of Promises to activate the Grading Engine.\n   * @returns {Promise}\n   * @throws {Error} An error coming from a Promise.\n   */\n  function runLoadSequence() {\n    var self = this;\n    if (!currentlyInjecting || self.geInjected) {\n      currentlyInjecting = true;\n      return importComponentsLibrary()\n        .then(importFeedbackWidget())\n        .then(injectGradingEngine)\n        .then(loadLibraries)\n        .then(loadJSONTestsFromFile)\n        .then(registerTestSuites)\n        .then(turnOn)\n      // This is to prevent UnitTests and other things in the page to execute before all tests are registered\n        .then(waitForTestRegistrations)\n        .then(loadUnitTests)\n        .then(function() {\n          self.geInjected = true;\n          currentlyInjecting = false;\n          return Promise.resolve();\n        }, function(e) {\n          // debugger;\n          console.log(e);\n          throw new Error('Something went wrong loading Udacity Feedback. Please reload.');\n        });\n    } else {\n      return Promise.resolve();\n    }\n  }\n\n  /**\n   * Checks if the host is allowed to execute the Grading Engine (and arbitrary tests).\n   * @returns {Promise}\n   */\n  this.isSiteOnWhitelist = function() {\n    var self = this;\n    self.isAllowed = false;\n    return new Promise(function(resolve, reject) {\n      var type = self.type;\n      chrome.storage.sync.get('whitelist', function(response) {\n        self.whitelist = response.whitelist || {remote: [], local: []};\n        // console.log(self.whitelist);\n        if (!(self.whitelist[type] instanceof Array)) {\n          self.whitelist[type] = [self.whitelist[type]];\n        }\n        if (self.whitelist[type].indexOf(self.host) > -1) {\n          self.isAllowed = true;\n        } else {\n          self.isAllowed = false;\n        }\n        resolve(self.isAllowed);\n      });\n    });\n  };\n\n  /**\n   * Adds the current Document host to the whitelist (local storage).\n   * @returns {Promise}\n   */\n  this.addSiteToWhitelist = function() {\n    var self = this;\n    return new Promise(function(resolve, reject) {\n      var type = self.type;\n      if(!type) {\n        reject();\n      }\n      var index = self.whitelist[type].indexOf(self.host);\n      if (index === -1) {\n        self.whitelist[type].push(self.host);\n      }\n      self.isAllowed = true;\n\n      var data = {whitelist: self.whitelist};\n      chrome.storage.sync.set(data, function() {\n        // debugger;\n        resolve();\n      });\n    });\n  };\n\n  /**\n   * Removes the current document host from the whitelist (local storage).\n   * @param {string} site - unused\n   * @returns {Promise}\n   */\n  this.removeSiteFromWhitelist = function(site) {\n    var self = this;\n    return new Promise(function(resolve, reject) {\n      var type = self.type;\n      var index = self.whitelist[type].indexOf(self.host);\n      if (index > -1) {\n        self.whitelist[type].splice(index, 1);\n      }\n      self.isAllowed = false;\n      var data = {whitelist: self.whitelist};\n      chrome.storage.sync.set(data, function() {\n        // debugger;\n        resolve();\n      });\n    });\n  };\n\n  /**\n   * Getter for {@link isAllowed} property. This property shows if the website is on the whitelist.\n   * @returns {boolean} The {@link isAllowed} property.\n   }\n   */\n  this.getIsAllowed = function() {\n    if(this.isChromium && this.type === 'local') {\n      return 'chrome_local_exception';\n    }\n    return this.isAllowed;\n  };\n\n  /**\n   * Method that activates the {@link runLoadSequence}.\n   * @returns {Promise}\n   */\n  this.turnOn = function() {\n    var self = this;\n    var g = document.querySelector('#ud-grader-options');\n    if (g) {\n      document.head.removeChild(g);\n    }\n    if (!self.geInjected) {\n      return runLoadSequence().then(function() {\n        Promise.resolve(true);\n      });\n    } else {\n      return Promise.resolve(true);\n    }\n  };\n\n  /**\n   * Method that desactivates the `test-widget`.\n   * @returns {Promise}\n   * @throws {it’s cool} do nothing\n   */\n  this.turnOff = function() {\n    var self = this;\n\n    removeFromDocument('ud-grader-options');\n    return injectIntoDocument('script', {\n      id: 'ud-grader-options',\n      // Reviewer: This is safe to pass.\n      innerHTML: 'UdacityFEGradingEngine.turnOff();' +\n        'delete window.UdacityFEGradingEngine;' +\n        'window.addEventListener(\"killUdacityFEGradingEngine\", function handler() {' +\n        '  window.removeEventListener(\"killUdacityFEGradingEngine\", handler, false);' +\n        '  window.dispatchEvent(new Event(\"killedGradingEngine\"));' +\n        '}, false);'\n    }, 'head')\n      .then(function() {\n        return new Promise(function(resolve, reject) {\n          window.addEventListener('killedGradingEngine', function handler() {\n            window.removeEventListener('killedGradingEngine', handler, false);\n            resolve();\n          }, false);\n          window.dispatchEvent(new Event('killUdacityFEGradingEngine'));\n        });\n      })\n      .then(function() {\n        removeInjectedFromDocument();\n        // wish I could unregister <test-widget>, but it doesn’t look like it’s possible at the moment\n        self.geInjected = false;\n      })\n      .catch(function(e) {\n        throw e;\n      });\n  };\n}\n\n// StateManager.js<inject> ends here\n"
  },
  {
    "path": "src/app/js/inject/helpers.js",
    "content": "/*global injectedElementsOnPage */\n\n/**\n * @fileOverview This file contains various functions that aren’t specific to the current extension.\n * @name helpers.js<inject>\n * @author Cameron Pittman\n * @author Etienne Prud’homme\n * @license GPLv3\n */\n\n/**\n * Adds elements to the main page.\n * @param  {String} tag       Type of element\n * @param  {Object} data      Key/value pairs you want to be assigned to as newTag[key] = value\n * @param  {Object} [location]  Set to “head” if you want the element to end up there. Default is body\n * @return {Promise}\n */\nfunction injectIntoDocument(tag, data, location) {\n  // debugger;\n  location = location || 'body';\n  return new Promise(function(resolve, reject) {\n    var newTag = document.createElement(tag);\n    // Firefox fix because it considers dynamically injected scripts as async\n    if(tag === 'script') {\n      newTag.async = false;\n      newTag.setAttribute('charset', 'utf-8');\n    }\n\n    if (data) {\n      for (var prop in data) {\n        newTag[prop] = data[prop];\n      }\n    }\n\n    if (!newTag.id) {\n      newTag.id = 'ud-' + Math.floor(Math.random() * 100000000).toString();\n    }\n\n    // for later removal\n    injectedElementsOnPage.push(newTag.id);\n\n    newTag.onload = function(e) {\n      resolve(e);\n    };\n    newTag.onerror = function(e) {\n      reject(e);\n    };\n    if (tag === 'script' && !newTag.src && (newTag.text || newTag.innerHTML)) {\n      resolve();\n    }\n    if (location === 'head') {\n      document.head.appendChild(newTag);\n    } else {\n      document.body.appendChild(newTag);\n    }\n  });\n}\n\n/**\n * Removes all injected elements from the document.\n */\nfunction removeInjectedFromDocument() {\n  injectedElementsOnPage.forEach(function(item) {\n    var element = document.getElementById(item);\n    var parent;\n\n    if(element !== null) {\n      parent = element.parentNode;\n      parent.removeChild(element);\n    }\n  });\n  injectedElementsOnPage = [];\n}\n\n\n/**\n * Removes a single resource from {@link injectedElementsOnPage}.\n * @param {String} id - The ID of the element.\n */\nfunction removeFromDocument(id) {\n  var element = document.getElementById(id);\n  var parent;\n  injectedElementsOnPage.splice(injectedElementsOnPage.indexOf(id), 1);\n\n  if(element !== null) {\n    parent = element.parentNode;\n    parent.removeChild(element);\n  }\n}\n\n/**\n * Removes a file name from a given path. It return the basename.\n * @param {string} path - The file path.\n * @returns {string} The basename of the path.\n */\nfunction removeFileNameFromPath(path) {\n  path = path.substr(0, path.lastIndexOf('/') + 1);\n\n  // If there’s a hashtag present, it can simulate a path\n  if(path.indexOf('#') !== -1) {\n    // Remove another URL part until there’s no hashtags\n    path = removeFileNameFromPath(path);\n  }\n  return path;\n}\n\n// helpers.js<inject> ends here\n"
  },
  {
    "path": "src/app/js/inject/inject.js",
    "content": "/*global removeFileNameFromPath, injectIntoDocument, chrome, StateManager */\n\n/**\n * @fileoverview This file manages the injection of several JavaScript files. It contains most procedure for injecting those files, but doesn’t handle the conditional injection part.\n * @name inject.js<inject>\n * @author Cameron Pittman\n * @author Etienne Prud’homme\n * @license GPLv3\n */\n\n/**\n * List of items id that were injected in the page. It is used to later remove them.\n * @type {string[]}\n */\nvar injectedElementsOnPage = [];\n\nvar runtimeError = null;\n\n/**\n * The meta tag that is used to load and activate a file of tests.\n * @type {Element}\n */\nvar metaTag = document.querySelector('meta[name=\"udacity-grader\"]');\n\nfunction importComponentsLibrary() {\n  var cScript = document.querySelector('script#components-lib');\n\n  if(!cScript) {\n    return injectIntoDocument('script', {\n      src: chrome.extension.getURL('lib/components.js'),\n      id: 'components-lib'\n    }, 'head');\n  } else {\n    return Promise.resolve();\n  }\n}\n\n/**\n * Finds Web Components templates.\n * @returns {Promise}\n */\nfunction importFeedbackWidget() {\n  var twScript = document.querySelector('script#udacity-test-widget');\n\n  if (!twScript) {\n    return injectIntoDocument('script', {\n      src: chrome.extension.getURL('app/templates/templates.js'),\n      id: 'udacity-test-widget'\n    }, 'head');\n  } else {\n    return Promise.resolve();\n  }\n}\n\n/**\n * Inject the Grading Engine inside the current Document.\n * @returns {Promise}\n */\nfunction injectGradingEngine() {\n  return injectIntoDocument('script', {\n    src: chrome.extension.getURL('app/js/libs/GE.js'),\n    id: 'udacity-front-end-feedback'\n  }, 'head');\n}\n\n/**\n * Load custom libraries for the Grading Engine (i.e. jsgrader.js). Currently only `jsgrader.js` is supported and allowed in the manifest.\n * @returns {Promise}\n */\nfunction loadLibraries() {\n  if (metaTag) {\n    var libraries = metaTag.getAttribute('libraries');\n  }\n\n  if (libraries) {\n    libraries = libraries.split(' ');\n  } else {\n    return Promise.resolve();\n  }\n\n  var loadedLibs = 0;\n  return Promise.all(\n    libraries.map(function(lib) {\n      return injectIntoDocument('script', {src: chrome.extension.getURL('app/js/libs/' + lib + '.js')}, 'head');\n    })\n  );\n}\n\n/**\n * Adds a unique GET ID in order to make the browser ignore the cache.\n * @param {String} url - A valid absolute URL.\n * @returns {String} The absolute URL and a unique GET ID.\n */\nfunction appendIDToURL(url) {\n  var _url = new URL(url);\n  var searchParams = _url.searchParams;\n  var paramName = 'udacityNoCache';\n\n  while(searchParams.has(paramName)) {\n    paramName += Math.floor(Math.random() * 10).toString();\n  }\n\n  searchParams.set(paramName, Math.floor(Math.random() * 100000000000).toString());\n  _url.searchParams = searchParams.toString;\n  return _url.toString();\n}\n\n/**\n * Loads asynchronously the JSON file containing the tests.\n * @returns {Promise}\n */\nfunction loadJSONTestsFromFile() {\n  if (metaTag) {\n    return new Promise(function(resolve, reject) {\n      // http://stackoverflow.com/a/14274828\n      var xmlhttp = new XMLHttpRequest();\n      // The complete path to the document excluding the file name (http://example.com/mydir/ for http://example.com/mydir/file.html)\n      var documentBase = removeFileNameFromPath(document.URL);\n      var url = metaTag.content;\n      var fileBase = '';\n\n      // If it’s not an absolute URL\n      if(url.search(/^(?:https?|file):\\/\\//) === -1) {\n        // If it’s protocol relative URL (i.e. //example.com)\n        if(url.search(/^\\/\\//) !== -1) {\n          // The window must at least use one of those protocols\n          switch(window.location.protocol) {\n          case 'http:':\n          case 'https:':\n          case 'file:':\n            url = window.location.protocol + url;\n            break;\n          default:\n            runtimeError = 'unknown_protocol';\n            console.warn('Unknown URL protocol. Supported protocols are: http, https and (local) file');\n            reject(false);\n          }\n        } else {\n          // it’s probably a relative path (may be garbage)\n          url = documentBase + url;\n        }\n      }\n\n      url = appendIDToURL(url);\n\n      // Extract the file path (http://example.com/mydir/ for http://example.com/mydir/file.html)\n      fileBase = url.substr(0, url.lastIndexOf('/') + 1);\n\n      if(fileBase !== documentBase) {\n        runtimeError = 'invalid_origin';\n        console.warn('Invalid JSON file origin');\n        reject(false);\n      }\n\n      xmlhttp.onreadystatechange = function() {\n        if (xmlhttp.status === 200 && xmlhttp.readyState === 4) {\n          // DANGER! Checks if that it wasn’t a redirection\n          if(xmlhttp.responseURL !== url) {\n            runtimeError = 'redirection';\n            console.warn('The JSON request received a redirection. Possible cross-origin request attempt');\n            reject(false);\n          }\n          resolve(xmlhttp.responseText);\n        } else if (xmlhttp.status >= 400) {\n          reject(false);\n        }\n      };\n      xmlhttp.open('GET', url, true);\n      xmlhttp.send();\n    });\n  } else {\n    return Promise.resolve(false);\n  }\n}\n\n// You don’t have access to the GE here, but you can inject a script into the document that does.\n/**\n * Register test suites from the JSON data.\n * @param {string} json - JSON containing tests for the Grading Engine.\n * @returns {Promise}\n * @throws {Error} Errors about the JSON file.\n */\nfunction registerTestSuites(json) {\n  if (!json) {\n    return Promise.resolve();\n  }\n  var errorMsg = null;\n  // validating the JSON\n  try {\n    if (json.length > 0) {\n      JSON.parse(json);\n    }\n  } catch (e) {\n    if (json.indexOf('\\\\') > -1) {\n      errorMsg = 'Are you trying to use “\\\\” in a RegEx? Try using \\\\\\\\ instead.';\n    } else {\n      errorMsg = 'Invalid JSON file format.';\n    }\n  }\n  try {\n    json = JSON.stringify(json);\n  } catch (e) {\n    errorMsg = 'Invalid JSON format.';\n  }\n\n  if (errorMsg) {\n    alert(errorMsg);\n    throw new Error(errorMsg);\n  } else {\n    return injectIntoDocument('script', {text: 'UdacityFEGradingEngine.registerSuites(' + json + ');'}, 'head');\n  }\n}\n\n/**\n * Checks and injects custom Unit Tests.\n * @returns {Promise}\n */\nfunction loadUnitTests() {\n  var unitTests = null;\n  if (metaTag) {\n    unitTests = metaTag.getAttribute('unit-tests');\n  }\n  if (!unitTests) {\n    return Promise.resolve();\n  }\n\n  return injectIntoDocument('script', {src: unitTests, defer: 'defer'});\n}\n\n/**\n * Activates the Grading Engine by injecting itself in the Document. Not to be confused with {@link StateManager.turnOn}. This method is called from {@link StateManager~runLoadSequence}.\n * @returns {Promise}\n */\nfunction turnOn() {\n  // console.log('Turned on from turnOn()');\n  return injectIntoDocument('script', {\n    id: 'ud-grader-options',\n    // Reviewer: Because we need to access the window script context, it’s\n    // necessary to inject the script that way. A content-script doesn’t have\n    // access to the window scripting context.\n    innerHTML: 'UdacityFEGradingEngine.turnOn();'\n  }, 'head');\n}\n\n/**\n * Stops {@link StateManager~runLoadSequence} until all tests are loaded. This is necessary because the Grading Engine is activated thought the page context. It isn’t a content script like this file.\n * @todo Add a timeout. If (for some reason) the event is never fired, it would probably block the widget.\n * @returns {Promise} A `Promise` that fulfills when all tests are loaded\n */\nfunction waitForTestRegistrations() {\n  return new Promise(function(resolve, reject) {\n    window.addEventListener('tests-registered', function(data) {\n      // console.log('tests-registered received');\n      return resolve();\n    });\n  });\n}\n\n// StateManager() was here\n\nvar stateManager = new StateManager();\n\n/**\n * Wait for messages from browser action.\n * @param {Object} message - Object containing a `data` and a `type` property.\n * @param {MessageSender} sender - Information about the Script context.\n * @param {function} sendResponse - Function to call when a response is received.\n */\nchrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {\n  switch (message.type) {\n  case 'json':\n    // A JSON test file was passed to the action page\n    registerTestSuites(message.data);\n    break;\n  case 'on-off':\n    // The action page checkbox was toggled\n    if (message.data === 'on') {\n      stateManager.addSiteToWhitelist()\n        .then(stateManager.turnOn);\n    } else if (message.data === 'off') {\n      stateManager.removeSiteFromWhitelist()\n        .then(stateManager.turnOff);\n    }\n    break;\n  case 'background-wake':\n    if(runtimeError) {\n      sendResponse(runtimeError);\n    }\n    // The action page is requesting infos about the current host\n    sendResponse(stateManager.getIsAllowed());\n    break;\n  default:\n    // Just in case of future bad implementation\n    console.warn('invalid message type for: %s from %s', message, sender);\n    break;\n  }\n});\n\n/**\n * for first load\n */\nwindow.addEventListener('GE-on', function() {\n  if (stateManager.isAllowed) {\n    stateManager.turnOn();\n  }\n});\n\n// Check if the site is on the Whitelist on page load\nstateManager.isSiteOnWhitelist()\n  .then(function(isAllowed) {\n    if (isAllowed) {\n      stateManager.turnOn();\n    }\n  });\n\n// inject.js<inject> ends here\n"
  },
  {
    "path": "src/app/js/libs/jsgrader.js",
    "content": "/**\n * @fileOverview This file contains the JSGrader library to test the JavaScript context.\n * @name jsgrader.js<libs>\n * @author Cameron Pittman\n * @license GPLv3\n */\nvar Grader = (function() {\n\n  // http://stackoverflow.com/questions/1068834/object-comparison-in-javascript?lq=1\n  function deepCompare () {\n    var i, l, leftChain, rightChain;\n\n    function compare2Objects (x, y) {\n      var p;\n\n      // remember that NaN === NaN returns false\n      // and isNaN(undefined) returns true\n      if (isNaN(x) && isNaN(y) && typeof x === 'number' && typeof y === 'number') {\n        return true;\n      }\n\n      // Compare primitives and functions.\n      // Check if both arguments link to the same object.\n      // Especially useful on step when comparing prototypes\n      if (x === y) {\n        return true;\n      }\n\n      // Works in case when functions are created in constructor.\n      // Comparing dates is a common scenario. Another built-ins?\n      // We can even handle functions passed across iframes\n      if ((typeof x === 'function' && typeof y === 'function') ||\n        (x instanceof Date && y instanceof Date) ||\n        (x instanceof RegExp && y instanceof RegExp) ||\n        (x instanceof String && y instanceof String) ||\n        (x instanceof Number && y instanceof Number)) {\n          return x.toString() === y.toString();\n      }\n\n      // At last checking prototypes as good a we can\n      if (!(x instanceof Object && y instanceof Object)) {\n        return false;\n      }\n\n      if (x.isPrototypeOf(y) || y.isPrototypeOf(x)) {\n        return false;\n      }\n\n      if (x.constructor !== y.constructor) {\n        return false;\n      }\n\n      if (x.prototype !== y.prototype) {\n        return false;\n      }\n\n      // Check for infinitive linking loops\n      if (leftChain.indexOf(x) > -1 || rightChain.indexOf(y) > -1) {\n         return false;\n      }\n\n      // Quick checking of one object beeing a subset of another.\n      // todo: cache the structure of arguments[0] for performance\n      for (p in y) {\n        if (y.hasOwnProperty(p) !== x.hasOwnProperty(p)) {\n          return false;\n        }\n        else if (typeof y[p] !== typeof x[p]) {\n          return false;\n        }\n      }\n\n      for (p in x) {\n        if (y.hasOwnProperty(p) !== x.hasOwnProperty(p)) {\n          return false;\n        }\n        else if (typeof y[p] !== typeof x[p]) {\n          return false;\n        }\n\n        switch (typeof (x[p])) {\n          case 'object':\n          case 'function':\n            leftChain.push(x);\n            rightChain.push(y);\n\n            if (!compare2Objects (x[p], y[p])) {\n              return false;\n            }\n\n            leftChain.pop();\n            rightChain.pop();\n            break;\n\n          default:\n            if (x[p] !== y[p]) {\n              return false;\n            }\n            break;\n        }\n      }\n\n      return true;\n    }\n\n    if (arguments.length < 1) {\n      return true; //Die silently? Don’t know how to handle such case, please help...\n      // throw \"Need two or more arguments to compare\";\n    }\n\n    for (i = 1, l = arguments.length; i < l; i++) {\n\n      leftChain = []; //Todo: this can be cached\n      rightChain = [];\n\n      if (!compare2Objects(arguments[0], arguments[i])) {\n        return false;\n      }\n    }\n    return true;\n  }\n\n  function Queue (grader) {\n    this.grader = grader;\n    this.gradingSteps = [];\n    this.flushing = false;\n    this.alwaysGo = false;\n  };\n\n  Queue.prototype = {\n    add: function(callback, messages, keepGoing) {\n      if (keepGoing !== false) {\n        keepGoing = true;\n      }\n\n      if (!callback) {\n        throw new Error(\"Every test added to the queue must have a valid function.\");\n      }\n\n      this.gradingSteps.push({\n        callback: callback,\n        isCorrect: false,\n        wrongMessage: messages.wrongMessage || null,\n        comment: messages.comment || null,\n        category: messages.category || null,\n        keepGoing: keepGoing\n      });\n    },\n\n    _flush: function () {\n      if (!this.flushing) {\n        this.flushing = true;\n      }\n      this.step();\n    },\n\n    clear: function () {\n      this.flushing = false;\n      this.gradingSteps = [];\n      this.grader.endTests();\n    },\n\n    step: function () {\n      var self = this;\n      if (this.gradingSteps.length === 0) {\n        this.clear();\n      }\n\n      function executeInPromise (fn) {\n        return new Promise(function (resolve, reject) {\n          if (fn) {\n            try {\n              var result = fn();\n            } catch (e) {\n              self.clear();\n              console.log(e);\n            }\n          }\n          resolve(result);\n        });\n      };\n\n      function takeNextStep (test, result) {\n        test.isCorrect = result;\n\n        self.registerResults(test);\n\n        if (test.isCorrect || test.keepGoing || self.alwaysGo) {\n          self.step();\n        } else {\n          self.clear();\n        }\n      };\n\n      if (this.flushing) {\n        var test = this.gradingSteps.shift();\n\n        if (this.grader.async) {\n          executeInPromise(test.callback).then(function (resolve) {\n            takeNextStep(test, resolve);\n          });\n        } else if (!this.grader.async) {\n          try {\n            var result = test.callback();\n          } catch (e) {\n            console.log(e);\n            throw new Error();\n          }\n          takeNextStep(test, result);\n        }\n\n      }\n    },\n\n    registerResults: function (test) {\n      this.grader.registerResults(test);\n    }\n  };\n\n  function Grader (type, categoryMessages) {\n    var self = this;\n    this.specificFeedback = [];\n    this.comments = [];\n    this.isCorrect = false;\n    this.correctHasChanged = false;\n    this.queue = new Queue(self);\n    this.async = false;\n    this.categoryMessages = null;\n    this.generalFeedback = [];\n    this.onresult = function () {};\n\n    for (n in arguments) {\n      switch (typeof arguments[n]) {\n        case 'string':\n          if (arguments[n] === 'async') {\n            this.async = true;\n          } else if (arguments[n] === 'sync') {\n            this.async = false;\n          } else {\n            throw new Error(\"Invalid type argument in Grader constructor\");\n          }\n          break;\n        case 'object':\n          this.categoryMessages = arguments[n];\n          break;\n        default:\n          throw new TypeError(\"Invalid argument in Grader constructor\");\n          break;\n      }\n    }\n  };\n\n  Grader.prototype = {\n    addTest: function (callback, messages, keepGoing) {\n      this.queue.add(callback, messages, keepGoing);\n    },\n\n    runTests: function (options) {\n      if (options) {\n        this.queue.alwaysGo = options.ignoreCheckpoints || false;\n      }\n      this.queue._flush();\n    },\n\n    endTests: function () {\n      if (this.queue.flushing) {\n        this.queue.clear();\n      } else {\n        var results = this.gatherResults();\n        this.onresult(results);\n      }\n    },\n\n    registerResults: function (test) {\n      this.generateSpecificFeedback(test);\n      this.generateGeneralFeedback(test);\n      this.setCorrect(test);\n    },\n\n    generateSpecificFeedback: function (test) {\n      if (!test.isCorrect && test.wrongMessage) {\n        this.addSpecificFeedback(test.wrongMessage);\n      } else if (test.isCorrect && test.comment) {\n        this.addComment(test.comment);\n      }\n    },\n\n    generateGeneralFeedback: function (test) {\n      if (!test.isCorrect && test.category) {\n        if (this.generalFeedback.indexOf(this.categoryMessages[test.category]) === -1) {\n          this.generalFeedback.push(this.categoryMessages[test.category]);\n        }\n      }\n    },\n\n    setCorrect: function (test) {\n      if (this.correctHasChanged) {\n        this.isCorrect = this.isCorrect && test.isCorrect;\n      } else {\n        this.correctHasChanged = true;\n        this.isCorrect = test.isCorrect;\n      }\n    },\n\n    addSpecificFeedback: function (feedback) {\n      this.specificFeedback.push(feedback);\n    },\n\n    addComment: function (feedback) {\n      this.comments.push(feedback);\n    },\n\n    gatherResults: function () {\n      var self = this;\n      return {\n        isCorrect: self.isCorrect,\n        testFeedback: self.specificFeedback.concat(self.generalFeedback),\n        testComments: self.comments\n      };\n    },\n\n    getFormattedWrongMessages: function (separator) {\n      var allMessages, message;\n\n      allMessages = this.specificFeedback.concat(this.generalFeedback);\n      message = allMessages.join(separator);\n\n      return message;\n    },\n\n    getFormattedComments: function (separator) {\n      return this.comments.join(separator);\n    },\n\n    isType: function (value, expectedType) {\n      var isCorrect = false;\n\n      if (typeof value !== expectedType) {\n\n        if (typeof value === 'function') {\n          value = value.name;\n        };\n\n        isCorrect = false;\n      } else if (typeof value === expectedType){\n        isCorrect = true;\n      }\n      return isCorrect;\n    },\n\n    isInstance: function (value, expectedInstance) {\n      var isCorrect = false;\n\n      if (value instanceof expectedInstance !== true) {\n\n        isCorrect = false;\n      } else if (value instanceof expectedInstance === true){\n        isCorrect = true;\n      }\n      return isCorrect;\n    },\n\n    isValue: function (value1, value2) {\n      var isCorrect = false;\n\n      if (!deepCompare(value1, value2)) {\n        isCorrect = false;\n      } else if (deepCompare(value1, value2)) {\n        isCorrect = true;\n      }\n      return isCorrect;\n    },\n\n    isInRange: function (value, lower, upper) {\n      var isCorrect = false;\n\n      if (typeof value !== 'number' || isNaN(value)) {\n        isCorrect = false;\n      } else if (value > upper || value < lower) {\n        isCorrect = false;\n\n      } else if (value < upper || value > lower) {\n        isCorrect = true;\n      }\n      return isCorrect;\n    },\n\n    isSet: function (value) {\n      var isCorrect = false;\n\n      if (value === undefined) {\n        isCorrect = false;\n\n      } else {\n        isCorrect = true;\n      }\n      return isCorrect;\n    },\n\n    isjQuery: function (elem) {\n      // could use obj.jquery, which will only return true if it is a jquery object\n      var isjQ = false;\n      if (elem instanceof $) {\n        isjQ = true;\n      }\n      return isjQ;\n    },\n\n    hasCorrectTag: function (elem, tag) {\n      if (!this.isjQuery(elem)) {\n        elem = $(elem);\n      }\n      var hasTag = false;\n      if (elem.is(tag)) {\n        hasTag = true;\n      }\n      return hasTag;\n    },\n\n    hasCorrectClass: function (elem, className) {\n      if (!this.isjQuery(elem)) {\n        elem = $(elem);\n      }\n      var hasClass = false;\n      if (elem.hasClass(className)) {\n        hasClass = true;\n      }\n      return hasClass;\n    },\n\n    hasCorrectId: function (elem, id) {\n      if (!this.isjQuery(elem)) {\n        elem = $(elem);\n      }\n      if (elem.is('#' + id)) return true;\n      return false;\n    },\n\n    hasCorrectText: function (elem, text) {\n      if (!this.isjQuery(elem)) {\n        elem = $(elem);\n      }\n      var hasText = false;\n      var re = new RegExp(text);\n      if (elem.text().match(re)) {\n        hasText = true;\n      }\n      return hasText;\n    },\n\n    hasAttr: function (elem, attrName, correctAttr) {\n      var isCorrect = false;\n      if (!this.isjQuery(elem)) {\n        elem = $(elem);\n      }\n      if (correctAttr && elem.attr(attrName) === correctAttr) {\n        isCorrect = true;\n      } else if (!correctAttr && elem.attr(attrName)) {\n        isCorrect = true;\n      }\n      return isCorrect;\n    },\n\n    hasCorrectLength: function (elems, _length) {\n      if (!this.isjQuery(elems)) {\n        elems = $(elems);\n      }\n      var correctLength = false;\n      var cLength = elems.length;\n      if (cLength === _length) {\n        correctLength = true;\n      }\n      return correctLength;\n    },\n\n    isCorrectElem: function (elem, correctElem) {\n      if (!this.isjQuery(elem)) {\n        elem = $(elem);\n      }\n      var is = false;\n      if (elem.is(correctElem)) {\n        is = true;\n      }\n      return is;\n    },\n\n    isCorrectCollection: function (collection, correctCollection) {\n      if (!this.isjQuery(elem)) {\n        elem = $(elem);\n      }\n      var is = false;\n      if (collection.is(correctCollection)) {\n        is = true;\n      }\n      return is;\n    },\n\n    hasCorrectStyle: function (elem, cssProperty, _correctStyle) {\n      if (!this.isjQuery(elem)) {\n        elem = $(elem);\n      }\n      var hasCorrectStyle = false;\n      var currentStyle = elem.css(cssProperty);\n      if (currentStyle  === _correctStyle) {\n        hasCorrectStyle = true;\n      }\n      return hasCorrectStyle;\n    },\n\n    doesExistInParent: function (elem, parentElem) {\n      if (!this.isjQuery(elem)) {\n        elem = $(elem);\n      }\n      if (!this.isjQuery(parentElem)) {\n        parentElem = $(parentElem);\n      }\n      var inParent = false;\n      if (parentElem.find(elem).length > 0) {\n        inParent = true;\n      }\n      return inParent;\n    },\n\n    elemDoesExist: function (elem) {\n      if (!this.isjQuery(elem)) {\n        elem = $(elem);\n      }\n      var exists = false;\n      if (elem.length > 0) {\n        exists = true;\n      }\n      return exists;\n    },\n\n    areSiblings: function (elem1, elem2) {\n      if (!this.isjQuery(elem1)) {\n        elem1 = $(elem1);\n      }\n      if (!this.isjQuery(elem2)) {\n        elem2 = $(elem2);\n      }\n      var siblingLove = false;\n      if (elem1.siblings(elem2).length > 0) {\n        siblingLove = true;\n      }\n      return siblingLove;\n    },\n\n    isImmediateChild: function (elem, parentElem) {\n      var isCorrect = false;\n      if (this.isjQuery(elem)) {\n        throw new Error(\"elem needs to be a string for Grader.isImmediateChild()\");\n      }\n      if (!this.isjQuery(parentElem)) {\n        parentElem = $(parentElem);\n      }\n      if (parentElem.children(elem).length > 0) {\n        isCorrect = true;\n      }\n      return isCorrect;\n    },\n\n    hasParent: function (elem, parentElem) {\n      var isCorrect = false;\n      if (this.isjQuery(parentElem)) {\n        throw new Error(\"parentElem needs to be a string for Grader.hasParent()\");\n      }\n      if (!this.isjQuery(elem)) {\n        elem = $(elem);\n      }\n      if (elem.closest(parentElem).length > 0) {\n        isCorrect = true;\n      }\n      return isCorrect;\n    },\n\n    sendResultsToExecutor: function () {\n      var output = {\n        isCorrect: false,\n        test_feedback: \"\",\n        test_comments: \"\",\n        congrats: \"\"\n      };\n\n      for (arg in arguments) {\n        var thisIsCorrect = arguments[arg].isCorrect;\n        var thisTestFeedback = arguments[arg].getFormattedWrongMessages();\n        var thisTestComment = arguments[arg].getFormattedComments();\n        if (typeof thisIsCorrect !== 'boolean') {\n          thisIsCorrect = false;\n        }\n\n        switch (arg) {\n          case '0':\n            output.congrats = arguments[arg];\n          case '1':\n            output.isCorrect = thisIsCorrect;\n            output.test_feedback = thisTestFeedback;\n            output.test_comments = thisTestComment;\n            break;\n          default:\n            output.isCorrect = thisIsCorrect && output.isCorrect;\n            if (output.test_feedback !== \"\") {\n              output.test_feedback = [output.test_feedback, thisTestFeedback].join('\\n');\n            } else {\n              output.test_feedback = thisTestFeedback;\n            }\n\n            if (output.test_comments !== \"\") {\n              output.test_comments = [output.test_comments, thisTestFeedback].join('\\n');\n            } else {\n              output.test_comments = thisTestComment;\n            }\n            break;\n        }\n      }\n      output = JSON.stringify(output);\n      console.info(\"UDACITY_RESULT:\" + output);\n    }\n  };\n  return Grader;\n})();\n\n// jsgrader.js<libs> ends here\n"
  },
  {
    "path": "src/app/options/index.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Udacity Feedback</title>\n    <style>\n     #whitelist-entry-template {\n         display: none;\n     }\n    </style>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <link rel=\"stylesheet\" href=\"../css/common.css\" />\n    <link rel=\"stylesheet\" href=\"../css/fonts.css\" />\n    <link rel=\"stylesheet\" href=\"../css/options.css\" />\n    <link rel=\"stylesheet\" href=\"../css/ui.css\" />\n  </head>\n  <body>\n    <table class=\"whitelist\">\n      <colgroup><col><col></colgroup>\n      <thead>\n        <tr class=\"whitelist-title\">\n          <th colspan=\"2\"><span id=\"back-button\" class=\"button fa\">&#xf112;</span>Whitelist</th>\n        </tr>\n        <tr class=\"whitelist-type\">\n          <th colspan=\"2\">Remote hosts<span id=\"remote-add\" class=\"add-remote-entry button fa\" title=\"Add remote host\">&#xf196;</span></th>\n        </tr>\n      </thead>\n      <tbody id=\"remote-whitelist\">\n        <tr id=\"whitelist-entry-template\" class=\"whitelist-row\">\n          <td class=\"entry\">host</td>\n          <td class=\"remove\"><span class=\"remove-entry button fa\" title=\"Remove\">&#xf00d;</span></td>\n        </tr>\n        <tr class=\"whitelist-placeholder\">\n          <td colspan=\"2\"><span class=\"whitelist-message\">Nothing to show here</span><span class=\"button fa\">&#xf119;</span></td>\n        </tr>\n      </tbody>\n      <thead>\n        <tr class=\"whitelist-type\">\n          <th colspan=\"2\">Local directories<span id=\"local-add\" class=\"add-remote-entry button fa\" title=\"Add local directory\">&#xf196;</span></th>\n        </tr>\n      </thead>\n      <tbody id=\"local-whitelist\">\n        <tr class=\"whitelist-placeholder\">\n          <td colspan=\"2\"><span class=\"whitelist-message\">Nothing to show here</span><span class=\"button fa\">&#xf119;</span></td>\n        </tr>\n      </tbody>\n    </table>\n    <main>\n      <p class=\"title\">Help</p>\n      <p class=\"description\">Usage</p>\n      <p class=\"about\">Not sure what how to make it work? Try the <a href=\"http://labs.udacity.com/udacity-feedback-extension/\">walkthrough</a>.</p>\n      <p class=\"description\">Reporting bugs</p>\n      <p class=\"about\">Because this extension tries to supports multiple browsers, it’s not unusual to find bugs when a new browser version rolls out. For any suggestions or bug reports, please make a <a href=\"https://github.com/udacity/frontend-grading-engine/issues\" href=\"\">new issue</a> on the GitHub platform. Make sure to include your browser version and the currently installed version of the extension.</p>\n      <p class=\"description\">Contact</p>\n      <p class=\"about\">You can contact us at <code>udacityfeedback@udacity.com</code>.<p>\n    </main>\n    <footer>\n      <p class=\"title\">About</p>\n      <p class=\"description\"><a title=\"About the extension\" href=\"https://github.com/udacity/frontend-grading-engine\">Udacity Front End Feedback<span class=\"button fa\">&#xf08e;</span></a></p>\n      <p class=\"about\">Immediate, visual feedback about any website’s HTML, CSS and JavaScript.</p>\n      <p class=\"about\">Version <code id=\"extension-version\"></code> for <span id=\"browser-name\"></span></p>\n    </footer>\n    <script src=\"options.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "src/app/options/options.js",
    "content": "/*global chrome, browserName */\n\n/**\n * @fileOverview This file contains the option page for adding/removing websites from the whitelist.\n * @name options.js<options>\n * @author Cameron Pittman\n * @author Etienne Prud’homme\n * @license GPLv3\n * @todo remove trailing / from URLs\n */\n\nvar remoteWhitelist = document.querySelector('#remote-whitelist');\nvar localWhitelist = document.querySelector('#local-whitelist');\nvar isChromium = window.navigator.vendor.toLocaleLowerCase().indexOf('google') !== -1;\n\nfunction StateManager() {\n  this.whitelist = {remote: [], local: []};\n};\n\nStateManager.prototype = {\n  /**\n   * Get the whitelist from the storage.\n   * @returns {Promise} A promise that resolves when the data is received.\n   */\n  getWhitelist: function() {\n    var self = this;\n    return new Promise(function (resolve, reject) {\n      chrome.storage.sync.get('whitelist', function (response) {\n        self.whitelist = response.whitelist || {remote: [], local: []};\n\n        if (!(self.whitelist.remote instanceof Array ||\n              Object.prototype.toString.call(self.whitelist.remote) === '[object Array]')) {\n          self.whitelist.remote = [self.whitelist.remote];\n        }\n        if (!(self.whitelist.local instanceof Array ||\n              Object.prototype.toString.call(self.whitelist.remote) === '[object Array]')) {\n          self.whitelist.local = [self.whitelist.local];\n        }\n        resolve(self.whitelist);\n      });\n    });\n  },\n  /**\n   * Add a given site to the stored whitelist and the {@link StateManager.whitelist}.\n   * @param {string} site - A URL to add to the whitelist.\n   * @param {string} type - The type of site. It either be: `remote` or `local`.\n   * @returns {Promise} A promise that resolves when the data is set.\n   */\n  addSiteToWhitelist: function(site, type) {\n    var self = this;\n    return new Promise(function (resolve, reject) {\n      if(type === 'remote') {\n        if(site.search(/^(?:https?:)\\/\\/[^\\s\\.]/) === -1) {\n          reject('The site is not a valid URL. The URL must at least contains the http:// or https:// scheme');\n        }\n        resolve();\n      } else if(type === 'local') {\n        if(site.search(/^file:\\/\\/\\/?[^\\s\\.]/) === -1) {\n          reject('The site is not a valid local URL. The URL must at least contains the file:// scheme');\n        }\n        resolve();\n      } else {\n        reject('type');\n      }}).then(function() {\n\n        var index = self.whitelist[type].indexOf(site);\n        if (index === -1) {\n          self.whitelist[type].push(site);\n        }\n        self.isAllowed = true;\n        var data = {whitelist: {remote: self.whitelist.remote, local: self.whitelist.local}};\n        chrome.storage.sync.set(data, function () {\n          Promise.resolve();\n        });\n      });\n  },\n  /**\n   * Remove a given site from the stored whitelist and the {@link StateManager.whitelist}.\n   * @param {string} site - A URL to remove from the whitelist.\n   * @param {string} type - The type of site. It either be: `remote` or `local`.\n   * @returns {Promise} A promise when the data is set.\n   */\n  removeSiteFromWhitelist: function(site, type) {\n    var self = this;\n    return new Promise(function (resolve, reject) {\n      if(type !== 'remote' && type !== 'local') {\n        reject('type');\n      }\n\n      var index = self.whitelist[type].indexOf(site);\n      if (index > -1) {\n        self.whitelist[type].splice(index, 1);\n      }\n      self.isAllowed = false;\n      var data = {whitelist: {remote: self.whitelist.remote, local: self.whitelist.local}};\n      chrome.storage.sync.set(data, function () {\n        resolve();\n      });\n    });\n  }\n};\n\n/**\n * Adds buttons to add entries.\n */\nfunction initDisplay() {\n  var manifest = chrome.runtime.getManifest();\n  var extensionVersion = document.getElementById('extension-version');\n  extensionVersion.textContent = manifest.version;\n  document.getElementById('browser-name').textContent = browserName;\n\n  var remoteAdd = document.getElementById('remote-add');\n  remoteAdd.addEventListener('click', function handler(event) {\n    newInputEntry('remote');\n  });\n\n  var localAdd = document.getElementById('local-add');\n  if(localAdd !== null) {\n    localAdd.addEventListener('click', function handler(event) {\n      newInputEntry('local');\n    });\n  }\n}\n\n/**\n * Removes entries from the whitelist table.\n */\nfunction cleanDisplay() {\n  var entryCollection = document.getElementsByClassName('whitelist-row');\n  var entries = [], i, len;\n\n  // An HTMLCollection would remove its item if we used\n  // `entryCollection[i].remove()` thus decreasing the lenght. That’s why we\n  // convert the collection to an Array\n  for(i=0, len=entryCollection.length; i<len; i++) {\n    if(entryCollection[i].id !== 'whitelist-entry-template') {\n      entries.push(entryCollection[i]);\n    }\n  }\n\n  for(i=0, len=entries.length; i<len; i++) {\n    entries[i].remove();\n  }\n}\n\n/**\n * Updates the whitelist table.\n */\nfunction refreshDisplay() {\n  cleanDisplay();\n\n  refreshSection('remote');\n  refreshSection('local');\n\n  function refreshSection(type) {\n    var whitelist = stateManager.whitelist[type];\n    var isEmpty = true,\n        newTypeEntry = type === 'remote' ? newRemoteEntry : newLocalEntry,\n        whitelistElem;\n\n    for(var i=0, len=whitelist.length; i<len; i++) {\n      if(whitelist[i]) {\n        newTypeEntry(whitelist[i]);\n        isEmpty = false;\n      }\n    }\n\n    var placeholderDisplay = isEmpty ? 'table-row' : 'none';\n    whitelistElem = document.getElementById(type + '-whitelist');\n    whitelistElem.getElementsByClassName('whitelist-placeholder')[0].style.display = placeholderDisplay;\n  }\n}\n\n/**\n * Return a new entry for the whitelist created from a template. The entry should isn’t attached to the document.\n * @param {string} data - The text node of the entry (`.entry`).\n * @param {string} type - The type of entry. It either be: `add-entry`, `remote` or `local`.\n * @returns {HTMLElement} The newly created entry.\n */\nfunction newEntry(data, type) {\n  var template = document.getElementById('whitelist-entry-template');\n  var entry = template.cloneNode(true);\n  entry.removeAttribute('id');\n\n  if(type === 'add-entry') {\n    entry.id = 'add-entry';\n  }\n\n  entry.getElementsByClassName('entry')[0].textContent = data;\n  entry.getElementsByClassName('remove-entry')[0].addEventListener('click', function handler(event) {\n    event.preventDefault();\n    entry.remove();\n    window.dispatchEvent(new CustomEvent('remove', {detail: {type: type, data: data}}));\n  });\n  return entry;\n}\n\n/**\n * Adds and attach a new entry in the **remote** section of the whitelist table.\n * @param {string} url - The URL (text) of the entry.\n * @returns {HTMLElement} A reference to the newly attached element.\n */\nfunction newRemoteEntry(url) {\n  return remoteWhitelist.appendChild(newEntry(url, 'remote'));\n}\n\n/**\n * Adds and attach a new entry in the **local** section of the whitelist table.\n * @param {string} url - The URL (text) of the entry.\n * @returns {HTMLElement} A reference to the newly attached element.\n */\nfunction newLocalEntry(url) {\n  return localWhitelist.appendChild(newEntry(url, 'local'));\n}\n\n/**\n * Creates an new empty entry with a text input to fill and remove an existing one if already present.\n * @param {string} type - The type of entry for the whitelist. It can either be: `local` or `remote`\n * @todo\n */\nfunction newInputEntry(type) {\n  var emptyEntry = document.getElementById('add-entry');\n\n  if(emptyEntry !== null) {\n    emptyEntry.remove();\n  }\n\n  var input = document.createElement('input');\n  emptyEntry = newEntry('', 'add-entry');\n\n  if(type === 'local') {\n    // TODO: How to handle directories?\n    input.className = 'local-add-input';\n    emptyEntry = localWhitelist.appendChild(emptyEntry);\n  } else if(type === 'remote') {\n    emptyEntry = remoteWhitelist.appendChild(emptyEntry);\n    input.className = 'remote-add-input';\n  } else {\n    throw new TypeError('The type argument isn’t valid');\n  }\n\n  // Actually attach the input\n  emptyEntry.getElementsByClassName('entry')[0].appendChild(input);\n\n  // TODO: Check correct values\n  input.addEventListener('keyup', function handler(event) {\n    if (event.keyCode === 13) {\n      if(event.target.value) {\n        var site = event.target.value;\n        stateManager.addSiteToWhitelist(site, type)\n          .then(refreshDisplay)\n          .then(function() {\n            emptyEntry.remove();\n          })\n          .catch(function(message) {\n            if(message === 'type') {\n              message = 'Unknown error';\n            }\n            // TODO: Implement something less annoying\n            window.alert(message);\n          });\n      }\n    }\n  }, false);\n  input.focus();\n  // console.log(emptyEntry);\n}\n\n/**\n * Adds a warning to Chromium/Chrome users that loading a local file can’t work without doing it manually.\n */\nfunction chromiumInit() {\n  if(isChromium) {\n    var localPlaceholder = document.querySelector('#local-whitelist td .whitelist-message');\n    localPlaceholder.textContent = 'Chrome doesn’t support loading local files asynchronously. You must manually load the test file. Sorry for the inconvenience ';\n    localPlaceholder.parentElement.classList = localPlaceholder.parentElement.classList + ' chromium-message';\n    // Removes the plus sign\n    document.getElementById('local-add').remove();\n  }\n}\n\nvar stateManager = new StateManager();\nstateManager.getWhitelist()\n  .then(refreshDisplay)\n  .then(initDisplay)\n  .then(chromiumInit);\n\nwindow.addEventListener('remove', function handler(event) {\n  stateManager.removeSiteFromWhitelist(event.detail.data, event.detail.type);\n  refreshDisplay();\n}, false);\n\n// options.js<options> ends here\n"
  },
  {
    "path": "src/app/test_widget/active_test.js",
    "content": "/*global components */\n\n/**\n * @fileOverview This file registers the `active-test` component. This file doesn’t depend on other components.\n * @name active_test.js<test_widget>\n * @author Etienne Prud’homme\n * @license MIT\n */\n\n/**\n * Registers the `active-test` component.\n */\n(function() {\n  'use strict';\n  var self = null;\n\n  var proto = {};\n\n  var template = '<div class=\"active-test\">' +\n        '  <div class=\"flex-container\">' +\n        '    <div class=\"mark incorrect\"><span class=\"test-desc\"></span></div>' +\n        '  </div>' +\n        '</div>' +\n        '<!-- active-test ends here -->';\n\n  /**\n   * Function to mark a test as `Passed`.\n   * @param {HTMLElement} markRightOrWrong - The element containing the mark.\n   * @private\n   */\n  function _testHasPassed(markRightOrWrong) {\n    markRightOrWrong.classList.remove('incorrect');\n    markRightOrWrong.classList.remove('error');\n    markRightOrWrong.classList.add('correct');\n  }\n\n  /**\n   * Function to mark a test as `Failed`.\n   * @param {HTMLElement} markRightOrWrong - The element containing the mark.\n   * @private\n   */\n  function _testHasFailed(markRightOrWrong) {\n    markRightOrWrong.classList.add('incorrect');\n    markRightOrWrong.classList.remove('correct');\n    markRightOrWrong.classList.remove('error');\n  }\n\n  /**\n   * Function to mark a test as `Erred` (is not valid).\n   * @param {HTMLElement} markRightOrWrong - The element containing the mark.\n   * @private\n   */\n  function _testHasErred(markRightOrWrong) {\n    markRightOrWrong.classList.remove('correct');\n    markRightOrWrong.classList.remove('incorrect');\n    markRightOrWrong.classList.add('error');\n  }\n\n  /**\n   * Main function for updating member elements.\n   */\n  function updateView() {\n    var testPassed, testDescription;\n    try {\n      testDescription = self.dataset.description;\n      testPassed = self.dataset.testPassed;\n    } catch (e) {\n      console.warn(e);\n    }\n\n    var markRightOrWrong = self.querySelector('.mark');\n    var descriptionDisplay = self.querySelector('.test-desc');\n\n    // Simple fix for backward compatibility\n    descriptionDisplay.textContent = testDescription.replace(/&lt;|&gt;/g, function(match) {\n      return {'&lt;': '<', '&gt;': '>'}[match];\n    });\n\n    if (testPassed === 'true') {\n      _testHasPassed(markRightOrWrong);\n    } else if (testPassed === 'false') {\n      _testHasFailed(markRightOrWrong);\n    } else if (testPassed === 'error') {\n      _testHasErred(markRightOrWrong);\n    }\n  }\n\n  /**\n   * Called when the element gets attached to the document\n   */\n  proto.attachedCallback = function() {\n    self = this;\n    self.dataset.testPassed = false;\n    updateView();\n  };\n\n  /**\n   * Called when any attribute on the element changes\n   */\n  proto.attributeChangedCallback = function () {\n    self = this;\n    updateView();\n  };\n\n  components.registerElement('active-test', template, proto);\n})();\n\n// active_test.js<test_widget> ends here\n"
  },
  {
    "path": "src/app/test_widget/font.js",
    "content": "/**\n * @fileOverview This file contains the \"Source Sans Pro\" font as base64. Because the `template.js` file is an injected script, it doesn’t have access to the extension path. Furthermore, sharing the path could be dangerous.\n * @name font.js<test_widget>\n * @author Copyright 2010, 2012, 2014 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries.\n\n This Font Software is licensed under the SIL Open Font License, Version 1.1.\n * @license GPLv3\n */\n\nvar sourceSansProFont = 'AAEAAAATAQAABAAwQkFTRYsZlLEAAilAAAAAOkRTSUexF+HqAAIpfAAAIFhHREVGWIRZ9wABwEAAAAEoR1BPUw6dvuMAAcFoAABMKkdTVUJ+lJvfAAINlAAAG6xPUy8yWrSUWwAAAbgAAABgY21hcG4XREUAABOEAAAKKGN2dCANmQD6AAAfbAAAAChmcGdtBlmcNwAAHawAAAFzZ2FzcP//AAMAAcA4AAAACGdseWbpcaFDAAAoTAABMtRoZWFk/hSz4gAAATwAAAA2aGhlYQejBwsAAAF0AAAAJGhtdHi/qKz/AAACGAAAEWxsb2NhuTYHZgAAH5QAAAi4bWF4cAZ1AkAAAAGYAAAAIG5hbWWdGO0SAAFbIAAAPLJwb3N03+u9sAABl9QAAChicHJlcJYE+usAAB8gAAAASwABAAAAAQzMpu0hD18PPPUACQPoAAAAAM2XgKUAAAAAzZfjFv9A/r0EiAO4AAAACQACAAAAAAAAAAEAAAPY/u8AAASq/0D/FgSIAAEAAAAAAAAAAAAAAAAAAARbAAEAAARbAFoABwBxAAUAAQAAAAAACgAAAgABcwADAAEAAwHHAZAABQAAAooCWAAAAEsCigJYAAABXgAyASAAAAILBQMDBAMCAgQgAAAHAAAAAQAAAAAAAAAAQURCRQBAAAD+/wLu/wYAAAPYAREgAAGTAAAAAAHgApQAAAAgAAMCjQBZAAAAAADKAAAAygAAAiAAAwJMAFoCOwA0AmcAWgIPAFoB7gBaAmkANAKMAFoBBwBaAeAAHwJDAFoB5gBaAtcAWgKHAFoCmAA0AkAAWgKYADQCRQBaAhYAKgIYABwChQBXAgMAAAMSABcCAQAPAdz//wIbAC0CAAA6AisAUgHIAC4CKwAvAfAALgEkAB4B+AAtAiAAUgD2AEMA9//YAe8AUgD/AFIDPQBSAiMAUgIeAC4CKwBSAiYALwFbAFIBowAcAVIAGAIgAEsB0wAMAs4AGAG+AA4B0wAMAakAHwIgAAMCIAADAiAAAwIgAAMCIAADAiAAAwIgAAMCIAADAiAAAwIgAAMCIAADAiAAAwIgAAMCIAADAiAAAwIgAAMCIAADAiAAAwIgAAMCIAADAiAAAwIgAAMDNgAIAjsANAI7ADQCOwA0AjsANAI7ADQCZwBaAmcAWgJnAFoCfgAhAg8AWgIPAFoCDwBaAg8AWgIPAFoCDwBaAg8AWgIPAFoCDwBaAg8AWgIPAFoCDwBaAg8AWgIPAFoCDwBaAg8AWgIPAFoCaQA0AmkANAJpADQCaQA0AmkANAJpADQCaQA0AowAWgKMAFoCjABaAq8AIAEHAAABBwBQAQf/+wEH//IBB//8AQcABwEHAEoBB//7AQcAQwEHAE4BBwArAeAAHwJDAFoB5gBTAeYAWgHmAFoB5gBaAeYAWgHmAAoB5gBaAekADQLXAFoChwBaAocAWgKHAFoChwBaAocAWgKHAFoChwBaApgANAKYADQCmAA0ApgANAKYADQCmAA0ApgANAKYADQCmAA0ApgANAKYADQCmAA0ApgANAKYADQCmAA0ApgAMgNPADQCmAA2ApgANgKYADYCmAA2ApgANgKYADYCmAA0AkUAWgJFAFoCRQBaAkUAWgJFAFoCRQBaAhYAKgIWACoCFgAqAhYAKgIWACoCFgAqAhYAKgKbAFsCGAAcAhgAHAIYABwCGAAcAhgAHAKFAFcChQBXAoUAVwKFAFcChQBXAoUAVwKFAFcChQBXAoUAVwKFAFcChQBXAoUAVwKFAFcChQBXAoUAVwKFAFcChQBXApMAVwKTAFcCkwBXApMAVwKTAFcCkwBXAxIAFwMSABcDEgAXAxIAFwHc//8B3P//Adz//wHc//8B3P//Adz//wHc//8B3P//AhsALQIbAC0CGwAtAhsALQJ+ACECRwBaApMAOgIAADoCAAA6AgAAOgIAADoCAAA6AgAAOgIAADoCAAA6AgAAOgIAADoCAAA6AgAAOgIAADoCAAA6AgAAOgIAADoCAAA6AgAAOgIAADoCAAA6AgAAOgIAADoDEQA6AcgALgHIAC4ByAAuAcgALgHIAC4CPQAvAisALwIrAC8CKwAvAfAALgHwAC4B8AAuAfAALgHwAC4B8AAuAfAALgHwAC4B8AAuAfAALgHwAC4B8AAuAfAALgHwAC4B8AAuAfAALgHwAC4B+AAtAfgALQH4AC0B+AAtAfgALQH4AC0B+AAtAiD/9AIgAFICIABSAiAACAD2AAwA9gA6APb/+gD2//AA9v/0APYAAAD2//oA9gA7APYAQwD2ACYA9gAmAPYAUgD3/9gB7wBSAe8AUgD/AEQBCABSAWoAUgD/AFIA/wBSAP///wD/AC4BBgAXAz0AUgIjAFICIwBSAiMAUgIjAFICIwBSAiMAUgIjAFIDBwA/Ah4ALgIeAC4CHgAuAh4ALgIeAC4CHgAuAh4ALgIeAC4CHgAuAh4ALgIeAC4CHgAuAh4ALgIeAC4CHgAuAh4ALgNHAC4CHgAuAh4ALgIeAC4CHgAuAh4ALgIeAC4CHgAuAVsAUgFbACQBWwBSAVsAQwFbAEMBW//9AaMAHAGjABwBowAcAaMAHAGjABwBowAcAaMAHAJAAFIBUgAYAVIAGAFSABgBUgAYAVIAGAFSAAkCIABLAiAASwIgAEsCIABLAiAASwIgAEsCIABLAiAASwIgAEsCIABLAiAASwIgAEsCIABLAiAASwIgAEsCIABLAiAASwIgAEsCIABLAiAASwIgAEsCIABLAiAASwLOABgCzgAYAs4AGALOABgB0wAMAdMADAHTAAwB0wAMAdMADAHTAAwB0wAMAdMADAGpAB8BqQAfAakAHwGpAB8CIQA1AisAUgD3/9gCKwAvAfAAJQIvADICPgAeAiwAHgIjAB4CUgAeAVgALgFYACkBWAAuAVgAJAFYABsBWAAlAVgALgFYAC4BWAAkAVgALgFYAC4BWAAuAisALwIrAC8CKwAvAisALwIrAC8CKwAvAisALwIrAC8CKwAvAisALwIrAC8CKwAvAisALwIrAC8CKwAvAisALwIrAC8CKwAvAisALwIrAC8CKwAvAisALwIrAC8CLwAyAi8AMgIvADICLwAyAi8AMgIvADICLwAyAi8AMgD2AFIA9gBFAQgAUgFqAFIA9gAmAPYARQD2AAAA9v//AQEAFwIsAB4CYQAgAfEALAHxAE8B8QAkAfEAGgHxABEB8QAZAfEAMAHxACwB8QApAfEAKAIaADcBcQAyAfUAJQHxABoCBwAiAfEAGQINAD0B6wAsAg0ANwINADQB8QAsAfEATwHxACQB8QAaAfEAEQHxABkB8QAxAfEALAHxACkB8QAeAgYANAFxADIB8QApAfEAGgIGABkB8QAZAgYAOQHpACwCBwAxAgYAJgD5AEEA+QAvAPkAQQD5AC8DtABeASEAVQEhAFUBqQAmAakAMAD5AFABqQBQAPkAOQD5AD8BqQA5AakAPwD5AD8BqQA/AQ8ALQEPADYBrQAtAa0ANgE3ACkBNwApAeAAKQMgACkB8QApAyAAKQD5AEEBMAAoAfQADAEvAFIBLwAmAS8AXgEvAB8BLwAiAS8AHwFeAAoA8QBcAV4ADgDxAFwBogA6AcYANgHGADYB8QAtAjAAKQLoADEC5wAxAacAFwJ9AAMCfQAbA08AMwMOADMB8QAjAW8AIwFvAFcBbwAoAW8AIwFvACoBbwAjAW8ALQFvADIBbwAtAW8AJwDtAEEA7QAnALEAKwCxACEBbwAjAW8AVwFvACgBbwAjAW8AKgFvACMBbwAtAW8AMgFvAC0BbwAnAO0AQQDtACcAsQArALEAIQFvACMBbwBXAW8AKAFvACMBbwAqAW8AIwFvAC0BbwAyAW8ALQFvACcA7QBBAO0AJwCxACsAsQAhAW8AIwFvAFcBbwAoAW8AIwFvACoBbwAjAW8ALQFvADIBbwAtAW8AJwDtAEEA7QAnALEAKwCxACEBWQAlAXYAIQFtAB4BWQAlAXYANAEyAB4BdgAhAVAAHADJABMBVwAeAW4ANACmACoAqf/mAVEANACuADQCLwA0AXEANAFtAB4BdgA0AXYAIQDwADQBGwATAOgAEAFyADIBQQAIAecAEAEzAAgBPwAIASIAFQFQABwBUAAcAVAAGQF2ACEBeQAiAKYANAFLACkB8QAaAfEANAHxADUB8QAXAfEAFwHxAD0B8QASAfEAPQHxADUB8QALAfEACgHxAEQB8QAKAfEALwHxAD0B8QBIAfEAFwBW/1kAVv9ZAFb/WQM4ACMEqgAjAw0AQAMoAEADHAAjAyQAQAM1ACkDJABAAzUAIwM1ACMDIQAfAfEAIgHxACIB8QAyAfEAIgH2ALwB8QAiAfEAIgHxACIB8QAiAfEAIgHxACIB8QA8AfEAIgHxACQB8QAkAfEAIgIxABgDDgAoAiYAUgIQACgBTAA0Ai0AKQJQAB4CrgArAfgAFgKhAFkBmQAVAyAALgJrABoCawAqAmsAJwJrACoBMgA2ATIADAG8ACkBeAA2AjsAFwI7ABcCOwA5AjsAOQI7ABcCOwAXAjsAEgI7ABIDHwBKAx8ASgJkAAAB9wAdAgUAOAD5AFEBqgBRAPkAOQD5AD8AlgAeAKIAFAIeAKACHgDOAh4AjgIeAI4AcgAWARUAEADhAC4A4QAAAHIAFgIeAIQCHgCIAh4AlAIeAJECHgCyAh4ArQIeANkCHgDAAh4AzQAA/5EAAP99AAD/vwAA/80AAP9/AAD/eAAA/3UAAP9vAAD/hQAA/4QAAP+CAAD/hQAA/8oAAP/HAAD/eQAA/3kAAP/AAAD/wAAA/6MAAP+jAAD/ngAA/5MAAP9/AAD/eAAA/0AAAP9AAAD/ywAA/9EAAP/3AAD/ygAA/3kAAP+rAAD/qwAA/6sAAP++AAD/vgAA/4IAAP+EAAD/fAAA/3wAAP98AAD/fAAA/3wAAP94AAD/fAAA/3wAAP+MAAD/gAAA/4wAAP+AAAD/jAAA/4AAAP99AAD/fAAA/4IAAP+GAAD/ggAA/4YAAP+CAAD/hgAA/30AAP98ABL/4wAA/7sAygAAAfEAAACHAAAAhwAAAlsAHgEHAAgCmAA0AiAACAD2//4CHgAuAAD/hAAA/4ACTABaAisAUgJDAFoB7wBSAg8AWgHwAC4CmAA0Ah4ALgGGAFwBsAAbAS8AXgEvAB8BLwBeAS8AHwF6AF4BegAfAS8AXgEvAB8BLwBeAS8AHwHxACwB8QAsAhoANwIaADcA9gBDAdYAAwIOAFoB9wA0AisAWgHbAFoBuwBaAiUANAJSAFoBBwBaAbYAHwICAFoBtQBaAocAWgJJAFoCTQA0AgYAWgJNADMCCwBaAdoAKgHTABwCRwBXAb8AAAKsABcBxQAPAZ///wHbAC0B1gADAdYAAwHWAAMB1gADAdYAAwHWAAMB1gADAdYAAwHWAAMB1gADAdYAAwHWAAMB1gADAdYAAwHWAAMB1gADAdYAAwHWAAMB1gADAdYAAwHWAAMB1gADAsgACAIhACECDgBaAfcANAH3ADQB9wA0AfcANAH3ADQCKgBaAioAWgIqAFoCPgAhAdsAWgHbAFoB2wBaAdsAWgHbAFoB2wBaAdsAWgHbAFoB2wBaAdsAWgHbAFoB2wBaAdsAWgHbAFoB2wBaAdsAWgHbAFoB2wBaAiUANAIlADQCJQA0AiUANAIlADQCJQA0AiUANAJSAFoCUgBaAlIAWgJ2ACABBwAAAQcAUAEH//sBB//yAQf//AEHAAcBBwBKAQf/+wEHAEMBBwBNAQcAKwEHAAgBtgAfAgIAWgICAFoBtQBWAbUAWgG1AFoBtQBaAbUAWgG1AA0BtQBaAbUADQKHAFoCSQBaAkkAWgJJAFoCSQBaAkkAWgJJAFoCSQBaAk0ANAJNADQCTQA0Ak0ANAJNADQCTQA0Ak0ANAJNADQCTQA0Ak0ANAJNADQCTQA0Ak0ANAJNADQCTQA0Ak0ALwLfADQCTQA0Ak0ANAJNADQCTQA0Ak0ANAJNADQCTQA0Ak0ANAJNADQCCwBaAgsAWgILAFoCCwBaAgsAWgILAFoB2gAqAdoAKgHaACoB2gAqAdoAKgHaACoB2gAqA7QAKgJSAFsB0wAcAdMAHAHTABwB0wAcAdMAHAJHAFcCRwBXAkcAVwJHAFcCRwBXAkcAVwJHAFcCRwBXAkcAVwJHAFcCRwBXAkcAVwJHAFcCRwBXAkcAVwJHAFcCRwBXAlUAVwJVAFcCVQBXAlUAVwJVAFcCVQBXAqwAFwKsABcCrAAXAqwAFwGf//8Bn///AZ///wGf//8Bn///AZ///wGf//8Bn///AdsALQHbAC0B2wAtAdsALQI+ACECDQBaAkYAOgIWACAB+QA3AWYAMgHFACIBywAXAeEAJAHRAB8B6AA+Aa8AIQHpADYB4wAxARYAKQGeACkCrwApAPkAUQFr//8BiAA5AXsAIAGbADkBXwA5AUoAOQGbACABsgA5ALAAOQFBABIBgwA5AUUAOQHmADkBrwA5AbsAIAGBADkBuwAfAYUAOQFkABoBZAARAa8AOAFa//4CDgANAVoACAFA//0BZgAbALEAKwDsACkBXAApAjIAKQAA/4UAAP+EAAAAAAAAAAMAAAADAAACFAABAAAAAAAcAAMAAQAAAhQABgH4AAAACQD3AAMAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAgICBwIxAo8CogHUAgYCGwIcAiUCrQH+AhIB/QIhAdUB1gHXAdgB2QHaAdsB3AHdAd4B/wIAArMCsgK0AgQCLwAEAAUABgAHAAgACQAKAAsADAANAA4ADwAQABEAEgATABQAFQAWABcAGAAZABoAGwAcAB0CHQIjAh4CuAIaAuQAHgAfACAAIQAiACMAJAAlACYAJwAoACkAKgArACwALQAuAC8AMAAxADIAMwA0ADUANgA3Ah8CIgIgAroAAAA8AD8ATwBZAIwAlQDAAOcA5gDoAOoA6QDtAP0BBwEGAQgBCgEjASIBJAEmATwBQwFCAUQBRgFFAW8BbgFwAXICJgKNApMCkAIoAhkCKQFnAiwCKgItAuUC7gK5AE4AoAK+ArcCtQK2ApECvwLAAsUCxgK9AsECagJsAAAA/AFRAgUCAwK8AsIClAK7AsMCEAIRAgEDNgA4ADsAlAChAVICFAIVAgoCCwIIAgkCsALdAYwA2gKfApICDgIPAZwBnQInAhgCDAINAqMAOgBaADkAXABYAHUAdgB4AHQAkgCTAAAAkQC9AL4AvAEtAuYC7QLvAvAC8wLxAvQC8gL1AucABAgUAAABGgEAAAcAGgAAAA0ALwA5AEAAWgBgAHoAfgC/AMQA0QDWAN8A5ADxAPYBMQFJAWUBfgGAAY8BkgGhAbAB3AHnAesCGwI3AkMCUQJZAmECsAKzArkCvAK/AswC3QLjAwQDDAMPAxMDGwMkAygDLgMxA8AdQx1JHU0dUB1SHVgdWx2cHaAdux4HHg8eFx4hHiUeKx47HkkeUx5jHm8ehR6PHpMelx6eHvkgByAWIBogHiAiICYgMCAzIDogPSBEIHEgeSB/IIkgjiCUIKEgpCCnIKwgsiC1ILohEyEXISAhIiEmIS4hVCFeIZMiAiIGIg8iEiIVIhoiHiIrIkgiYCJlIx8loCWzJbclvSXBJcYlyiYRJmonEydSJ+cuJfsC/v///wAAAAAADQAgADAAOgBBAFsAYQB7AKAAwADFANIA1wDgAOUA8gD3ATQBTAFoAYABjwGSAaABrwHNAeYB6gIYAjcCQwJRAlkCYQKwArICtwK7Ar4CxgLYAuEDAAMGAw8DEgMbAyMDJgMuAzEDwB1DHUcdTR1PHVIdVh1bHZwdoB27HgYeDB4WHiAeJB4qHjQeQh5SHloebB6AHo4ekh6XHp4eoCAHIBIgGCAcICAgJiAwIDIgOSA9IEQgcCB0IH0ggCCNIJQgoSCkIKYgqyCxILUguSETIRchICEiISYhLiFTIVshkCICIgYiDyIRIhUiGSIeIisiSCJgImQjHCWgJbIltiW8JcAlxiXJJhAmaicTJ1In5i4i+wD+////AAH/9QAAAaUAAP/DAAD/vQAAAAD/eAAA/78AAAAGAAAAUAAAAAAAAAAAAb3/VgECAAAAAAAAAAAAAAAA/2AA9/9H/0D/Of/EAAAAAAAlACQAIAAAAAAAAAAA/////v/3//AAAP/s/+r+/eUqAADlJgAA5SkAAOUn5NPk0uTL5TwAAOUwAAAAAAAAAAAAAOT2AAAAAAAAAAAAAOLW4hgAAOMwAAAAAAAAAADh2+Jz4qzh1eMO4lsAAOHCAADhwOG94fXh9OHy4fEAAOHp4efh5OG04RThDuEL4Z7hmuFU4U7hOeC+4L3gtwAA4IsAAOCg4Jbgc+BZ4FHgMN0t3R/dHd0Z3RfdCAAA3MncctvI237batUwBpsFWwABAAAAAAEWAAABMgAAATwAAAFEAUoAAAGGAAABnAAAAaoAAAHAAjQCXgKQAAAAAAAAArYCuAK6AtgC2gLcAAAAAAAAAAAAAAAAAtYC2AAAAAAAAALWAuAC5ALsAAAAAAAAAAAC8AAAAAAAAAAAAuwAAALuAAAC7gAAAAAAAAAAAAAC6AAAAuwC7gLwAvIDAAAAAwwDHgMkAy4DMAAAAAADLgAAA94D5gPqA+4AAAAAAAAAAAAAAAAD5gAAA+YAAAAAAAAAAAAAAAAD3gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPCAAADwgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOsAAAAAAAAAAAAAAAAAAAAAAAAAAMCAgIHAjECjwKiAdQCBgIbAhwCJQKtAf4CEgH9AiEB/wIAArMCsgK0AgQCLwIdAiMCHgK4AhoC5AIfAiICIAK6AzYCAwKTApACjgKRAiQCKALuAioCagIQArwCEwIsAu8CjQK3AjQCNQLlAr8CKQIYAvQCMwJsAhECpAKlAqYCBQA/AE4ATwBYAFkAWgBcAHQAdQB2AHgA4wCMAq8AoAC8AL0AvgDAANgA5AFnAO0A/AD9AQYBBwEIAQoBIgEjASQBJgGVATwCsAFRAW4BbwFwAXIBigGWAYwAPQDrAD4A7ABNAPsAUAD+AFEA/wBTAQEAUgEAAFQBAgBXAQUAXQELAF4BDABfAQ0AaAEWAFsBCQBpARcAagEYAGsBGQBsARoAcAEeAHMBIQB3ASUAeQEnAzsDPgB+ASsAegEtAH8BLgCAAS8BMACBATEAgwE0AIIBMgCEATMAiAE4AIoBOgCNAT0AiwE7AUEAlgFHAzwDPwCXAUgAoQFSAKkBWgCrAVsAqgFcAK8BYACwAWEAsgFjALEBYgC4AWkAtwFoAL8BcQDBAXMAwgF0AMMBdQDEAXYAzAF+ANUBhwDZAYsA2gDfAZEA4QGTAOABkgCiAVMAzQF/AEAA7gB7ASgAmAFJAMUBdwDGAXgAxwF5AMgBegDJAXsAbQEbAKgBWQCzAWQAuQFqAnYCfgKDAoUEOQLwAvMC8QL1Au0C8gJ4An8ChAL2AvgC+gL8Av4DAAMCAwQDBgMIAwoDDAMVAxYDGAJuAnACcQJ3AnkCfAKAAoEAVQEDAFYBBABuARwAcQEfAHIBIANEA0UAhQE1AIYBNgCHATcAiQE5AI4BPgCPAT8AkAFAAKwBXQCtAV4ArgFfALQBZQC1AWYAugFrALsBbADTAYUA1AGGANYBiADbAY0A4gGUAEEA7wBCAPAAQwDxAEQA8gBFAPMARgD0AEcA9QBIAPYASQD3AEoA+ABLAPkATAD6AGABDgBhAQ8AYgEQAGMBEQBkARIAZQETAGYBFABnARUAfAEpAH0BKgCZAUoAmgFLAJsBTACcAU0AnQFOAJ4BTwCfAVAAowFUAKQBVQClAVYApgFXAKcBWADKAXwAywF9AM4BgADPAYEA0AGCANEBgwDSAYQA1wGJANwBjgDdAY8A3gGQAhYCFAIVAhcDSgIIAgkCDAIKAgsCDQImAicCGQIyAnUCPAI9AnoCmQKSAsUCrgKxAsICzwLduAAALEu4AAlQWLEBAY5ZuAH/hbgARB25AAkAA19eLbgAASwgIEVpRLABYC24AAIsuAABKiEtuAADLCBGsAMlRlJYI1kgiiCKSWSKIEYgaGFksAQlRiBoYWRSWCNlilkvILAAU1hpILAAVFghsEBZG2kgsABUWCGwQGVZWTotuAAELCBGsAQlRlJYI4pZIEYgamFksAQlRiBqYWRSWCOKWS/9LbgABSxLILADJlBYUViwgEQbsEBEWRshISBFsMBQWLDARBshWVktuAAGLCAgRWlEsAFgICBFfWkYRLABYC24AAcsuAAGKi24AAgsSyCwAyZTWLBAG7AAWYqKILADJlNYIyGwgIqKG4ojWSCwAyZTWCMhuADAioobiiNZILADJlNYIyG4AQCKihuKI1kgsAMmU1gjIbgBQIqKG4ojWSC4AAMmU1iwAyVFuAGAUFgjIbgBgCMhG7ADJUUjISMhWRshWUQtuAAJLEtTWEVEGyEhWS0AsAArALIBAQIrAbICAgIrAbcCRDYqIRQACCu3A0A2KiEUAAgrALcBUUM0JBcACCsAsgQIByuwACBFfWkYREuwYFJYsAEbsABZsAGOAAAUAEQAUgBWAAAADP8zAAwB5gAMAgYADAI+AAwCfgAMApAADALIAAwAAABiAGIAYgBiALABFgFmAaIB4AIWAnQCsALQAwIDSgNwA9QEJAR4BMAFMgWGBfQGIAZmBqIHGAd0B7IH6AheCNoJKgmiCgQKUgsCC1ALhAvMDBQMRgzGDRwNcA3sDmIOqg8WD2APtg/yEGgQwhEYEU4RWhFmEXIRfhGKEZYRohGuEboRxhHSEd4R6hH2EgISEhIeEioSNhJCElISxhMqEzYTQhNOE1oTZhNyE34TihOSE54TqhO2E8ITzhPaE+YT8hP+FAoUFhQiFC4UOhRGFFYUuhTGFNIU3hTqFPYVAhUOFRoVJhUyFZoVphWyFb4VyhXWFeIV7hX6FgYWEhZcFmgWdBaAFowWmBakFrAWwBbMFwwXGBckFzAXPBdIF1QXYBdsF3gXhBeQF5wXqBe0F8AXzBfYF+QX8Bf8GAgYFBgkGLAZBhl2GYIZjhmaGaYZshoyGj4aShpWGmIachp+GooalhqiGq4auhrGGtIbPBtIG1QbYBtsG3gbhBuQG5wbqBu0G8AbzBvYG+Qb8Bv8HAgcFBwgHCwcOByqHQodFh0iHS4dOh1GHVIdXh1qHXYdgh2OHZodph2yHb4dyh3WHeId7h36HgYeXh6iHwIfDh8aHyYfMh8+H0ofVh9iH24feh+GH5Ifnh+qH7Yfxh/SH94f6h/2IAYgkiFIIVQhYCFsIXghhCGQIZwhqCIgIiwiOCJEIlAiXCJoInQigCKMIpgipCKwIrwiyCLUIuQjZiNyI34jiiOWI6IjriO6I8Yj0iPeJDYkQiROJFokZiRyJH4kiiSWJKIk9iU2JVYlYiVuJbIlviXKJdYl4iXuJf4mCiZYJmQmcCZ8JogmlCagJqwmuCbEJtAm3CboJvQnACcMJxgnJCcwJzwnSCdUJ2AnbCd8J+gogCjwKPwpCCkUKSApLCmmKbIpvinKKdYp5inyKf4qCioWKiIqLio6KkYqxCrQKtwq6Cr0KwArDCsYKyQrMCs8K0grVCtgK2wreCuEK5ArnCuoK7QrwCvMLDIsliyiLK4suizGLNIs3izqLPYtAi0OLRotJi0yLT4tSi1WLWItbi16LYYtki4ULnourC8IL2gv2jBSMF4wajDsMSIxLjE6MUYxUjFeMWoxdjGCMY4xmjH4MgAyDDIYMiQyMDI8MkgyVDJgMmwyeDKEMpAynDKoMrQyxDLQMtwy6DL0MwQzfjOGM5IznjOqM7YzwjPO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AAEECQABAB4UMgADAAEECQACAA4UUAADAAEECQADAEwUXgADAAEECQAEAB4UMgADAAEECQAFAIIUqgADAAEECQAGACoVLAADAAEECQAHAMAVVgADAAEECQAIADQWFgADAAEECQAJABgWSgADAAEECQALADIWYgADAAEECQANI7YWlAADAAEECQAOAEg6SgADAAEECQEAABg6kgADAAEECQEBABQ6qgADAAEECQECABY6vgADAAEECQEDABY61AADAAEECQEEABI66kNvcHlyaWdodCAyMDEwLCAyMDEyIEFkb2JlIFN5c3RlbXMgSW5jb3Jwb3JhdGVkLiBBbGwgUmlnaHRzIFJlc2VydmVkLlNvdXJjZSBTYW5zIFByb1JlZ3VsYXIxLjA1MDtBREJFO1NvdXJjZVNhbnNQcm8tUmVndWxhcjtBRE9CRVZlcnNpb24gMS4wNTA7UFMgVmVyc2lvbiAxLjAwMDtob3Rjb252IDEuMC43MDttYWtlb3RmLmxpYjIuNS41OTAwU291cmNlU2Fuc1Byby1SZWd1bGFyU291cmNlIGlzIGEgdHJhZGVtYXJrIG9mIEFkb2JlIFN5c3RlbXMgSW5jb3Jwb3JhdGVkIGluIHRoZSBVbml0ZWQgU3RhdGVzIGFuZC9vciBvdGhlciBjb3VudHJpZXMuQWRvYmUgU3lzdGVtcyBJbmNvcnBvcmF0ZWRQYXVsIEQuIEh1bnRodHRwOi8vd3d3LmFkb2JlLmNvbS90eXBlQ29weXJpZ2h0IDIwMTAsIDIwMTIgQWRvYmUgU3lzdGVtcyBJbmNvcnBvcmF0ZWQgKGh0dHA6Ly93d3cuYWRvYmUuY29tLyksIHdpdGggUmVzZXJ2ZWQgRm9udCBOYW1lICdTb3VyY2UnLiBBbGwgUmlnaHRzIFJlc2VydmVkLiBTb3VyY2UgaXMgYSB0cmFkZW1hcmsgb2YgQWRvYmUgU3lzdGVtcyBJbmNvcnBvcmF0ZWQgaW4gdGhlIFVuaXRlZCBTdGF0ZXMgYW5kL29yIG90aGVyIGNvdW50cmllcy4NCg0KVGhpcyBGb250IFNvZnR3YXJlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBTSUwgT3BlbiBGb250IExpY2Vuc2UsIFZlcnNpb24gMS4xLg0KDQpUaGlzIGxpY2Vuc2UgaXMgY29waWVkIGJlbG93LCBhbmQgaXMgYWxzbyBhdmFpbGFibGUgd2l0aCBhIEZBUSBhdDogaHR0cDovL3NjcmlwdHMuc2lsLm9yZy9PRkwNCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NClNJTCBPUEVOIEZPTlQgTElDRU5TRSBWZXJzaW9uIDEuMSAtIDI2IEZlYnJ1YXJ5IDIwMDcNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNClBSRUFNQkxFDQpUaGUgZ29hbHMgb2YgdGhlIE9wZW4gRm9udCBMaWNlbnNlIChPRkwpIGFyZSB0byBzdGltdWxhdGUgd29ybGR3aWRlIGRldmVsb3BtZW50IG9mIGNvbGxhYm9yYXRpdmUgZm9udCBwcm9qZWN0cywgdG8gc3VwcG9ydCB0aGUgZm9udCBjcmVhdGlvbiBlZmZvcnRzIG9mIGFjYWRlbWljIGFuZCBsaW5ndWlzdGljIGNvbW11bml0aWVzLCBhbmQgdG8gcHJvdmlkZSBhIGZyZWUgYW5kIG9wZW4gZnJhbWV3b3JrIGluIHdoaWNoIGZvbnRzIG1heSBiZSBzaGFyZWQgYW5kIGltcHJvdmVkIGluIHBhcnRuZXJzaGlwIHdpdGggb3RoZXJzLg0KDQpUaGUgT0ZMIGFsbG93cyB0aGUgbGljZW5zZWQgZm9udHMgdG8gYmUgdXNlZCwgc3R1ZGllZCwgbW9kaWZpZWQgYW5kIHJlZGlzdHJpYnV0ZWQgZnJlZWx5IGFzIGxvbmcgYXMgdGhleSBhcmUgbm90IHNvbGQgYnkgdGhlbXNlbHZlcy4gVGhlIGZvbnRzLCBpbmNsdWRpbmcgYW55IGRlcml2YXRpdmUgd29ya3MsIGNhbiBiZSBidW5kbGVkLCBlbWJlZGRlZCwgcmVkaXN0cmlidXRlZCBhbmQvb3Igc29sZCB3aXRoIGFueSBzb2Z0d2FyZSBwcm92aWRlZCB0aGF0IGFueSByZXNlcnZlZCBuYW1lcyBhcmUgbm90IHVzZWQgYnkgZGVyaXZhdGl2ZSB3b3Jrcy4gVGhlIGZvbnRzIGFuZCBkZXJpdmF0aXZlcywgaG93ZXZlciwgY2Fubm90IGJlIHJlbGVhc2VkIHVuZGVyIGFueSBvdGhlciB0eXBlIG9mIGxpY2Vuc2UuIFRoZSByZXF1aXJlbWVudCBmb3IgZm9udHMgdG8gcmVtYWluIHVuZGVyIHRoaXMgbGljZW5zZSBkb2VzIG5vdCBhcHBseSB0byBhbnkgZG9jdW1lbnQgY3JlYXRlZCB1c2luZyB0aGUgZm9udHMgb3IgdGhlaXIgZGVyaXZhdGl2ZXMuDQoNCkRFRklOSVRJT05TDQoiRm9udCBTb2Z0d2FyZSIgcmVmZXJzIHRvIHRoZSBzZXQgb2YgZmlsZXMgcmVsZWFzZWQgYnkgdGhlIENvcHlyaWdodCBIb2xkZXIocykgdW5kZXIgdGhpcyBsaWNlbnNlIGFuZCBjbGVhcmx5IG1hcmtlZCBhcyBzdWNoLiBUaGlzIG1heSBpbmNsdWRlIHNvdXJjZSBmaWxlcywgYnVpbGQgc2NyaXB0cyBhbmQgZG9jdW1lbnRhdGlvbi4NCg0KIlJlc2VydmVkIEZvbnQgTmFtZSIgcmVmZXJzIHRvIGFueSBuYW1lcyBzcGVjaWZpZWQgYXMgc3VjaCBhZnRlciB0aGUgY29weXJpZ2h0IHN0YXRlbWVudChzKS4NCg0KIk9yaWdpbmFsIFZlcnNpb24iIHJlZmVycyB0byB0aGUgY29sbGVjdGlvbiBvZiBGb250IFNvZnR3YXJlIGNvbXBvbmVudHMgYXMgZGlzdHJpYnV0ZWQgYnkgdGhlIENvcHlyaWdodCBIb2xkZXIocykuDQoNCiJNb2RpZmllZCBWZXJzaW9uIiByZWZlcnMgdG8gYW55IGRlcml2YXRpdmUgbWFkZSBieSBhZGRpbmcgdG8sIGRlbGV0aW5nLCBvciBzdWJzdGl0dXRpbmcgLS0gaW4gcGFydCBvciBpbiB3aG9sZSAtLSBhbnkgb2YgdGhlIGNvbXBvbmVudHMgb2YgdGhlIE9yaWdpbmFsIFZlcnNpb24sIGJ5IGNoYW5naW5nIGZvcm1hdHMgb3IgYnkgcG9ydGluZyB0aGUgRm9udCBTb2Z0d2FyZSB0byBhIG5ldyBlbnZpcm9ubWVudC4NCg0KIkF1dGhvciIgcmVmZXJzIHRvIGFueSBkZXNpZ25lciwgZW5naW5lZXIsIHByb2dyYW1tZXIsIHRlY2huaWNhbCB3cml0ZXIgb3Igb3RoZXIgcGVyc29uIHdobyBjb250cmlidXRlZCB0byB0aGUgRm9udCBTb2Z0d2FyZS4NCg0KUEVSTUlTU0lPTiAmIENPTkRJVElPTlMNClBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHkgb2YgdGhlIEZvbnQgU29mdHdhcmUsIHRvIHVzZSwgc3R1ZHksIGNvcHksIG1lcmdlLCBlbWJlZCwgbW9kaWZ5LCByZWRpc3RyaWJ1dGUsIGFuZCBzZWxsIG1vZGlmaWVkIGFuZCB1bm1vZGlmaWVkIGNvcGllcyBvZiB0aGUgRm9udCBTb2Z0d2FyZSwgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6DQoNCjEpIE5laXRoZXIgdGhlIEZvbnQgU29mdHdhcmUgbm9yIGFueSBvZiBpdHMgaW5kaXZpZHVhbCBjb21wb25lbnRzLCBpbiBPcmlnaW5hbCBvciBNb2RpZmllZCBWZXJzaW9ucywgbWF5IGJlIHNvbGQgYnkgaXRzZWxmLg0KDQoyKSBPcmlnaW5hbCBvciBNb2RpZmllZCBWZXJzaW9ucyBvZiB0aGUgRm9udCBTb2Z0d2FyZSBtYXkgYmUgYnVuZGxlZCwgcmVkaXN0cmlidXRlZCBhbmQvb3Igc29sZCB3aXRoIGFueSBzb2Z0d2FyZSwgcHJvdmlkZWQgdGhhdCBlYWNoIGNvcHkgY29udGFpbnMgdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgbGljZW5zZS4gVGhlc2UgY2FuIGJlIGluY2x1ZGVkIGVpdGhlciBhcyBzdGFuZC1hbG9uZSB0ZXh0IGZpbGVzLCBodW1hbi1yZWFkYWJsZSBoZWFkZXJzIG9yIGluIHRoZSBhcHByb3ByaWF0ZSBtYWNoaW5lLXJlYWRhYmxlIG1ldGFkYXRhIGZpZWxkcyB3aXRoaW4gdGV4dCBvciBiaW5hcnkgZmlsZXMgYXMgbG9uZyBhcyB0aG9zZSBmaWVsZHMgY2FuIGJlIGVhc2lseSB2aWV3ZWQgYnkgdGhlIHVzZXIuDQoNCjMpIE5vIE1vZGlmaWVkIFZlcnNpb24gb2YgdGhlIEZvbnQgU29mdHdhcmUgbWF5IHVzZSB0aGUgUmVzZXJ2ZWQgRm9udCBOYW1lKHMpIHVubGVzcyBleHBsaWNpdCB3cml0dGVuIHBlcm1pc3Npb24gaXMgZ3JhbnRlZCBieSB0aGUgY29ycmVzcG9uZGluZyBDb3B5cmlnaHQgSG9sZGVyLiBUaGlzIHJlc3RyaWN0aW9uIG9ubHkgYXBwbGllcyB0byB0aGUgcHJpbWFyeSBmb250IG5hbWUgYXMgcHJlc2VudGVkIHRvIHRoZSB1c2Vycy4NCg0KNCkgVGhlIG5hbWUocykgb2YgdGhlIENvcHlyaWdodCBIb2xkZXIocykgb3IgdGhlIEF1dGhvcihzKSBvZiB0aGUgRm9udCBTb2Z0d2FyZSBzaGFsbCBub3QgYmUgdXNlZCB0byBwcm9tb3RlLCBlbmRvcnNlIG9yIGFkdmVydGlzZSBhbnkgTW9kaWZpZWQgVmVyc2lvbiwgZXhjZXB0IHRvIGFja25vd2xlZGdlIHRoZSBjb250cmlidXRpb24ocykgb2YgdGhlIENvcHlyaWdodCBIb2xkZXIocykgYW5kIHRoZSBBdXRob3Iocykgb3Igd2l0aCB0aGVpciBleHBsaWNpdCB3cml0dGVuIHBlcm1pc3Npb24uDQoNCjUpIFRoZSBGb250IFNvZnR3YXJlLCBtb2RpZmllZCBvciB1bm1vZGlmaWVkLCBpbiBwYXJ0IG9yIGluIHdob2xlLCBtdXN0IGJlIGRpc3RyaWJ1dGVkIGVudGlyZWx5IHVuZGVyIHRoaXMgbGljZW5zZSwgYW5kIG11c3Qgbm90IGJlIGRpc3RyaWJ1dGVkIHVuZGVyIGFueSBvdGhlciBsaWNlbnNlLiBUaGUgcmVxdWlyZW1lbnQgZm9yIGZvbnRzIHRvIHJlbWFpbiB1bmRlciB0aGlzIGxpY2Vuc2UgZG9lcyBub3QgYXBwbHkgdG8gYW55IGRvY3VtZW50IGNyZWF0ZWQgdXNpbmcgdGhlIEZvbnQgU29mdHdhcmUuDQoNClRFUk1JTkFUSU9ODQpUaGlzIGxpY2Vuc2UgYmVjb21lcyBudWxsIGFuZCB2b2lkIGlmIGFueSBvZiB0aGUgYWJvdmUgY29uZGl0aW9ucyBhcmUgbm90IG1ldC4NCg0KRElTQ0xBSU1FUg0KVEhFIEZPTlQgU09GVFdBUkUgSVMgUFJPVklERUQgIkFTIElTIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIEFOWSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVCBPRiBDT1BZUklHSFQsIFBBVEVOVCwgVFJBREVNQVJLLCBPUiBPVEhFUiBSSUdIVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIENPUFlSSUdIVCBIT0xERVIgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBJTkNMVURJTkcgQU5ZIEdFTkVSQUwsIFNQRUNJQUwsIElORElSRUNULCBJTkNJREVOVEFMLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVMsIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLCBPVVQgT0YgVEhFIFVTRSBPUiBJTkFCSUxJVFkgVE8gVVNFIFRIRSBGT05UIFNPRlRXQVJFIE9SIEZST00gT1RIRVIgREVBTElOR1MgSU4gVEhFIEZPTlQgU09GVFdBUkUuaHR0cDovL3d3dy5hZG9iZS5jb20vdHlwZS9sZWdhbC5odG1sU2xhc2hlZCB6ZXJvU3RyYWlnaHQgbEFsdGVybmF0ZSBhQWx0ZXJuYXRlIGdTZXJpZmVkIEkAQwBvAHAAeQByAGkAZwBoAHQAIAAyADAAMQAwACwAIAAyADAAMQAyACAAQQBkAG8AYgBlACAAUwB5AHMAdABlAG0AcwAgAEkAbgBjAG8AcgBwAG8AcgBhAHQAZQBkAC4AIABBAGwAbAAgAFIAaQBnAGgAdABzACAAUgBlAHMAZQByAHYAZQBkAC4AUwBvAHUAcgBjAGUAIABTAGEAbgBzACAAUAByAG8AUgBlAGcAdQBsAGEAcgAxAC4AMAA1ADAAOwBBAEQAQgBFADsAUwBvAHUAcgBjAGUAUwBhAG4AcwBQAHIAbwAtAFIAZQBnAHUAbABhAHIAOwBBAEQATwBCAEUAVgBlAHIAcwBpAG8AbgAgADEALgAwADUAMAA7AFAAUwAgAFYAZQByAHMAaQBvAG4AIAAxAC4AMAAwADAAOwBoAG8AdABjAG8AbgB2ACAAMQAuADAALgA3ADAAOwBtAGEAawBlAG8AdABmAC4AbABpAGIAMgAuADUALgA1ADkAMAAwAFMAbwB1AHIAYwBlAFMAYQBuAHMAUAByAG8ALQBSAGUAZwB1AGwAYQByAFMAbwB1AHIAYwBlACAAaQBzACAAYQAgAHQAcgBhAGQAZQBtAGEAcgBrACAAbwBmACAAQQBkAG8AYgBlACAAUwB5AHMAdABlAG0AcwAgAEkAbgBjAG8AcgBwAG8AcgBhAHQAZQBkACAAaQBuACAAdABoAGUAIABVAG4AaQB0AGUAZAAgAFMAdABhAHQAZQBzACAAYQBuAGQALwBvAHIAIABvAHQAaABlAHIAIABjAG8AdQBuAHQAcgBpAGUAcwAuAEEAZABvAGIAZQAgAFMAeQBzAHQAZQBtAHMAIABJAG4AYwBvAHIAcABvAHIAYQB0AGUAZABQAGEAdQBsACAARAAuACAASAB1AG4AdABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBkAG8AYgBlAC4AYwBvAG0ALwB0AHkAcABlAEMAbwBwAHkAcgBpAGcAaAB0ACAAMgAwADEAMAAsACAAMgAwADEAMgAgAEEAZABvAGIAZQAgAFMAeQBzAHQAZQBtAHMAIABJAG4AYwBvAHIAcABvAHIAYQB0AGUAZAAgACgAaAB0AHQAcAA6AC8ALwB3AHcAdwAuAGEAZABvAGIAZQAuAGMAbwBtAC8AKQAsACAAdwBpAHQAaAAgAFIAZQBzAGUAcgB2AGUAZAAgAEYAbwBuAHQAIABOAGEAbQBlACAAJwBTAG8AdQByAGMAZQAnAC4AIABBAGwAbAAgAFIAaQBnAGgAdABzACAAUgBlAHMAZQByAHYAZQBkAC4AIABTAG8AdQByAGMAZQAgAGkAcwAgAGEAIAB0AHIAYQBkAGUAbQBhAHIAawAgAG8AZgAgAEEAZABvAGIAZQAgAFMAeQBzAHQAZQBtAHMAIABJAG4AYwBvAHIAcABvAHIAYQB0AGUAZAAgAGkAbgAgAHQAaABlACAAVQBuAGkAdABlAGQAIABTAHQAYQB0AGUAcwAgAGEAbgBkAC8AbwByACAAbwB0AGgAZQByACAAYwBvAHUAbgB0AHIAaQBlAHMALgANAAoADQAKAFQAaABpAHMAIABGAG8AbgB0ACAAUwBvAGYAdAB3AGEAcgBlACAAaQBzACAAbABpAGMAZQBuAHMAZQBkACAAdQBuAGQAZQByACAAdABoAGUAIABTAEkATAAgAE8AcABlAG4AIABGAG8AbgB0ACAATABpAGMAZQBuAHMAZQAsACAAVgBlAHIAcwBpAG8AbgAgADEALgAxAC4ADQAKAA0ACgBUAGgAaQBzACAAbABpAGMAZQBuAHMAZQAgAGkAcwAgAGMAbwBwAGkAZQBkACAAYgBlAGwAbwB3ACwAIABhAG4AZAAgAGkAcwAgAGEAbABzAG8AIABhAHYAYQBpAGwAYQBiAGwAZQAgAHcAaQB0AGgAIABhACAARgBBAFEAIABhAHQAOgAgAGgAdAB0AHAAOgAvAC8AcwBjAHIAaQBwAHQAcwAuAHMAaQBsAC4AbwByAGcALwBPAEYATAANAAoADQAKAC0ALQAtAC0ALQAtAC0ALQAtAC0ALQAtAC0ALQAtAC0ALQAtAC0ALQAtAC0ALQAtAC0ALQAtAC0ALQAtAC0ALQAtAC0ALQAtAC0ALQAtAC0ALQAtAC0ALQAtAC0ALQAtAC0ALQAtAC0ALQAtAC0ALQAtAC0ALQANAAoAUwBJAEwAIABPAFAARQBOACAARgBPAE4AVAAgAEwASQBDAEUATgBTAEUAIABWAGUAcgBzAGkAbwBuACAAMQAuADEAIAAtACAAMgA2ACAARgBlAGIAcgB1AGEAcgB5ACAAMgAwADAANwANAAoALQAtAC0ALQAtAC0ALQAtAC0ALQAtAC0ALQAtAC0ALQAtAC0ALQAtAC0ALQAtAC0ALQAtAC0ALQAtAC0ALQAtAC0ALQAtAC0ALQAtAC0ALQAtAC0ALQAtAC0ALQAtAC0ALQAtAC0ALQAtAC0ALQAtAC0ALQAtAA0ACgANAAoAUABSAEUAQQBNAEIATABFAA0ACgBUAGgAZQAgAGcAbwBhAGwAcwAgAG8AZgAgAHQAaABlACAATwBwAGUAbgAgAEYAbwBuAHQAIABMAGkAYwBlAG4AcwBlACAAKABPAEYATAApACAAYQByAGUAIAB0AG8AIABzAHQAaQBtAHUAbABhAHQAZQAgAHcAbwByAGwAZAB3AGkAZABlACAAZABlAHYAZQBsAG8AcABtAGUAbgB0ACAAbwBmACAAYwBvAGwAbABhAGIAbwByAGEAdABpAHYAZQAgAGYAbwBuAHQAIABwAHIAbwBqAGUAYwB0AHMALAAgAHQAbwAgAHMAdQBwAHAAbwByAHQAIAB0AGgAZQAgAGYAbwBuAHQAIABjAHIAZQBhAHQAaQBvAG4AIABlAGYAZgBvAHIAdABzACAAbwBmACAAYQBjAGEAZABlAG0AaQBjACAAYQBuAGQAIABsAGkAbgBnAHUAaQBzAHQAaQBjACAAYwBvAG0AbQB1AG4AaQB0AGkAZQBzACwAIABhAG4AZAAgAHQAbwAgAHAAcgBvAHYAaQBkAGUAIABhACAAZgByAGUAZQAgAGEAbgBkACAAbwBwAGUAbgAgAGYAcgBhAG0AZQB3AG8AcgBrACAAaQBuACAAdwBoAGkAYwBoACAAZgBvAG4AdABzACAAbQBhAHkAIABiAGUAIABzAGgAYQByAGUAZAAgAGEAbgBkACAAaQBtAHAAcgBvAHYAZQBkACAAaQBuACAAcABhAHIAdABuAGUAcgBzAGgAaQBwACAAdwBpAHQAaAAgAG8AdABoAGUAcgBzAC4ADQAKAA0ACgBUAGgAZQAgAE8ARgBMACAAYQBsAGwAbwB3AHMAIAB0AGgAZQAgAGwAaQBjAGUAbgBzAGUAZAAgAGYAbwBuAHQAcwAgAHQAbwAgAGIAZQAgAHUAcwBlAGQALAAgAHMAdAB1AGQAaQBlAGQALAAgAG0AbwBkAGkAZgBpAGUAZAAgAGEAbgBkACAAcgBlAGQAaQBzAHQAcgBpAGIAdQB0AGUAZAAgAGYAcgBlAGUAbAB5ACAAYQBzACAAbABvAG4AZwAgAGEAcwAgAHQAaABlAHkAIABhAHIAZQAgAG4AbwB0ACAAcwBvAGwAZAAgAGIAeQAgAHQAaABlAG0AcwBlAGwAdgBlAHMALgAgAFQAaABlACAAZgBvAG4AdABzACwAIABpAG4AYwBsAHUAZABpAG4AZwAgAGEAbgB5ACAAZABlAHIAaQB2AGEAdABpAHYAZQAgAHcAbwByAGsAcwAsACAAYwBhAG4AIABiAGUAIABiAHUAbgBkAGwAZQBkACwAIABlAG0AYgBlAGQAZABlAGQALAAgAHIAZQBkAGkAcwB0AHIAaQBiAHUAdABlAGQAIABhAG4AZAAvAG8AcgAgAHMAbwBsAGQAIAB3AGkAdABoACAAYQBuAHkAIABzAG8AZgB0AHcAYQByAGUAIABwAHIAbwB2AGkAZABlAGQAIAB0AGgAYQB0ACAAYQBuAHkAIAByAGUAcwBlAHIAdgBlAGQAIABuAGEAbQBlAHMAIABhAHIAZQAgAG4AbwB0ACAAdQBzAGUAZAAgAGIAeQAgAGQAZQByAGkAdgBhAHQAaQB2AGUAIAB3AG8AcgBrAHMALgAgAFQAaABlACAAZgBvAG4AdABzACAAYQBuAGQAIABkAGUAcgBpAHYAYQB0AGkAdgBlAHMALAAgAGgAbwB3AGUAdgBlAHIALAAgAGMAYQBuAG4AbwB0ACAAYgBlACAAcgBlAGwAZQBhAHMAZQBkACAAdQBuAGQAZQByACAAYQBuAHkAIABvAHQAaABlAHIAIAB0AHkAcABlACAAbwBmACAAbABpAGMAZQBuAHMAZQAuACAAVABoAGUAIAByAGUAcQB1AGkAcgBlAG0AZQBuAHQAIABmAG8AcgAgAGYAbwBuAHQAcwAgAHQAbwAgAHIAZQBtAGEAaQBuACAAdQBuAGQAZQByACAAdABoAGkAcwAgAGwAaQBjAGUAbgBzAGUAIABkAG8AZQBzACAAbgBvAHQAIABhAHAAcABsAHkAIAB0AG8AIABhAG4AeQAgAGQAbwBjAHUAbQBlAG4AdAAgAGMAcgBlAGEAdABlAGQAIAB1AHMAaQBuAGcAIAB0AGgAZQAgAGYAbwBuAHQAcwAgAG8AcgAgAHQAaABlAGkAcgAgAGQAZQByAGkAdgBhAHQAaQB2AGUAcwAuAA0ACgANAAoARABFAEYASQBOAEkAVABJAE8ATgBTAA0ACgAiAEYAbwBuAHQAIABTAG8AZgB0AHcAYQByAGUAIgAgAHIAZQBmAGUAcgBzACAAdABvACAAdABoAGUAIABzAGUAdAAgAG8AZgAgAGYAaQBsAGUAcwAgAHIAZQBsAGUAYQBzAGUAZAAgAGIAeQAgAHQAaABlACAAQwBvAHAAeQByAGkAZwBoAHQAIABIAG8AbABkAGUAcgAoAHMAKQAgAHUAbgBkAGUAcgAgAHQAaABpAHMAIABsAGkAYwBlAG4AcwBlACAAYQBuAGQAIABjAGwAZQBhAHIAbAB5ACAAbQBhAHIAawBlAGQAIABhAHMAIABzAHUAYwBoAC4AIABUAGgAaQBzACAAbQBhAHkAIABpAG4AYwBsAHUAZABlACAAcwBvAHUAcgBjAGUAIABmAGkAbABlAHMALAAgAGIAdQBpAGwAZAAgAHMAYwByAGkAcAB0AHMAIABhAG4AZAAgAGQAbwBjAHUAbQBlAG4AdABhAHQAaQBvAG4ALgANAAoADQAKACIAUgBlAHMAZQByAHYAZQBkACAARgBvAG4AdAAgAE4AYQBtAGUAIgAgAHIAZQBmAGUAcgBzACAAdABvACAAYQBuAHkAIABuAGEAbQBlAHMAIABzAHAAZQBjAGkAZgBpAGUAZAAgAGEAcwAgAHMAdQBjAGgAIABhAGYAdABlAHIAIAB0AGgAZQAgAGMAbwBwAHkAcgBpAGcAaAB0ACAAcwB0AGEAdABlAG0AZQBuAHQAKABzACkALgANAAoADQAKACIATwByAGkAZwBpAG4AYQBsACAAVgBlAHIAcwBpAG8AbgAiACAAcgBlAGYAZQByAHMAIAB0AG8AIAB0AGgAZQAgAGMAbwBsAGwAZQBjAHQAaQBvAG4AIABvAGYAIABGAG8AbgB0ACAAUwBvAGYAdAB3AGEAcgBlACAAYwBvAG0AcABvAG4AZQBuAHQAcwAgAGEAcwAgAGQAaQBzAHQAcgBpAGIAdQB0AGUAZAAgAGIAeQAgAHQAaABlACAAQwBvAHAAeQByAGkAZwBoAHQAIABIAG8AbABkAGUAcgAoAHMAKQAuAA0ACgANAAoAIgBNAG8AZABpAGYAaQBlAGQAIABWAGUAcgBzAGkAbwBuACIAIAByAGUAZgBlAHIAcwAgAHQAbwAgAGEAbgB5ACAAZABlAHIAaQB2AGEAdABpAHYAZQAgAG0AYQBkAGUAIABiAHkAIABhAGQAZABpAG4AZwAgAHQAbwAsACAAZABlAGwAZQB0AGkAbgBnACwAIABvAHIAIABzAHUAYgBzAHQAaQB0AHUAdABpAG4AZwAgAC0ALQAgAGkAbgAgAHAAYQByAHQAIABvAHIAIABpAG4AIAB3AGgAbwBsAGUAIAAtAC0AIABhAG4AeQAgAG8AZgAgAHQAaABlACAAYwBvAG0AcABvAG4AZQBuAHQAcwAgAG8AZgAgAHQAaABlACAATwByAGkAZwBpAG4AYQBsACAAVgBlAHIAcwBpAG8AbgAsACAAYgB5ACAAYwBoAGEAbgBnAGkAbgBnACAAZgBvAHIAbQBhAHQAcwAgAG8AcgAgAGIAeQAgAHAAbwByAHQAaQBuAGcAIAB0AGgAZQAgAEYAbwBuAHQAIABTAG8AZgB0AHcAYQByAGUAIAB0AG8AIABhACAAbgBlAHcAIABlAG4AdgBpAHIAbwBuAG0AZQBuAHQALgANAAoADQAKACIAQQB1AHQAaABvAHIAIgAgAHIAZQBmAGUAcgBzACAAdABvACAAYQBuAHkAIABkAGUAcwBpAGcAbgBlAHIALAAgAGUAbgBnAGkAbgBlAGUAcgAsACAAcAByAG8AZwByAGEAbQBtAGUAcgAsACAAdABlAGMAaABuAGkAYwBhAGwAIAB3AHIAaQB0AGUAcgAgAG8AcgAgAG8AdABoAGUAcgAgAHAAZQByAHMAbwBuACAAdwBoAG8AIABjAG8AbgB0AHIAaQBiAHUAdABlAGQAIAB0AG8AIAB0AGgAZQAgAEYAbwBuAHQAIABTAG8AZgB0AHcAYQByAGUALgANAAoADQAKAFAARQBSAE0ASQBTAFMASQBPAE4AIAAmACAAQwBPAE4ARABJAFQASQBPAE4AUwANAAoAUABlAHIAbQBpAHMAcwBpAG8AbgAgAGkAcwAgAGgAZQByAGUAYgB5ACAAZwByAGEAbgB0AGUAZAAsACAAZgByAGUAZQAgAG8AZgAgAGMAaABhAHIAZwBlACwAIAB0AG8AIABhAG4AeQAgAHAAZQByAHMAbwBuACAAbwBiAHQAYQBpAG4AaQBuAGcAIABhACAAYwBvAHAAeQAgAG8AZgAgAHQAaABlACAARgBvAG4AdAAgAFMAbwBmAHQAdwBhAHIAZQAsACAAdABvACAAdQBzAGUALAAgAHMAdAB1AGQAeQAsACAAYwBvAHAAeQAsACAAbQBlAHIAZwBlACwAIABlAG0AYgBlAGQALAAgAG0AbwBkAGkAZgB5ACwAIAByAGUAZABpAHMAdAByAGkAYgB1AHQAZQAsACAAYQBuAGQAIABzAGUAbABsACAAbQBvAGQAaQBmAGkAZQBkACAAYQBuAGQAIAB1AG4AbQBvAGQAaQBmAGkAZQBkACAAYwBvAHAAaQBlAHMAIABvAGYAIAB0AGgAZQAgAEYAbwBuAHQAIABTAG8AZgB0AHcAYQByAGUALAAgAHMAdQBiAGoAZQBjAHQAIAB0AG8AIAB0AGgAZQAgAGYAbwBsAGwAbwB3AGkAbgBnACAAYwBvAG4AZABpAHQAaQBvAG4AcwA6AA0ACgANAAoAMQApACAATgBlAGkAdABoAGUAcgAgAHQAaABlACAARgBvAG4AdAAgAFMAbwBmAHQAdwBhAHIAZQAgAG4AbwByACAAYQBuAHkAIABvAGYAIABpAHQAcwAgAGkAbgBkAGkAdgBpAGQAdQBhAGwAIABjAG8AbQBwAG8AbgBlAG4AdABzACwAIABpAG4AIABPAHIAaQBnAGkAbgBhAGwAIABvAHIAIABNAG8AZABpAGYAaQBlAGQAIABWAGUAcgBzAGkAbwBuAHMALAAgAG0AYQB5ACAAYgBlACAAcwBvAGwAZAAgAGIAeQAgAGkAdABzAGUAbABmAC4ADQAKAA0ACgAyACkAIABPAHIAaQBnAGkAbgBhAGwAIABvAHIAIABNAG8AZABpAGYAaQBlAGQAIABWAGUAcgBzAGkAbwBuAHMAIABvAGYAIAB0AGgAZQAgAEYAbwBuAHQAIABTAG8AZgB0AHcAYQByAGUAIABtAGEAeQAgAGIAZQAgAGIAdQBuAGQAbABlAGQALAAgAHIAZQBkAGkAcwB0AHIAaQBiAHUAdABlAGQAIABhAG4AZAAvAG8AcgAgAHMAbwBsAGQAIAB3AGkAdABoACAAYQBuAHkAIABzAG8AZgB0AHcAYQByAGUALAAgAHAAcgBvAHYAaQBkAGUAZAAgAHQAaABhAHQAIABlAGEAYwBoACAAYwBvAHAAeQAgAGMAbwBuAHQAYQBpAG4AcwAgAHQAaABlACAAYQBiAG8AdgBlACAAYwBvAHAAeQByAGkAZwBoAHQAIABuAG8AdABpAGMAZQAgAGEAbgBkACAAdABoAGkAcwAgAGwAaQBjAGUAbgBzAGUALgAgAFQAaABlAHMAZQAgAGMAYQBuACAAYgBlACAAaQBuAGMAbAB1AGQAZQBkACAAZQBpAHQAaABlAHIAIABhAHMAIABzAHQAYQBuAGQALQBhAGwAbwBuAGUAIAB0AGUAeAB0ACAAZgBpAGwAZQBzACwAIABoAHUAbQBhAG4ALQByAGUAYQBkAGEAYgBsAGUAIABoAGUAYQBkAGUAcgBzACAAbwByACAAaQBuACAAdABoAGUAIABhAHAAcAByAG8AcAByAGkAYQB0AGUAIABtAGEAYwBoAGkAbgBlAC0AcgBlAGEAZABhAGIAbABlACAAbQBlAHQAYQBkAGEAdABhACAAZgBpAGUAbABkAHMAIAB3AGkAdABoAGkAbgAgAHQAZQB4AHQAIABvAHIAIABiAGkAbgBhAHIAeQAgAGYAaQBsAGUAcwAgAGEAcwAgAGwAbwBuAGcAIABhAHMAIAB0AGgAbwBzAGUAIABmAGkAZQBsAGQAcwAgAGMAYQBuACAAYgBlACAAZQBhAHMAaQBsAHkAIAB2AGkAZQB3AGUAZAAgAGIAeQAgAHQAaABlACAAdQBzAGUAcgAuAA0ACgANAAoAMwApACAATgBvACAATQBvAGQAaQBmAGkAZQBkACAAVgBlAHIAcwBpAG8AbgAgAG8AZgAgAHQAaABlACAARgBvAG4AdAAgAFMAbwBmAHQAdwBhAHIAZQAgAG0AYQB5ACAAdQBzAGUAIAB0AGgAZQAgAFIAZQBzAGUAcgB2AGUAZAAgAEYAbwBuAHQAIABOAGEAbQBlACgAcwApACAAdQBuAGwAZQBzAHMAIABlAHgAcABsAGkAYwBpAHQAIAB3AHIAaQB0AHQAZQBuACAAcABlAHIAbQBpAHMAcwBpAG8AbgAgAGkAcwAgAGcAcgBhAG4AdABlAGQAIABiAHkAIAB0AGgAZQAgAGMAbwByAHIAZQBzAHAAbwBuAGQAaQBuAGcAIABDAG8AcAB5AHIAaQBnAGgAdAAgAEgAbwBsAGQAZQByAC4AIABUAGgAaQBzACAAcgBlAHMAdAByAGkAYwB0AGkAbwBuACAAbwBuAGwAeQAgAGEAcABwAGwAaQBlAHMAIAB0AG8AIAB0AGgAZQAgAHAAcgBpAG0AYQByAHkAIABmAG8AbgB0ACAAbgBhAG0AZQAgAGEAcwAgAHAAcgBlAHMAZQBuAHQAZQBkACAAdABvACAAdABoAGUAIAB1AHMAZQByAHMALgANAAoADQAKADQAKQAgAFQAaABlACAAbgBhAG0AZQAoAHMAKQAgAG8AZgAgAHQAaABlACAAQwBvAHAAeQByAGkAZwBoAHQAIABIAG8AbABkAGUAcgAoAHMAKQAgAG8AcgAgAHQAaABlACAAQQB1AHQAaABvAHIAKABzACkAIABvAGYAIAB0AGgAZQAgAEYAbwBuAHQAIABTAG8AZgB0AHcAYQByAGUAIABzAGgAYQBsAGwAIABuAG8AdAAgAGIAZQAgAHUAcwBlAGQAIAB0AG8AIABwAHIAbwBtAG8AdABlACwAIABlAG4AZABvAHIAcwBlACAAbwByACAAYQBkAHYAZQByAHQAaQBzAGUAIABhAG4AeQAgAE0AbwBkAGkAZgBpAGUAZAAgAFYAZQByAHMAaQBvAG4ALAAgAGUAeABjAGUAcAB0ACAAdABvACAAYQBjAGsAbgBvAHcAbABlAGQAZwBlACAAdABoAGUAIABjAG8AbgB0AHIAaQBiAHUAdABpAG8AbgAoAHMAKQAgAG8AZgAgAHQAaABlACAAQwBvAHAAeQByAGkAZwBoAHQAIABIAG8AbABkAGUAcgAoAHMAKQAgAGEAbgBkACAAdABoAGUAIABBAHUAdABoAG8AcgAoAHMAKQAgAG8AcgAgAHcAaQB0AGgAIAB0AGgAZQBpAHIAIABlAHgAcABsAGkAYwBpAHQAIAB3AHIAaQB0AHQAZQBuACAAcABlAHIAbQBpAHMAcwBpAG8AbgAuAA0ACgANAAoANQApACAAVABoAGUAIABGAG8AbgB0ACAAUwBvAGYAdAB3AGEAcgBlACwAIABtAG8AZABpAGYAaQBlAGQAIABvAHIAIAB1AG4AbQBvAGQAaQBmAGkAZQBkACwAIABpAG4AIABwAGEAcgB0ACAAbwByACAAaQBuACAAdwBoAG8AbABlACwAIABtAHUAcwB0ACAAYgBlACAAZABpAHMAdAByAGkAYgB1AHQAZQBkACAAZQBuAHQAaQByAGUAbAB5ACAAdQBuAGQAZQByACAAdABoAGkAcwAgAGwAaQBjAGUAbgBzAGUALAAgAGEAbgBkACAAbQB1AHMAdAAgAG4AbwB0ACAAYgBlACAAZABpAHMAdAByAGkAYgB1AHQAZQBkACAAdQBuAGQAZQByACAAYQBuAHkAIABvAHQAaABlAHIAIABsAGkAYwBlAG4AcwBlAC4AIABUAGgAZQAgAHIAZQBxAHUAaQByAGUAbQBlAG4AdAAgAGYAbwByACAAZgBvAG4AdABzACAAdABvACAAcgBlAG0AYQBpAG4AIAB1AG4AZABlAHIAIAB0AGgAaQBzACAAbABpAGMAZQBuAHMAZQAgAGQAbwBlAHMAIABuAG8AdAAgAGEAcABwAGwAeQAgAHQAbwAgAGEAbgB5ACAAZABvAGMAdQBtAGUAbgB0ACAAYwByAGUAYQB0AGUAZAAgAHUAcwBpAG4AZwAgAHQAaABlACAARgBvAG4AdAAgAFMAbwBmAHQAdwBhAHIAZQAuAA0ACgANAAoAVABFAFIATQBJAE4AQQBUAEkATwBOAA0ACgBUAGgAaQBzACAAbABpAGMAZQBuAHMAZQAgAGIAZQBjAG8AbQBlAHMAIABuAHUAbABsACAAYQBuAGQAIAB2AG8AaQBkACAAaQBmACAAYQBuAHkAIABvAGYAIAB0AGgAZQAgAGEAYgBvAHYAZQAgAGMAbwBuAGQAaQB0AGkAbwBuAHMAIABhAHIAZQAgAG4AbwB0ACAAbQBlAHQALgANAAoADQAKAEQASQBTAEMATABBAEkATQBFAFIADQAKAFQASABFACAARgBPAE4AVAAgAFMATwBGAFQAVwBBAFIARQAgAEkAUwAgAFAAUgBPAFYASQBEAEUARAAgACIAQQBTACAASQBTACIALAAgAFcASQBUAEgATwBVAFQAIABXAEEAUgBSAEEATgBUAFkAIABPAEYAIABBAE4AWQAgAEsASQBOAEQALAAgAEUAWABQAFIARQBTAFMAIABPAFIAIABJAE0AUABMAEkARQBEACwAIABJAE4AQwBMAFUARABJAE4ARwAgAEIAVQBUACAATgBPAFQAIABMAEkATQBJAFQARQBEACAAVABPACAAQQBOAFkAIABXAEEAUgBSAEEATgBUAEkARQBTACAATwBGACAATQBFAFIAQwBIAEEATgBUAEEAQgBJAEwASQBUAFkALAAgAEYASQBUAE4ARQBTAFMAIABGAE8AUgAgAEEAIABQAEEAUgBUAEkAQwBVAEwAQQBSACAAUABVAFIAUABPAFMARQAgAEEATgBEACAATgBPAE4ASQBOAEYAUgBJAE4ARwBFAE0ARQBOAFQAIABPAEYAIABDAE8AUABZAFIASQBHAEgAVAAsACAAUABBAFQARQBOAFQALAAgAFQAUgBBAEQARQBNAEEAUgBLACwAIABPAFIAIABPAFQASABFAFIAIABSAEkARwBIAFQALgAgAEkATgAgAE4ATwAgAEUAVgBFAE4AVAAgAFMASABBAEwATAAgAFQASABFACAAQwBPAFAAWQBSAEkARwBIAFQAIABIAE8ATABEAEUAUgAgAEIARQAgAEwASQBBAEIATABFACAARgBPAFIAIABBAE4AWQAgAEMATABBAEkATQAsACAARABBAE0AQQBHAEUAUwAgAE8AUgAgAE8AVABIAEUAUgAgAEwASQBBAEIASQBMAEkAVABZACwAIABJAE4AQwBMAFUARABJAE4ARwAgAEEATgBZACAARwBFAE4ARQBSAEEATAAsACAAUwBQAEUAQwBJAEEATAAsACAASQBOAEQASQBSAEUAQwBUACwAIABJAE4AQwBJAEQARQBOAFQAQQBMACwAIABPAFIAIABDAE8ATgBTAEUAUQBVAEUATgBUAEkAQQBMACAARABBAE0AQQBHAEUAUwAsACAAVwBIAEUAVABIAEUAUgAgAEkATgAgAEEATgAgAEEAQwBUAEkATwBOACAATwBGACAAQwBPAE4AVABSAEEAQwBUACwAIABUAE8AUgBUACAATwBSACAATwBUAEgARQBSAFcASQBTAEUALAAgAEEAUgBJAFMASQBOAEcAIABGAFIATwBNACwAIABPAFUAVAAgAE8ARgAgAFQASABFACAAVQBTAEUAIABPAFIAIABJAE4AQQBCAEkATABJAFQAWQAgAFQATwAgAFUAUwBFACAAVABIAEUAIABGAE8ATgBUACAAUwBPAEYAVABXAEEAUgBFACAATwBSACAARgBSAE8ATQAgAE8AVABIAEUAUgAgAEQARQBBAEwASQBOAEcAUwAgAEkATgAgAFQASABFACAARgBPAE4AVAAgAFMATwBGAFQAVwBBAFIARQAuAA0ACgBoAHQAdABwADoALwAvAHcAdwB3AC4AYQBkAG8AYgBlAC4AYwBvAG0ALwB0AHkAcABlAC8AbABlAGcAYQBsAC4AaAB0AG0AbABTAGwAYQBzAGgAZQBkACAAegBlAHIAbwBTAHQAcgBhAGkAZwBoAHQAIABsAEEAbAB0AGUAcgBuAGEAdABlACAAYQBBAGwAdABlAHIAbgBhAHQAZQAgAGcAUwBlAHIAaQBmAGUAZAAgAEkAAAACAAAAAAAA/7UAMgAAAAAAAAAAAAAAAAAAAAAAAAAABFsAAAECAQMAAwAkACUAJgAnACgAKQAqACsALAAtAC4ALwAwADEAMgAzADQANQA2ADcAOAA5ADoAOwA8AD0ARABFAEYARwBIAEkASgBLAEwATQBOAE8AUABRAFIAUwBUAFUAVgBXAFgAWQBaAFsAXABdAK0AyQDHAK4AYgEEAQUAYwEGAQcBCAEJAQoBCwEMAQ0BDgEPARABEQESARMAkABkAP0BFAD/ARUBFgEXARgBGQDLAGUAyAEaAMoBGwEcAR0BHgEfASABIQEiASMBJAElASYBJwD4ASgBKQEqASsBLAEtAS4BLwEwAM8AzADNATEAzgEyAPoBMwE0ATUBNgE3ATgBOQE6ATsBPAE9AT4BPwDiAUABQQFCAGYBQwFEAUUBRgDTANAA0QCvAGcBRwFIAUkBSgFLAUwBTQFOAU8BUACRALABUQFSAVMBVAFVAVYBVwFYAVkBWgFbAVwBXQFeAV8A5AFgAWEBYgFjAWQBZQFmAWcBaAFpANYA1ADVAWoAaAFrAWwBbQFuAW8BcAFxAXIBcwF0AXUBdgF3AXgBeQF6AXsBfAF9AX4BfwGAAYEA6wGCALsBgwGEAYUBhgGHAOYBiAGJAOkA7QGKAGoAaQBrAG0AbAGLAYwAbgGNAY4BjwGQAZEBkgGTAZQBlQGWAZcBmAGZAZoAoABvAP4BmwEAAZwBnQGeAZ8BAQBxAHAAcgGgAHMBoQGiAaMBpAGlAaYBpwGoAakBqgGrAawBrQD5Aa4BrwGwAbEBsgGzAbQBtQG2AHUAdAB2AbcAdwG4AbkBugG7AbwBvQDXAb4BvwHAAcEBwgHDAcQBxQHGAccA4wHIAckBygB4AcsBzAHNAc4BzwB6AHkAewB9AHwB0AHRAdIB0wHUAdUB1gHXAdgB2QChALEB2gHbAdwB3QHeAd8B4AHhAeIB4wHkAeUB5gHnAegA5QHpAeoB6wHsAIkB7QHuAe8B8AHxAfIAfwB+AIAB8wCBAfQB9QH2AfcB+AH5AfoB+wH8Af0B/gH/AgACAQICAgMCBAIFAgYCBwIIAgkCCgDsAgsAugIMAg0CDgIPAhAA5wIRAhIA6gDuAhMCFAIVAhYCFwDAAMECGAIZAhoCGwIcAh0CHgIfAiACIQIiAiMCJAIlAiYCJwIoAikCKgIrAiwCLQIuAi8CMAIxAjICMwI0AjUCNgI3AjgCOQI6AjsCPAI9Aj4CPwJAAkECQgJDAkQCRQJGAkcCSAJJAkoCSwJMAk0ACQATABQAFQAWABcAGAAZABoAGwAcAk4CTwJQAlECUgJTAlQCVQJWAlcCWAJZAloCWwJcAl0CXgJfAmACYQJiAmMCZAJlAmYCZwJoAmkCagJrABEADwAdAB4AqwAEAKMAIgCiAAoABQC2ALcAtAC1AMQAxQC+AL8AqQCqABACbACyALMCbQJuAMMAhwBCAAsADAA+AEAAXgBgABIAXwA/AOgADQCCAMIAhgCIAIsCbwCKAIwCcAAjAnEABgJyAnMCdAJ1AnYCdwJ4AnkCegJ7AnwCfQJ+An8CgAKBAoICgwKEAoUChgKHAogCiQKKAosCjAKNAo4CjwKQApECkgKTApQClQKWApcCmAKZApoCmwKcAp0CngKfAqACoQKiAqMCpAKlAqYCpwKoAqkAnQKqAJ4CqwKsAq0CrgKvArACsQKyArMCtAK1ArYCtwK4ArkCugK7ArwCvQK+Ar8CwALBAsICwwLEAsUCxgLHAsgCyQLKAIMAvQAHAIUAlgLLAIQCzALNAs4CzwLQAtEC0gLTAtQC1QLWALwC1wLYAAgAxgD1APQA9gLZAtoC2wLcAt0C3gAOAO8A8AC4At8AIAAfACEAlACVAJMAQQCPAGEApwCkAJsAkgLgAJgAnAClAuEC4gCZAJoC4wLkAuUC5gLnAugC6QLqAusC7ALtAu4C7wLwAvEC8gLzAvQC9QL2AvcC+AC5AvkC+gL7AvwC/QL+AEMAjQDYAOEC/wMAAwEDAgMDANkAjgDaANsA3QDfANwA3gDgAwQDBQMGAwcDCAMJAwoDCwMMAw0DDgMPAxADEQMSAxMDFAMVAxYDFwMYAxkDGgMbAxwDHQMeAx8DIAMhAyIDIwMkAyUDJgMnAygDKQMqAysDLAMtAy4DLwMwAzEDMgMzAzQDNQM2AzcDOAM5AzoDOwM8Az0DPgM/A0ADQQNCA0MDRANFA0YDRwNIA0kDSgNLA0wDTQNOA08DUANRA1IDUwNUA1UDVgNXA1gDWQNaA1sDXANdA14DXwNgA2EDYgNjA2QDZQNmA2cDaANpA2oDawNsA20DbgNvA3ADcQNyA3MDdAN1A3YDdwN4A3kDegN7A3wDfQN+A38DgAOBA4IDgwOEA4UDhgOHA4gDiQOKA4sDjAONA44DjwOQA5EDkgOTA5QDlQOWA5cDmAOZA5oDmwOcA50DngOfA6ADoQOiA6MDpAOlA6YDpwOoA6kDqgOrA6wDrQOuA68DsAOxA7IDswO0A7UDtgO3A7gDuQO6A7sDvAO9A74DvwPAA8EDwgPDA8QDxQPGA8cDyAPJA8oDywPMA80DzgPPA9AD0QPSA9MD1APVA9YD1wPYA9kD2gPbA9wD3QPeA98D4APhA+ID4wPkA+UD5gPnA+gD6QPqA+sD7APtA+4D7wPwA/ED8gPzA/QD9QP2A/cD+AP5A/oD+wP8A/0D/gP/BAAEAQQCBAMEBAQFBAYEBwQIBAkECgQLBAwEDQQOBA8EEAQRBBIEEwQUBBUEFgQXBBgEGQQaBBsEHAQdBB4EHwQgBCEEIgQjBCQEJQQmBCcEKAQpBCoEKwQsBC0ELgQvBDAEMQQyBDMENAQ1BDYENwQ4BDkEOgQ7BDwEPQQ+BD8EQARBBEIEQwREBEUERgRHBEgESQRKBEsETARNBE4ETwRQBFEEUgRTBFQEVQRWBFcEWARZBFoEWwRcBF0EXgRfBGAEYQRiBGMEZARlBGYEZwRoBE5VTEwCQ1IHQW1hY3JvbgZBYnJldmUHdW5pMDFDRAd1bmkxRUEwB3VuaTFFQTIHdW5pMUVBNAd1bmkxRUE2B3VuaTFFQTgHdW5pMUVBQQd1bmkxRUFDB3VuaTFFQUUHdW5pMUVCMAd1bmkxRUIyB3VuaTFFQjQHdW5pMUVCNgdBb2dvbmVrC0NjaXJjdW1mbGV4CkNkb3RhY2NlbnQGRGNhcm9uB3VuaTFFMEMHdW5pMUUwRQZEY3JvYXQGRWNhcm9uB0VtYWNyb24GRWJyZXZlCkVkb3RhY2NlbnQHdW5pMUVCOAd1bmkxRUJBB3VuaTFFQkMHdW5pMUVCRQd1bmkxRUMwB3VuaTFFQzIHdW5pMUVDNAd1bmkxRUM2B0VvZ29uZWsLR2NpcmN1bWZsZXgKR2RvdGFjY2VudAd1bmkwMTIyBkdjYXJvbgd1bmkxRTIwC3VuaTAwNDcwMzAzC0hjaXJjdW1mbGV4B3VuaTFFMjQHdW5pMUUyQQRIYmFyBkl0aWxkZQdJbWFjcm9uB3VuaTAxQ0YHdW5pMUVDOAd1bmkxRUNBB0lvZ29uZWsLSmNpcmN1bWZsZXgHdW5pMDEzNgZMYWN1dGUGTGNhcm9uB3VuaTAxM0IETGRvdAd1bmkxRTM2B3VuaTFFMzgHdW5pMUUzQQd1bmkxRTQyBk5hY3V0ZQZOY2Fyb24HdW5pMDE0NQd1bmkxRTQ0B3VuaTFFNDYHdW5pMUU0OAdPbWFjcm9uDU9odW5nYXJ1bWxhdXQHdW5pMDFEMQd1bmkxRUNDB3VuaTFFQ0UHdW5pMUVEMAd1bmkxRUQyB3VuaTFFRDQHdW5pMUVENgd1bmkxRUQ4BU9ob3JuB3VuaTFFREEHdW5pMUVEQwd1bmkxRURFB3VuaTFFRTAHdW5pMUVFMgd1bmkwMUVBBlJhY3V0ZQZSY2Fyb24HdW5pMDE1Ngd1bmkxRTVBB3VuaTFFNUMHdW5pMUU1RQZTYWN1dGULU2NpcmN1bWZsZXgHdW5pMDE1RQd1bmkwMjE4B3VuaTFFNjAHdW5pMUU2Mgd1bmkxRTlFBlRjYXJvbgd1bmkwMTYyB3VuaTAyMUEHdW5pMUU2Qwd1bmkxRTZFBlV0aWxkZQdVbWFjcm9uBlVicmV2ZQVVcmluZw1VaHVuZ2FydW1sYXV0B3VuaTAxRDMHdW5pMDFENQd1bmkwMUQ3B3VuaTAxRDkHdW5pMDFEQgd1bmkxRUU0B3VuaTFFRTYHVW9nb25lawVVaG9ybgd1bmkxRUU4B3VuaTFFRUEHdW5pMUVFQwd1bmkxRUVFB3VuaTFFRjAGV2dyYXZlBldhY3V0ZQtXY2lyY3VtZmxleAlXZGllcmVzaXMGWWdyYXZlC1ljaXJjdW1mbGV4B3VuaTFFOEUHdW5pMUVGNAd1bmkxRUY2B3VuaTFFRjgGWmFjdXRlClpkb3RhY2NlbnQHdW5pMUU5Mgd1bmkwMThGB2FtYWNyb24GYWJyZXZlB3VuaTAxQ0UHdW5pMUVBMQd1bmkxRUEzB3VuaTFFQTUHdW5pMUVBNwd1bmkxRUE5B3VuaTFFQUIHdW5pMUVBRAd1bmkxRUFGB3VuaTFFQjEHdW5pMUVCMwd1bmkxRUI1B3VuaTFFQjcHYW9nb25lawtjY2lyY3VtZmxleApjZG90YWNjZW50BmRjYXJvbgd1bmkxRTBEB3VuaTFFMEYGZWNhcm9uB2VtYWNyb24GZWJyZXZlCmVkb3RhY2NlbnQHdW5pMUVCOQd1bmkxRUJCB3VuaTFFQkQHdW5pMUVCRgd1bmkxRUMxB3VuaTFFQzMHdW5pMUVDNQd1bmkxRUM3B2VvZ29uZWsLZ2NpcmN1bWZsZXgKZ2RvdGFjY2VudAd1bmkwMTIzBmdjYXJvbgd1bmkxRTIxC3VuaTAwNjcwMzAzC2hjaXJjdW1mbGV4B3VuaTFFMjUHdW5pMUUyQgRoYmFyBml0aWxkZQdpbWFjcm9uB3VuaTAxRDAHdW5pMUVDOQd1bmkxRUNCB2lvZ29uZWsJaW9nb25lay5kC2pjaXJjdW1mbGV4B3VuaTAxMzcMa2dyZWVubGFuZGljBmxhY3V0ZQZsY2Fyb24EbGRvdAd1bmkwMTNDB3VuaTFFMzcHdW5pMUUzOQd1bmkxRTNCB3VuaTFFNDMGbmFjdXRlBm5jYXJvbgd1bmkwMTQ2B3VuaTFFNDUHdW5pMUU0Nwd1bmkxRTQ5C25hcG9zdHJvcGhlB29tYWNyb24Nb2h1bmdhcnVtbGF1dAd1bmkwMUQyB3VuaTFFQ0QHdW5pMUVDRgd1bmkxRUQxB3VuaTFFRDMHdW5pMUVENQd1bmkxRUQ3B3VuaTFFRDkFb2hvcm4HdW5pMUVEQgd1bmkxRUREB3VuaTFFREYHdW5pMUVFMQd1bmkxRUUzB3VuaTAxRUIGcmFjdXRlB3VuaTAxNTcGcmNhcm9uB3VuaTFFNUIHdW5pMUU1RAd1bmkxRTVGBnNhY3V0ZQtzY2lyY3VtZmxleAd1bmkwMTVGB3VuaTAyMTkHdW5pMUU2MQd1bmkxRTYzBnRjYXJvbgd1bmkwMTYzB3VuaTAyMUIHdW5pMUU2RAd1bmkxRTZGB3VuaTFFOTcGdXRpbGRlB3VtYWNyb24GdWJyZXZlBXVyaW5nDXVodW5nYXJ1bWxhdXQHdW5pMDFENAd1bmkwMUQ2B3VuaTAxRDgHdW5pMDFEQQd1bmkwMURDB3VuaTFFRTUHdW5pMUVFNwd1b2dvbmVrBXVob3JuB3VuaTFFRTkHdW5pMUVFQgd1bmkxRUVEB3VuaTFFRUYHdW5pMUVGMQZ3Z3JhdmUGd2FjdXRlC3djaXJjdW1mbGV4CXdkaWVyZXNpcwZ5Z3JhdmULeWNpcmN1bWZsZXgHdW5pMUU4Rgd1bmkxRUY1B3VuaTFFRjcHdW5pMUVGOQZ6YWN1dGUKemRvdGFjY2VudAd1bmkxRTkzB3VuaTAyMzcHdW5pMDI1MQd1bmkwMjU5B3VuaTAyNjEDZl9mA2ZfdANJLmEISWdyYXZlLmEISWFjdXRlLmENSWNpcmN1bWZsZXguYQhJdGlsZGUuYQtJZGllcmVzaXMuYQlJbWFjcm9uLmEMSWRvdGFjY2VudC5hCXVuaTAxQ0YuYQl1bmkxRUM4LmEJdW5pMUVDQS5hCUlvZ29uZWsuYQNhLmEIYWdyYXZlLmEIYWFjdXRlLmENYWNpcmN1bWZsZXguYQhhdGlsZGUuYQthZGllcmVzaXMuYQlhbWFjcm9uLmEIYWJyZXZlLmEHYXJpbmcuYQl1bmkwMUNFLmEJdW5pMUVBMS5hCXVuaTFFQTMuYQl1bmkxRUE1LmEJdW5pMUVBNy5hCXVuaTFFQTkuYQl1bmkxRUFCLmEJdW5pMUVBRC5hCXVuaTFFQUYuYQl1bmkxRUIxLmEJdW5pMUVCMy5hCXVuaTFFQjUuYQl1bmkxRUI3LmEJYW9nb25lay5hA2cuYQ1nY2lyY3VtZmxleC5hCGdicmV2ZS5hDGdkb3RhY2NlbnQuYQl1bmkwMTIzLmEIZ2Nhcm9uLmEJdW5pMUUyMS5hDXVuaTAwNjcwMzAzLmEDbC5hCGxhY3V0ZS5hCGxjYXJvbi5hBmxkb3QuYQl1bmkwMTNDLmEJdW5pMUUzNy5hCXVuaTFFMzkuYQl1bmkxRTNCLmEIbHNsYXNoLmEEZmwuYQl6ZXJvLnBudW0Ib25lLnBudW0IdHdvLnBudW0KdGhyZWUucG51bQlmb3VyLnBudW0JZml2ZS5wbnVtCHNpeC5wbnVtCnNldmVuLnBudW0KZWlnaHQucG51bQluaW5lLnBudW0JemVyby50bnVtCG9uZS50bnVtCHR3by50bnVtCnRocmVlLnRudW0JZm91ci50bnVtCWZpdmUudG51bQhzaXgudG51bQpzZXZlbi50bnVtCmVpZ2h0LnRudW0JbmluZS50bnVtCXplcm8ub251bQhvbmUub251bQh0d28ub251bQp0aHJlZS5vbnVtCWZvdXIub251bQlmaXZlLm9udW0Ic2l4Lm9udW0Kc2V2ZW4ub251bQplaWdodC5vbnVtCW5pbmUub251bQd1bmkwMEFECmZpZ3VyZWRhc2gHdW5pMjAxNQd1bmkyMTE3B3VuaTIxMjAHYXQuY2FzZQl6ZXJvLnN1cHMIb25lLnN1cHMIdHdvLnN1cHMKdGhyZWUuc3Vwcwlmb3VyLnN1cHMJZml2ZS5zdXBzCHNpeC5zdXBzCnNldmVuLnN1cHMKZWlnaHQuc3VwcwluaW5lLnN1cHMOcGFyZW5sZWZ0LnN1cHMPcGFyZW5yaWdodC5zdXBzC3BlcmlvZC5zdXBzCmNvbW1hLnN1cHMJemVyby5zdWJzCG9uZS5zdWJzCHR3by5zdWJzCnRocmVlLnN1YnMJZm91ci5zdWJzCWZpdmUuc3VicwhzaXguc3VicwpzZXZlbi5zdWJzCmVpZ2h0LnN1YnMJbmluZS5zdWJzDnBhcmVubGVmdC5zdWJzD3BhcmVucmlnaHQuc3VicwtwZXJpb2Quc3Vicwpjb21tYS5zdWJzCXplcm8uZG5vbQhvbmUuZG5vbQh0d28uZG5vbQp0aHJlZS5kbm9tCWZvdXIuZG5vbQlmaXZlLmRub20Ic2l4LmRub20Kc2V2ZW4uZG5vbQplaWdodC5kbm9tCW5pbmUuZG5vbQ5wYXJlbmxlZnQuZG5vbQ9wYXJlbnJpZ2h0LmRub20LcGVyaW9kLmRub20KY29tbWEuZG5vbQl6ZXJvLm51bXIIb25lLm51bXIIdHdvLm51bXIKdGhyZWUubnVtcglmb3VyLm51bXIJZml2ZS5udW1yCHNpeC5udW1yCnNldmVuLm51bXIKZWlnaHQubnVtcgluaW5lLm51bXIOcGFyZW5sZWZ0Lm51bXIPcGFyZW5yaWdodC5udW1yC3BlcmlvZC5udW1yCmNvbW1hLm51bXINb3JkZmVtaW5pbmUuYQZhLnN1cHMGYi5zdXBzBmMuc3VwcwZkLnN1cHMGZS5zdXBzBmYuc3VwcwZnLnN1cHMGaC5zdXBzBmkuc3VwcwZqLnN1cHMGay5zdXBzBmwuc3VwcwZtLnN1cHMGbi5zdXBzBm8uc3VwcwZwLnN1cHMGcS5zdXBzBnIuc3VwcwZzLnN1cHMGdC5zdXBzBnUuc3VwcwZ2LnN1cHMGdy5zdXBzBnguc3VwcwZ5LnN1cHMGei5zdXBzC2VncmF2ZS5zdXBzC2VhY3V0ZS5zdXBzDHVuaTAyNTkuc3VwcwZhLnN1cGEGZy5zdXBhBmwuc3VwYQRFdXJvB3VuaTAxOTINY29sb25tb25ldGFyeQRsaXJhB3VuaTIwQTYGcGVzZXRhBGRvbmcHdW5pMjBCMQd1bmkyMEIyB3VuaTIwQjUHdW5pMjBCOQd1bmkyMEJBB3VuaTIyMTUKc2xhc2guZnJhYwhvbmV0aGlyZAl0d290aGlyZHMJb25lZWlnaHRoDHRocmVlZWlnaHRocwtmaXZlZWlnaHRocwxzZXZlbmVpZ2h0aHMHdW5pMjIxOQd1bmkwMEI1B3VuaTIyMDYHdW5pMjEyNgd1bmkyMTEzCWVzdGltYXRlZAd1bmkyMTkwB2Fycm93dXAHdW5pMjE5MglhcnJvd2Rvd24HdW5pMjVBMAd1bmkyNUM2B3VuaTI1QzkHdW5pMjc1Mgd0cmlhZ3VwB3VuaTI1QjMHdW5pMjVCNgd1bmkyNUI3B3RyaWFnZG4HdW5pMjVCRAd1bmkyNUMwB3VuaTI1QzEHdW5pMjYxMAd1bmkyNjExB3VuaTI3MTMHdW5pMjY2QQd1bmkyMDMyB3VuaTIwMzMHdW5pMDJCQgd1bmkwMkJDB3VuaTAyQkUHdW5pMDJCRgd1bmkwMkM4B3VuaTAyQzkHdW5pMDJDQQd1bmkwMkNCB3VuaTAyQ0MHdW5pMDMwMAt1bmkwMzAwLmNhcAd1bmkwMzAxC3VuaTAzMDEuY2FwB3VuaTAzMDILdW5pMDMwMi5jYXAHdW5pMDMwMwt1bmkwMzAzLmNhcAd1bmkwMzA0C3VuaTAzMDQuY2FwB3VuaTAzMDYLdW5pMDMwNi5jYXAHdW5pMDMwNwt1bmkwMzA3LmNhcAd1bmkwMzA4C3VuaTAzMDguY2FwB3VuaTAzMDkLdW5pMDMwOS5jYXAHdW5pMDMwQQt1bmkwMzBBLmNhcAd1bmkwMzBCC3VuaTAzMEIuY2FwB3VuaTAzMEMLdW5pMDMwQy5jYXAHdW5pMDMwRgt1bmkwMzBGLmNhcAd1bmkwMzEyB3VuaTAzMTMHdW5pMDMxQgd1bmkwMzIzB3VuaTAzMjQHdW5pMDMyNgd1bmkwMzI3C3VuaTAzMjcuY2FwB3VuaTAzMjgLdW5pMDMyOC5jYXAHdW5pMDMyRQd1bmkwMzMxC3VuaTAzMDgwMzA0D3VuaTAzMDgwMzA0LmNhcAt1bmkwMzA4MDMwMQ91bmkwMzA4MDMwMS5jYXALdW5pMDMwODAzMEMPdW5pMDMwODAzMEMuY2FwC3VuaTAzMDgwMzAwD3VuaTAzMDgwMzAwLmNhcAt1bmkwMzAyMDMwMQ91bmkwMzAyMDMwMS5jYXALdW5pMDMwMjAzMDAPdW5pMDMwMjAzMDAuY2FwC3VuaTAzMDIwMzA5D3VuaTAzMDIwMzA5LmNhcAt1bmkwMzAyMDMwMw91bmkwMzAyMDMwMy5jYXALdW5pMDMwNjAzMDEPdW5pMDMwNjAzMDEuY2FwC3VuaTAzMDYwMzAwD3VuaTAzMDYwMzAwLmNhcAt1bmkwMzA2MDMwOQ91bmkwMzA2MDMwOS5jYXALdW5pMDMwNjAzMDMPdW5pMDMwNjAzMDMuY2FwCXVuaTAzMEMuYQl1bmkwMzI2LmEHdW5pMDBBMAd1bmkyMDA3CnNwYWNlLmZyYWMMbmJzcGFjZS5mcmFjB3VuaTAyNDMHdW5pMDEyQwd1bmkwMTRFB3VuaTAxODAHdW5pMDEyRAd1bmkwMTRGC3VuaTAzMDIwMzA2D3VuaTAzMDIwMzA2LmNhcAd1bmkxRTA2B3VuaTFFMDcHdW5pMUUzNAd1bmkxRTM1B3VuaTFFMTYHdW5pMUUxNwd1bmkxRTUyB3VuaTFFNTMHdW5pMjAxNgd1bmkyMDNEB3VuaTIzMUMHdW5pMjMxRAd1bmkyMzFFB3VuaTIzMUYHdW5pMjdFNgd1bmkyN0U3B3VuaTJFMjIHdW5pMkUyMwd1bmkyRTI0B3VuaTJFMjUGemVyby4wB3plcm8uMHMHemVyby4wcAh6ZXJvLjBwcwVpLnRyawRBLnNjBEIuc2MEQy5zYwRELnNjBEUuc2MERi5zYwRHLnNjBEguc2MESS5zYwRKLnNjBEsuc2METC5zYwRNLnNjBE4uc2METy5zYwRQLnNjBFEuc2MEUi5zYwRTLnNjBFQuc2MEVS5zYwRWLnNjBFcuc2MEWC5zYwRZLnNjBFouc2MJQWdyYXZlLnNjCUFhY3V0ZS5zYw5BY2lyY3VtZmxleC5zYwlBdGlsZGUuc2MMQWRpZXJlc2lzLnNjCkFtYWNyb24uc2MJQWJyZXZlLnNjCEFyaW5nLnNjCnVuaTAxQ0Quc2MKdW5pMUVBMC5zYwp1bmkxRUEyLnNjCnVuaTFFQTQuc2MKdW5pMUVBNi5zYwp1bmkxRUE4LnNjCnVuaTFFQUEuc2MKdW5pMUVBQy5zYwp1bmkxRUFFLnNjCnVuaTFFQjAuc2MKdW5pMUVCMi5zYwp1bmkxRUI0LnNjCnVuaTFFQjYuc2MKQW9nb25lay5zYwVBRS5zYwp1bmkwMjQzLnNjCnVuaTFFMDYuc2MLQ2NlZGlsbGEuc2MJQ2FjdXRlLnNjDkNjaXJjdW1mbGV4LnNjCUNjYXJvbi5zYw1DZG90YWNjZW50LnNjCURjYXJvbi5zYwp1bmkxRTBDLnNjCnVuaTFFMEUuc2MJRGNyb2F0LnNjCUVncmF2ZS5zYwlFYWN1dGUuc2MORWNpcmN1bWZsZXguc2MJRWNhcm9uLnNjDEVkaWVyZXNpcy5zYwpFbWFjcm9uLnNjCUVicmV2ZS5zYw1FZG90YWNjZW50LnNjCnVuaTFFQjguc2MKdW5pMUVCQS5zYwp1bmkxRUJDLnNjCnVuaTFFQkUuc2MKdW5pMUVDMC5zYwp1bmkxRUMyLnNjCnVuaTFFQzQuc2MKdW5pMUVDNi5zYwpFb2dvbmVrLnNjCnVuaTFFMTYuc2MOR2NpcmN1bWZsZXguc2MJR2JyZXZlLnNjDUdkb3RhY2NlbnQuc2MKdW5pMDEyMi5zYwlHY2Fyb24uc2MKdW5pMUUyMC5zYw51bmkwMDQ3MDMwMy5zYw5IY2lyY3VtZmxleC5zYwp1bmkxRTI0LnNjCnVuaTFFMkEuc2MHSGJhci5zYwlJZ3JhdmUuc2MJSWFjdXRlLnNjDkljaXJjdW1mbGV4LnNjCUl0aWxkZS5zYwxJZGllcmVzaXMuc2MKSW1hY3Jvbi5zYw1JZG90YWNjZW50LnNjCnVuaTAxQ0Yuc2MKdW5pMUVDOC5zYwp1bmkxRUNBLnNjCklvZ29uZWsuc2MKdW5pMDEyQy5zYw5KY2lyY3VtZmxleC5zYwp1bmkwMTM2LnNjCnVuaTFFMzQuc2MJTGFjdXRlLnNjCUxjYXJvbi5zYwp1bmkwMTNCLnNjB0xkb3Quc2MKdW5pMUUzNi5zYwp1bmkxRTM4LnNjCnVuaTFFM0Euc2MJTHNsYXNoLnNjCnVuaTFFNDIuc2MJTmFjdXRlLnNjCU5jYXJvbi5zYwlOdGlsZGUuc2MKdW5pMDE0NS5zYwp1bmkxRTQ0LnNjCnVuaTFFNDYuc2MKdW5pMUU0OC5zYwlPZ3JhdmUuc2MJT2FjdXRlLnNjDk9jaXJjdW1mbGV4LnNjCU90aWxkZS5zYwxPZGllcmVzaXMuc2MKT21hY3Jvbi5zYxBPaHVuZ2FydW1sYXV0LnNjCnVuaTAxRDEuc2MKdW5pMUVDQy5zYwp1bmkxRUNFLnNjCnVuaTFFRDAuc2MKdW5pMUVEMi5zYwp1bmkxRUQ0LnNjCnVuaTFFRDYuc2MKdW5pMUVEOC5zYwlPc2xhc2guc2MFT0Uuc2MIT2hvcm4uc2MKdW5pMUVEQS5zYwp1bmkxRURDLnNjCnVuaTFFREUuc2MKdW5pMUVFMC5zYwp1bmkxRUUyLnNjCnVuaTAxRUEuc2MKdW5pMDE0RS5zYwp1bmkxRTUyLnNjCVJhY3V0ZS5zYwlSY2Fyb24uc2MKdW5pMDE1Ni5zYwp1bmkxRTVBLnNjCnVuaTFFNUMuc2MKdW5pMUU1RS5zYwlTYWN1dGUuc2MOU2NpcmN1bWZsZXguc2MJU2Nhcm9uLnNjCnVuaTAxNUUuc2MKdW5pMDIxOC5zYwp1bmkxRTYwLnNjCnVuaTFFNjIuc2MNZ2VybWFuZGJscy5zYwp1bmkxRTlFLnNjCVRjYXJvbi5zYwp1bmkwMTYyLnNjCnVuaTAyMUEuc2MKdW5pMUU2Qy5zYwp1bmkxRTZFLnNjCVVncmF2ZS5zYwlVYWN1dGUuc2MOVWNpcmN1bWZsZXguc2MJVXRpbGRlLnNjDFVkaWVyZXNpcy5zYwpVbWFjcm9uLnNjCVVicmV2ZS5zYwhVcmluZy5zYxBVaHVuZ2FydW1sYXV0LnNjCnVuaTAxRDMuc2MKdW5pMDFENS5zYwp1bmkwMUQ3LnNjCnVuaTAxRDkuc2MKdW5pMDFEQi5zYwp1bmkxRUU0LnNjCnVuaTFFRTYuc2MKVW9nb25lay5zYwhVaG9ybi5zYwp1bmkxRUU4LnNjCnVuaTFFRUEuc2MKdW5pMUVFQy5zYwp1bmkxRUVFLnNjCnVuaTFFRjAuc2MJV2dyYXZlLnNjCVdhY3V0ZS5zYw5XY2lyY3VtZmxleC5zYwxXZGllcmVzaXMuc2MJWWdyYXZlLnNjCVlhY3V0ZS5zYw5ZY2lyY3VtZmxleC5zYwxZZGllcmVzaXMuc2MKdW5pMUU4RS5zYwp1bmkxRUY0LnNjCnVuaTFFRjYuc2MKdW5pMUVGOC5zYwlaYWN1dGUuc2MJWmNhcm9uLnNjDVpkb3Rh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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//D/0v/2/97/+gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/8AAAAAA/8YAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/+j/6P/aAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/6n/2P/Y/6cAAAA7AAAAAAAAAAAAAAAAAAAAAAAA/8L/3QAA/9T/3f/C/+sAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP+6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP+6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/9gAZAAAAAAAAAAAAAAAAAAAAAAAA/9gAAAAAAAD/6AAA/+H/sAAZAAn/7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/9j/8QAA//IAAAAA//z/8v/JAAAAAAAPAA0AGAAAAAAAAP/4//YAAP/2AAAAAAAA//L/+v+i/9j/6P+w/8wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUABQADv/yABAABAAU/+b/zP/G//IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/+gAAP/8//IAAAAA//b/8gAA//0AAAAQAAYAAAAAAAD/8v/8AAAAAAAAAAD/8AAA//YAAP/iAAD/7AAA/+wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAQAEP/6AAr//AAAAAAAAAAA//IABv/2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/8gAA//z//P/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//wAAP/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/+7/8v/8//n/7AAA//b/8gAAAAAAAAAAAAAAAAAAAAD/6P/2/+MAAAAAAAD/9gAA//L/9gAAAAD/zAAOABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA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//b/3gAA//L/dgAA//b/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//UAAAAAAAAAAAAAAAAAAAAAAAD/2AAAAAD/7P/5/+z/7P/iAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/6cABgAGAA3/9v+2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//kAAAAAAAAAAAAAAAAAAAAAAAD/6QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//QAA//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//0AAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYADQANABwACQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAYADQAAABMAAAAXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYADQANABwACQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAYADQAAABMAAAAXAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/9gAA/+//7wAAAAAAAAAAAAAAAAAAAAAAAAAA//IAAP/s//YAAAAA/+8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/+8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//oADQAKAA0ABv/oAAAAAAAAAAAAAAAAAAD/2QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAMACQAAAA0AAAAGAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/94AAAAAAAAAAP/lAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/9gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/+z/6P/6/+//7//eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//cAAP/5AAAAAAAAAAD/+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/+gAAAAA//b/4gAAAAAAAAAA/4gABAAAAA0AAP+Q/87/9v+yAAD/1QAA/+j/bgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/0gAA/+f/7P/rAAD/9v/sAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/4n/8gAAAAD/3P+WAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//cAAAAAAAAAAAAAAAAAAAAAAAD/3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/9wAAAAAAAAAAP/oAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//AAAAAAAAAAAAAAAAAAAAAAAAD/9gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/9gAAAAD/6wAA//f/9wAA/8gAFAAKABQAAP+///L/8P/t//b/6gAA//H/t//9AAD/4gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/6AAAABAAAAAAAAAAAAAAAAAAAAAD//AAA/+3/6wAA/+z/9P/n/+3/+gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/8EAAAAAAAD/8P/EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/2//AAAAAAAAAAAAAAAAAAAAAAAAD/9gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/+z/9gAAAAAAAAAA//L/8P/5ABT/+QAGAA0ABgAAAAP/8gAA/+//9v/w//n/+wAA//D/9gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAYABgAAAAAAAAAAAAD//P/5AAAAEAAA/+X/8gAAAAAAAP/y//kABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/5//YAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/+cAAP/8/74AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/sAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/mAAD/5gAAAAAAAAAA//wAAP/yAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//L/8P/IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/8AAAAAAAA//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//D/vf/QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/9gAAP/v/9MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/vAAD/+QAAAAAAAAAAAAAAAP/sAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/9IAAP/2/8kAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/4v/uAAAAAAAAAAD/4gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/rAAD/8gAAAAAAAAAAAAAAAP/oAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/rAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP+N/8kAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/3wAAAAAAAAAAAAAAAAAAAAAAAP98/8YAAAAAAAD/3v/w/98AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/zwAAAAAAAAAAAAAAAAAA/+wAAAAA//kAAP/2AAAAAAAAAAAAAAAAAAAAAP/d//UAAP/8AAD/7AAA//z/2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//kAAAAAAAAAAP/oAAAAAAAAAAAAAAAA/98AAAAA//EAAAAAAAD/8gAAAAAAAAAAAAAAAAAAAAD//AAA//b/9gAA/+8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//L/6AAAAAAAAAAA/+wAAAAAAAAAAgAEAvYDEQAAAxwDMwAcAzUDNQA0A0ADQQA1AAIAHQAEADcAAABNAE4ANABoAGgANgB+AH4ANwCgAKIAOACoAKgAOwDMAM0APADlAOUAPgD7APsAPwEWARYAQAEsAS0AQQFRAVMAQwFZAVkARgF+AX8ARwGWAZoASQGfAZ8ATgGqAasATwG3AbcAUQHBAcIAUgHKAcoAVALmAuYAVQLwAvAAVgNbA3QAVwOKA4oAcQOnA6cAcgO+A74AcwPkA+QAdAPqA+oAdQQRBBIAdgABAAIDFgMXAAEACQAGABYAFwAgADAAMQNdA20DbgABAAUDEwMUAxUDGgMbAAIAEwAEABMAAAAVADcAEACiAKIAMwDNAM0ANADlAOUANQEtAS0ANgFTAVMANwF/AX8AOAGWAZYAOQGYAZoAOgGfAZ8APQGrAasAPgG3AbcAPwHCAcIAQAHKAcoAQQNbA2oAQgNsA3QAUgPkA+QAWwQSBBIAXAABAAEDEgABAAYAEgAYACwAMgNpA28AAQACAxgDGQABABQABAAIAAwAEgAYAB4AIgAmACwAMgEtAZkBnwGrA1sDXwNjA2kDbwPkAAEAAwL6AwIDBAABADYACQATABkAGwAzADUAcwC2AOQBZwHfAeAB4QHiAeMB5AHlAeYB5wHoAfMB9AH1AfYB9wH4AfkB+gH7AfwCAwIFAhgCIQIjAo8CkAKRApIDYANqA3ADcgQsBC0ELgQvBDAEMQQyBDMENAQ1BDYAAgAtAAQAIAAAACIAJQAdACgAKAAhACoAcgAiAHQAtQBrALcBAgCtAQYBIQD5AS0BLQEVAS8BMAEWATIBMgEYATkBlAEZAZYBlgF1AZgBmwF2AZ4ByQF6AcwBzAGmAeYB5gGnAfoB+gGoAf0CCwGpAg4CGAG4AhsCGwHDAh0CHQHEAh8CHwHFAiECIQHGAiMCIwHHAuAC4QHIAzoDPQHKAz8DPwHOA0IDSQHPA0sDSwHXA1sDXgHYA2ADYQHcA2QDZgHeA2kDigHhA4wDlgIDA6kDrwIOA8ADwwIVA8UDygIZA9MD4gIfA+oD+gIvA/wEEQJABBgEKAJWBCoEKgJnBC0ELQJoBDMEMwJpBDUENgJqAAIAwAAEAAQADAAFAAUADQAGAAYADwAHAAcAFgAIAAgAPAAJAAkAPQAKAAoAEQALAAsAQAAMAAwAQQANAA0AQwAOAA4AEgAPAA8AFAAQABEAQAASABIAFgATABMARwAUABQAFgAVABUAGAAWABYAGgAXABcAHAAYABgAHgAZABkASwAaABoAIAAbABsATQAcABwAIgAdAB0AJAAeAB4AJgAfAB8AMAAgACAAJwAiACIAKgAjACMAKwAkACQALAAlACUALwAoACgALQAqACsALwAsAC0AMAAuAC4ANgAvAC8AMwAwADAANAAxADEANQAyADIANgAzADMAVwA0ADQAOAA1ADUAWAA2ADYAOQA3ADcAOgA4AE0ADABOAE4APABPAFMADwBUAFcAFgBYAGgAPABpAG8AEQBwAHIAQAB0AH4AQQB/AH8AQwCAAIAAEgCBAIEAFACCAIIARQCDAIgAFACJAJAAQACRAKAAFgChAKEAPACiAKcAFwCoAKgAFgCpAK4AGACvALUAGgC3ALsAHAC8AMwAHgDNANIAHwDTANYAIADXAN4AIgDfAOIAJADjAOMAFgDkAOQASQDlAOUAFgDmAPsAJgD8APwAKgD9AQEAJwECAQIALgEGARYAKgEXAR0ALAEeASEALwEtAS0ANgEvATAALQEyATIALgE5AUEALwFCAVEAMAFSAVIAKgFTAVgAMQFZAVkAMAFaAV8AMwFgAWYANAFnAWcAUQFoAW0ANQFuAX4ANgF/AYQANwGFAYgAOAGJAZAAOQGRAZQAOgGWAZYAMAGYAZgANgGZAZkAMAGaAZoANgGbAZsAKwGeAZ4ANQGfAaoAQgGrAckANgHMAcwALgHmAeYACQH6AfoACAH9Af4AKQH/AgAAKAIBAgEAKQICAgIAAQIDAgMAAgIEAgQAVAIFAgUABwIGAgcAVQIIAggAMgIJAgkAVgIKAgoAMgILAgsAVgIOAg4AUgIP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ZG5vbQN0ZnJhYwN6ZnJhYwOEZnJhYwOOZnJhYwOYZnJhYwOibGlnYQOsbGlnYQOybGlnYQO4bGlnYQO+bGlnYQPEbG9jbAPKbG9jbAPQbG9jbAPWbnVtcgPcbnVtcgPibnVtcgPobnVtcgPubnVtcgP0b251bQP6b251bQQAb251bQQGb251bQQMb251bQQSb3JkbgQYb3JkbgQeb3JkbgQkb3JkbgQqb3JkbgQwcG51bQQ2cG51bQQ8cG51bQRCcG51bQRIcG51bQROc2FsdARUc2FsdARgc2FsdARsc2FsdAR4c2FsdASEc2luZgSQc2luZgSWc2luZgScc2luZgSic2luZgSoc21jcASuc21jcAS2c21jcAS+c21jcATGc21jcATOc3MwMQTWc3MwMQTcc3MwMQTic3MwMQToc3MwMQTuc3MwMgT0c3MwMgT6c3MwMgUAc3MwMgUGc3MwMgUMc3MwMwUSc3MwMwUYc3MwMwUec3MwMwUkc3MwMwUqc3MwNAUwc3MwNAU2c3MwNAU8c3MwNAVCc3MwNAVIc3MwNQVOc3MwNQVUc3MwNQVac3MwNQVgc3MwNQVmc3VicwVsc3VicwVyc3VicwV4c3VicwV+c3VicwWEc3VwcwWKc3VwcwWWc3VwcwWic3VwcwWuc3VwcwW6emVybwXGemVybwXMemVybwXSemVybwXYemVybwXeAAAAAgAAAAEAAAACAAAAAQAAAAIAAAABAAAAAgAAAAEAAAACAAAAAQAAAAIACQAKAAAAAgAJAAoAAAACAAkACgAAAAIACQAKAAAAAgAJAAoAAAABABkAAAABABkAAAABABkAAAABABkAAAABABkAAAAFAAQABQAGAAcACAAAAAUABAAFAAYABwAIAAAABQAEAAUABgAHAAgAAAAFAAQABQAGAAcACAAAAAUABAAFAAYABwAIAAAAAQANAAAAAQANAAAAAQANAAAAAQANAAAAAQANAAAAAwAMAA4ADwAAAAMADAAOAA8AAAADAAwADgAPAAAAAwAMAA4ADwAAAAMADAAOAA8AAAABAB4AAAABAB4AAAABAB4AAAABAB4AAAABAB4AAAABAAIAAAABAAIAAAABAAIAAAABAAwAAAABAAwAAAABAAwAAAABAAwAAAABAAwAAAABABYAAAABABYAAAABABYAAAABABYAAAAB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A34DfwOAA4EDggODA4QDhQOGA4cDiAOJA4oDiwOOA48DkAORA5IDkwOUA5UDlgOXA5gDmQOaA5sDnAOdA54DnwOgA6EDogOjA6QDpQOmA6cDqQOqA6sDrAOtA64DrwOwA7EDsgOzA8ADwQPDA8QDxQPGA8cDyAPJA8oDywPMA80DzgPPA9AD0QPSA9MD1APVA9YD1wPYA9kD2gPbA9wD3QPeA98D4APhA+ID4wPkA+UD5gPnA+gD6QPqA+0D7gPvA/AD8QPyA/MD9AP1A/YD9wP4A/kD+wP8A/0D/gP/BAAEAQQCBAMEBAQFBAYEBwQIBAkECgQLBAwEDQQOBA8EEAQRBBIEEwQUBBUEFgQXBBgEGQQaBBsEHAQdBB4EHwQgBCEEIgQjBCQEJQQmBCcEKAQpBCoDiwOOA48DkAORA5IDkwOUA5UDlgOZA5oDmwOcA50DngOfA6ADoQOiA6MDpAOlA6YDpwOwA7EDsgOzA7QDtQO2A7cDuAO5A7sDvAO9A74DvgPAA8EDywPMA80DzgPPA9AD0QPSA9MD1APVA9YD1wPYA9kD2gPbA9wD3QPeA98D4APhA+ID4wPkA+UD5gPnA+gD6QPqA+0D7wPuA/AD8QPyA/MD9AP1A/YD9wP4A/kD+wP8A/0D/gP/BAAEAQQCBAMEBAQFBAYEBwQIBAkECgQLBAwEDQQOBA8EEAQRBBIEEwQUBBUEFgQXBBgEGQQaBBsEHAQdBB4EHwQgBCEEIgQjBCQEJQQmBCcEKAQpBCsB8wH0AfUB9gH3AfgB+QH6AfsB/AHzAfQB9QH2AfcB+AH5AfoB+wH8BFQCMAJrAooCiwKMAvcC+QL7Av0C/wMBAwMDBQMHAwkDCwMNAw8DFwMZAx0DHwMhAyMDJQMnAykDKwMtAy8DMQMzA4wDvwPrA4wDvwPrA0EDjQONA8IDwgOoA6gD7APsA7oAAQhiAHgA9gD8AQIBCAEOARQBGgEgASYBLgE0AToBQAFGAUwBUgFYAV4BZAFqAXABdgF8AYIBiAGOAZQBnAGiAagBrgG0AboBwgHIAdAB1gHcAeQB6gHwAfYB/AICAggCDgIUAhoCIAImAiwCMgI4Aj4CRAJKAlACVgJcAmICaAJuAnQCegKAAoYCjAKSApgCngKkAqoCsAK2ArwCwgLIAs4C1ALaAuAC5gLsAvIC+AL+AwQDCgMQAxYDHAMiAygDLgM0AzoDQANGA0wDUgNYA14DZANqA3oDigOaA6oDugPKA9oD6gP6BAoEFAQeBCQEKgQwBDoAAgNbBDoAAgNcBDsAAgNdBDwAAgNeBD0AAgNfBD4AAgNgBD8AAgNhBEAAAgNiBEEAAwNjBEIBnwACA2QEQwACA2UERAACA2YERQACA2cERgACA2gERwACA2kESAACA2oESQACA2sESgACA2wESwACA20ETAACA24ETQACA28ETgACA3AETwACA3EEUAACA3IEUQACA3MEUgACA3QEUwADA1sCbQGrAAIDXAJuAAIDXQJvAAIDXgJwAAIDXwJxAAIDYAJyAAMDYQJzAcIAAgNiAnQAAwNaA2MCdQACA2QCdgACA2UCdwADA2YCeAHKAAIDZwJ5AAIDaAJ6AAIDaQJ7AAIDagJ8AAIDawJ9AAIDbAJ+AAIDbQJ/AAIDbgKAAAIDbwKBAAIDcAKCAAIDcQKDAAIDcgKEAAIDcwKFAAIDdAKGAAIDtAGgAAIDtQGhAAIDtgGiAAIDtwGjAAIDuAGkAAIDuQGlAAIDugGmAAIDuwGnAAIDvAGoAAIDvQGpAAIDvgGqAAIDdQGsAAIDdgGtAAIDdwGuAAIDeAGvAAIDeQGwAAIDegGxAAIDewGyAAIDfAGzAAIDfQG0AAIDfgG1AAIDfwG2AAIDgAG3AAIDgQG4AAIDggG5AAIDgwG6AAIDhAG7AAIDhQG8AAIDhgG9AAIDhwG+AAIDiAG/AAIDiQHAAAIDigHBAAIDlwKHAAIDmAKIAAIDqQHDAAIDqgHEAAIDqwHFAAIDrAHGAAIDrQHHAAIDrgHIAAIDrwHJAAIDwwHLAAIDxAHMAAIDxgHNAAIDxQHOAAIDxwHPAAIDyAHQAAIDyQHRAAIDygHSAAIEKgKJAAcELAJcAk4CMgJAAd8B6QAHBC0CXQJPAjMCQQHgAeoABwQuAl4CUAI0AkIB4QHrAAcELwJfAlECNQJDAeIB7AAHBDACYAJSAjYCRAHjAe0ABwQxAmECUwI3AkUB5AHuAAcEMgJiAlQCOAJGAeUB7wAHBDMCYwJVAjkCRwHmAfAABwQ0AmQCVgI6AkgB5wHxAAcENQJlAlcCOwJJAegB8gAEAmgCWgI+AkwABAJpAlsCPwJNAAIENgRVAAIENwRWAAIEOARXAAQCZgJYAjwCSgAEAmcCWQI9AksAAQByAAEACAABAAQBLAACAxgAAgRYAC0DOAEsAk4CTwJQAlECUgJTAlQCVQJWAlcCWAJZAloCWwL3AvkC+wL9Av8DAQMDAwUDBwMJAwsDDQMPAxcDGQMdAx8DIQMjAyUDJwMpAysDLQMvAzEDMwM5A0EAAQABACYAAQAIAFoAXQCTAJYBCAELAUQBRwABAAQAWgCTAQgBRAABAAEDAAABAAQAXQCWAQsBRwABAAEC+AABAAEDGAABAAEBKwABAAMC+gMAAwQAAQAQAAQACAAKAAwAEgAYAB4AIQAiACQAJgApACwAMQAyAcIAAgAHAAQAHQAAADgA5QAaAzoDPADIA0IDQgDLA0QDRADMA0YDRgDNA0gDSADOAAEAHAL2AvgC+gL8Av4DAAMCAwQDBgMIAwoDDAMOAxYDGAMcAx4DIAMiAyQDJgMoAyoDLAMuAzADMgNAAAIAAwHUAd4AAAISAhIACwIUAhUADAACAA0AHgA3AAAA5gEsABoBLgEvAGEBMQFAAGMBQgFsAHMBbgGWAJ4BmQGZAMcDPQM/AMgDQwNDAMsDRQNFAMwDRwNHAM0DSQNJAM4DWgNaAM8AAgADAdUB3gAAAf0B/gAKAhsCHAAMAAEAAQIhAAIAAQJcAmUAAAABAAIAAwM2AAIAAgJOAlsAAAKfAqEADgACAAECXAJpAAAAAgABAk4CVwAAAAEAAgM4AzkAAgADAB4ANwAAAQYBBwAaAZkBmQAcAAIAAQAEAB0AAAABAAQB/wISAhQCFQACAAIB1QHeAAAB6QHyAAoAAgABAdUB6AAAAAEAAgHVAd8AAQAdAi8C9gL4AvoC/AL+AwADAgMEAwYDCAMKAwwDDgMWAxgDHAMeAyADIgMkAyYDKAMqAywDLgMwAzIDQAACAAMAKQApAAABMQE4AAECeAJ4AAkAAgAEAB4AHgAAAOYA+wABAmoCagAXAm0CbQAYAAIAAwAkACQAAAEXAR0AAQJzAnMACAACAAIADAAMAAAAdAB+AAEAAQABACMAAgAvADgAcwAAAH8A5QA8APwBBQCjAQgBFgCtAR4BLAC8AS4BLwDLATkBQADNAUIBbADVAW4BlgEAAdQB1AEpAd8B8gEqAf8B/wE+Ai8CLwE/AmoCagFAAm0CbQFBAnMCcwFCAngCeAFDAvYC9gFEAvgC+AFFAvoC+gFGAvwC/AFHAv4C/gFIAwADAAFJAwIDAgFKAwQDBAFLAwYDBgFMAwgDCAFNAwoDCgFOAwwDDAFPAw4DDgFQAxYDFgFRAxgDGAFSAxwDHAFTAx4DHgFUAyADIAFVAyIDIgFWAyQDJAFXAyYDJgFYAygDKAFZAyoDKgFaAywDLAFbAy4DLgFcAzADMAFdAzIDMgFeAzoDQAFfA0IDSQFmA1oDWgFuAAIADAAEADcAAAB0AH4ANADmAPsAPwEGAQcAVQEXAR0AVwExATgAXgGZAZkAZgHVAd4AZwH9Af4AcQISAhIAcwIUAhUAdAIbAhwAdgABAC0AAwErAlwCXQJeAl8CYAJhAmICYwJkAmUCZgJnAmgCaQL2AvgC+gL8Av4DAAMCAwQDBgMIAwoDDAMOAxYDGAMcAx4DIAMiAyQDJgMoAyoDLAMuAzADMgM2A0AAAQAAAAgAAAAEAA4AAmlkZW9yb21uAAJERkxUAA5sYXRuAA4ABgAAAAAAAQACAAgADAAB/1YAAQAAAAAAAAABAAEAAQAAAAEAACBEAAAAFAAAAAAAACA8MIIgOAYJKoZIhvcNAQcCoIIgKTCCICUCAQExCzAJBgUrDgMCGgUAMGEGCisGAQQBgjcCAQSgUzBRMCwGCisGAQQBgjcCARyiHoAcADwAPAA8AE8AYgBzAG8AbABlAHQAZQA+AD4APjAhMAkGBSsOAwIaBQAEFJ43+TOOmiMAorzcnAs0uMjGG2InoIIbDzCCAjwwggGlAhBwuuQdENkpNLY4ynsDzLq/MA0GCSqGSIb3DQEBAgUAMF8xCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05NjAxMjkwMDAwMDBaFw0yODA4MDEyMzU5NTlaMF8xCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE3MDUGA1UECxMuQ2xhc3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAyVxZnvIbigEUtBDfBEDb41evakVAj4QMC9Ez2dkRz+4CWB8l9yqoRAWq7AMfeH+ek7maAKojfdashaJjRcdyJ8z0TMZ1cdI5709C8HXfCpDGjiBvmA/4rCNfcCk2pMmG57GaIMtTpYXnPb59mv4kRTPcdhXtD6JxZExlLoFoRacCAwEAATANBgkqhkiG9w0BAQIFAAOBgQC7TBIrzywmAE8UE92m+/wKEYSM8ygcZ5IvfLbF+t/w6JW8HY9sLKhRzHPYpMBT8E7WJsB2AVeBkl4h8dGx/+fQIVjNaRfjRBycGUQ5iVzcnAAPVo0Cme2ikEVM5LsQpD3wMgMO8c746MlRjOZin+afwH23cpzJNjprn06o/2QNZDCCA+4wggNXoAMCAQICEH6T6/t8xk5Z6kuad9QG/DswDQYJKoZIhvcNAQEFBQAwgYsxCzAJBgNVBAYTAlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxFDASBgNVBAcTC0R1cmJhbnZpbGxlMQ8wDQYDVQQKEwZUaGF3dGUxHTAbBgNVBAsTFFRoYXd0ZSBDZXJ0aWZpY2F0aW9uMR8wHQYDVQQDExZUaGF3dGUgVGltZXN0YW1waW5nIENBMB4XDTEyMTIyMTAwMDAwMFoXDTIwMTIzMDIzNTk1OVowXjELMAkGA1UEBhMCVVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMTAwLgYDVQQDEydTeW1hbnRlYyBUaW1lIFN0YW1waW5nIFNlcnZpY2VzIENBIC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCxrLNJVEuXHBIK2CV5kSJXKm/cuCbEQ3Nrwr8uUFr7FMJ2jkMBJUO0oeJF9Oi3e8N0zCLXtJQAAvdN7b+0t0Qka81fRTvRRM5DEnMXgotptCvLmR6schsmTXEfsTHd+1FhAlOmqvVJLAV4RaUvic7nmef+jOJXPz3GktxK+Hsz5HkK+/B1iEGc/8UDUZmq12yfk2mHZSmDhcJgFMTIyTsU2sCB8B8NdN6SIqvK9/t0fCfm90obf6fDni2uiuqm5qonFn1h95hxEbziUKFL5V365Q6nLJ+qZSDT2JboyHylTkhE/xniRAeSC9dohIBdanhkRc1gRn5UwRN8xXnxycFxAgMBAAGjgfowgfcwHQYDVR0OBBYEFF+a9W5czMx0mtTdfe8/2+xMgC7dMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcwAYYWaHR0cDovL29jc3AudGhhd3RlLmNvbTASBgNVHRMBAf8ECDAGAQH/AgEAMD8GA1UdHwQ4MDYwNKAyoDCGLmh0dHA6Ly9jcmwudGhhd3RlLmNvbS9UaGF3dGVUaW1lc3RhbXBpbmdDQS5jcmwwEwYDVR0lBAwwCgYIKwYBBQUHAwgwDgYDVR0PAQH/BAQDAgEGMCgGA1UdEQQhMB+kHTAbMRkwFwYDVQQDExBUaW1lU3RhbXAtMjA0OC0xMA0GCSqGSIb3DQEBBQUAA4GBAAMJm495739ZMKrvaLX64wkdu0+CBl03X6ZSnxaN6hySCURu9W3rWHww6PlpjSNzCxJvR6muORH4KrGbsBrDjutZlgCtzgxNstAxpghcKnr84nodV0yoZRjpeUBiJZZux8c3aoMhCI5B6t3ZVz8dd0mHKhYGXqY4aiISo1EZg362MIIEkDCCA/mgAwIBAgIQGwk7eGCW2je7pFGURsiWeDANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsTLkNsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYxMTA4MDAwMDAwWhcNMjExMTA3MjM1OTU5WjCByjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbext0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIzSdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQGBO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/NIeWiu5T6CUVAgMBAAGjggFbMIIBVzAPBgNVHRMBAf8EBTADAQH/MDEGA1UdHwQqMCgwJqAkoCKGIGh0dHA6Ly9jcmwudmVyaXNpZ24uY29tL3BjYTMuY3JsMA4GA1UdDwEB/wQEAwIBBjA9BgNVHSAENjA0MDIGBFUdIAAwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL2NwczAdBgNVHQ4EFgQUf9Nlp8Ld7LvwMAnzQzn6Aq8zMTMwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24uY29tL3ZzbG9nby5naWYwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC52ZXJpc2lnbi5jb20wDQYJKoZIhvcNAQEFBQADgYEAo819HvfHdY1I51Y0TACQdalRpVbBbbz+9VMi6ZiirJp+cB6zjjtF44aVMdptTPs0UICWzSTyQN8EP+JlzjQiYRXqZnBk0vFu88oYWWpBRn6C3hmwcDFWaQ0M5h2dcVjczN5i9eF6EALYetw7+le9yemPRiE5n1FlTI46vihBcB0wggSjMIIDi6ADAgECAhAOz/Q4yP6/NW4E2GqYGxpQMA0GCSqGSIb3DQEBBQUAMF4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjEwMC4GA1UEAxMnU3ltYW50ZWMgVGltZSBTdGFtcGluZyBTZXJ2aWNlcyBDQSAtIEcyMB4XDTEyMTAxODAwMDAwMFoXDTIwMTIyOTIzNTk1OVowYjELMAkGA1UEBhMCVVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMTQwMgYDVQQDEytTeW1hbnRlYyBUaW1lIFN0YW1waW5nIFNlcnZpY2VzIFNpZ25lciAtIEc0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAomMLOUS4uyOnREm7Dv+h8GEKU5OwmNutLA9KxW7/hjxTVQ8VzgQ/K/2plpbZvmF5C1vJTIZ25eBDSyKV7sIrQ8Gf2Gi0jkBP7oU4uRHFI/JkWPAVMm9OV6GuiKQC1yoezUvh3WPVF4kyW7BemVqonShQDhfultthO0VRHc8SVguSR/yrrvZmPUescHLnkudfzRC5xINklBm9JYDh6NIipdC6Anqhd5NbZcPuF3S8QYYq3AhMjJKMkS2ed0QfaNaodHfbDlsyi1aLM73ZY8hJnTrFxeozC9Lxoxv0i77Zs1eLO94Ep3oisiSuLsdwxb5OgyYI+wu9qU+ZCOEQKHKqzQIDAQABo4IBVzCCAVMwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDAOBgNVHQ8BAf8EBAMCB4AwcwYIKwYBBQUHAQEEZzBlMCoGCCsGAQUFBzABhh5odHRwOi8vdHMtb2NzcC53cy5zeW1hbnRlYy5jb20wNwYIKwYBBQUHMAKGK2h0dHA6Ly90cy1haWEud3Muc3ltYW50ZWMuY29tL3Rzcy1jYS1nMi5jZXIwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL3RzLWNybC53cy5zeW1hbnRlYy5jb20vdHNzLWNhLWcyLmNybDAoBgNVHREEITAfpB0wGzEZMBcGA1UEAxMQVGltZVN0YW1wLTIwNDgtMjAdBgNVHQ4EFgQURsZpow5KFB7VTNpSYxc/Xja8DeYwHwYDVR0jBBgwFoAUX5r1blzMzHSa1N197z/b7EyALt0wDQYJKoZIhvcNAQEFBQADggEBAHg7tJEqAEzwj2IwN3ijhCcHbxiy3iXcoNSUA6qGTiWfmkADHN3O43nLIWgG2rYytG2/9CwmYzPkSWRtDebDZw73BaQ1bHyJFsbpst+y6d0gxnEPzZV03LZc3r03H0N45ni1zSgEIKOq8UvEiCmRDoDREfzdXHZuT14ORUZBbg2w6jiasTraCXEQ/Bx5tIB7rGn0/Zy2DBYr8X9bCT2bW+IWyhOBbQAuOA2oKY8s4bL0WqkBrxWcLC9JG9siu8P+eJRRw4axgohd8D20UaF5Mysue7ncIAkTcetqGVvP6KUwVyyJST+5z3/Jvz4iaGNTmr1pdKzFHTx/kuDDvBzYBHUwggWQMIIEeKADAgECAhB0JVOtB+Sv0RUEr5hNSe1oMA0GCSqGSIb3DQEBBQUAMIG0MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMS4wLAYDVQQDEyVWZXJpU2lnbiBDbGFzcyAzIENvZGUgU2lnbmluZyAyMDEwIENBMB4XDTEyMDkxODAwMDAwMFoXDTEzMDkxODIzNTk1OVowgdMxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMREwDwYDVQQHEwhTYW4gSm9zZTEjMCEGA1UEChQaQWRvYmUgU3lzdGVtcyBJbmNvcnBvcmF0ZWQxEjAQBgNVBAsUCVR5cGUgRm9udDE+MDwGA1UECxM1RGlnaXRhbCBJRCBDbGFzcyAzIC0gTWljcm9zb2Z0IFNvZnR3YXJlIFZhbGlkYXRpb24gdjIxIzAhBgNVBAMUGkFkb2JlIFN5c3RlbXMgSW5jb3Jwb3JhdGVkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt8IRU10oomHTBNRxvjw5PlrAHhy67eKUw8c4g8HrLWsPSriKJ/8XFQXK3upLoXeSZA5P9vLT9ga+mZWzYxrGsq3hpgtw59Y1UsIhipYyLA1iitYf15PnEnH1DNGucWBVdFLQruJVlQ/gD1zpN6YIS1yR/9SSuhXkYoxqc91Qq6hWnkpecr8TzenA05KbjLlrCrknT7hRm14WaR3T7mfVKPfkDI/rfNhayHhr9XbqMkPfcj+acmmNAFTSCfue2unC4KlD1JJ0SrfEAY/jMEutsUBYV2DWj4Pzi+vAvdVDT2URP3IVF16t2v9xBbIpnpwNeIjn7UuckqTNoRr9jwierQIDAQABo4IBezCCAXcwCQYDVR0TBAIwADAOBgNVHQ8BAf8EBAMCB4AwQAYDVR0fBDkwNzA1oDOgMYYvaHR0cDovL2NzYzMtMjAxMC1jcmwudmVyaXNpZ24uY29tL0NTQzMtMjAxMC5jcmwwRAYDVR0gBD0wOzA5BgtghkgBhvhFAQcXAzAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy52ZXJpc2lnbi5jb20vY3BzMBMGA1UdJQQMMAoGCCsGAQUFBwMDMHEGCCsGAQUFBwEBBGUwYzAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AudmVyaXNpZ24uY29tMDsGCCsGAQUFBzAChi9odHRwOi8vY3NjMy0yMDEwLWFpYS52ZXJpc2lnbi5jb20vQ1NDMy0yMDEwLmNlcjAfBgNVHSMEGDAWgBTPmanqeyb0S8mOj9fwBSbv49KnnTARBglghkgBhvhCAQEEBAMCBBAwFgYKKwYBBAGCNwIBGwQIMAYBAQABAf8wDQYJKoZIhvcNAQEFBQADggEBAKpoYb2v3VICxI5BpX1viJ6+/rnLt2vtwjhlG2IxRNubrTkzv4WU/2wA+bqUlKCbW+dPHy0DWeDjot1j1rzlK3QBey2kAHQ2216SmZv4exe5v904TOYshPpOKtoQmdX0jZWBM+1kD5tIRCI0XwdjcdtozNFR/zjf2ugOs8HqJa8IswydyjCTygx+3TuA2COiCtUWJdwM2tvdMgO1mx/60VL52ZoqED6MsZcbQS6pHwEvb0kJ3Gy3K85/2C/czH32aR7flB3JxXal4vc0K3bT9C4+FOLqakHy3+1/Di/c7q72BWwKQEDxTyGKg4Okto4HZxVz1AZg3MTaGYtLKDW2weEwggYKMIIE8qADAgECAhBSAOWqJVb8GobtlsnUSzPHMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA2IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHNTAeFw0xMDAyMDgwMDAwMDBaFw0yMDAyMDcyMzU5NTlaMIG0MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMS4wLAYDVQQDEyVWZXJpU2lnbiBDbGFzcyAzIENvZGUgU2lnbmluZyAyMDEwIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA9SNLXqXXirsy6dRX9+/kxyZ+rRmY/qidfZT2NmsQ13WBMH8EaH/LK3UezR0IjN9plKc3o5x7gOCZ4e43TV/OOxTuhtTQ9Sc1vCULOKeMY50Xowilq7D7zWpigkzVIdob2fHjhDuKKk+FW5ABT8mndhB/JwN8vq5+fcHd+QW8G0icaefApDw8QQA+35blxeSUcdZVAccAJkpAPLWhJqkMp22AjpAle8+/PxzrL5b65Yd3xrVWsno7VDBTG99iNP8e0fRakyiF5UwXTn5b/aSTmX/fze+kde/vFfZH5/gZctguNBqmtKdMfr27Tww9V/Ew1qY2jtaAdtcZLqXNfjQtiQIDAQABo4IB/jCCAfowEgYDVR0TAQH/BAgwBgEB/wIBADBwBgNVHSAEaTBnMGUGC2CGSAGG+EUBBxcDMFYwKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LnZlcmlzaWduLmNvbS9jcHMwKgYIKwYBBQUHAgIwHhocaHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL3JwYTAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24uY29tL3ZzbG9nby5naWYwNAYDVR0fBC0wKzApoCegJYYjaHR0cDovL2NybC52ZXJpc2lnbi5jb20vcGNhMy1nNS5jcmwwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC52ZXJpc2lnbi5jb20wHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMDMCgGA1UdEQQhMB+kHTAbMRkwFwYDVQQDExBWZXJpU2lnbk1QS0ktMi04MB0GA1UdDgQWBBTPmanqeyb0S8mOj9fwBSbv49KnnTAfBgNVHSMEGDAWgBR/02Wnwt3su/AwCfNDOfoCrzMxMzANBgkqhkiG9w0BAQUFAAOCAQEAViLmNKTEYctIuQGtVqhkD9mMkcS7zAzlrXqgIn/fRzhKLWzRf3EafOxwqbHwT+QPDFP6FV7+dJhJJIWBJhyRFEewTGOMu6E01MZF6A2FJnMD0KmMZG3ccZLmRQVgFVlROfxYFGv+1KTteWsIDEFy5zciBgm+I+k/RJoe6WGdzLGQXPw90o2sQj1lNtS0PUAoj5sQzyMmzEsgy5AfXYxMNMo82OU31m+lIL006ybZrg3nxZr3obQhkTNvhuhYuyV8dA5Y/nUbYz/OMXybjxuWnsVTdoRbnK2R+qztk7pdyCFTwoJTY68SDVCHERs9VFKWiiycPZIaCJoFLseTpUiR0zGCBJswggSXAgEBMIHJMIG0MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOzA5BgNVBAsTMlRlcm1zIG9mIHVzZSBhdCBodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhIChjKTEwMS4wLAYDVQQDEyVWZXJpU2lnbiBDbGFzcyAzIENvZGUgU2lnbmluZyAyMDEwIENBAhB0JVOtB+Sv0RUEr5hNSe1oMAkGBSsOAwIaBQCggZgwFAYJKwYBBAGCNygBMQcDBQADAAAAMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMCIGCisGAQQBgjcCAQwxFDASoRCADnd3dy5hZG9iZS5jb20gMCMGCSqGSIb3DQEJBDEWBBTvGig28BPjpz/5DMwo5R/6QWWoHzANBgkqhkiG9w0BAQEFAASCAQBclPyg7Y7ihnGm47HuuHFfgeUCCBYcV9OOxJfaligA9HTRYH8MLm971ytOEUzS938WBxgN563PQ3oYANuHyTZBpy/JfOuACHiJhWc+MdF2pG7gPFcrKAlZnRg2KOBJ7WMM+p/HeQV3e3X29BUpKuU2D3aOWHqMINtkQPpunRxLSGHnjXi2oUIHLON8j4LlUz475KhA9YD4XD/KilRqwDppwYCtEqcIAVB7XBEulO7F6eY+nn0zCMmSKCxzP0VruwmJgaPIpIbI1xw+mXVoe8mMDRxa+lbJhjk5E9kbB9L4ExPmMVTQI2NqQ8wzAuLkjMv/fMU+X18ll+E2UcRPQlLGoYICCzCCAgcGCSqGSIb3DQEJBjGCAfgwggH0AgEBMHIwXjELMAkGA1UEBhMCVVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMTAwLgYDVQQDEydTeW1hbnRlYyBUaW1lIFN0YW1waW5nIFNlcnZpY2VzIENBIC0gRzICEA7P9DjI/r81bgTYapgbGlAwCQYFKw4DAhoFAKBdMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTEzMDQyMDIzMTIzNVowIwYJKoZIhvcNAQkEMRYEFLwfFBXARXuxs31gdAsIIYn7lAkNMA0GCSqGSIb3DQEBAQUABIIBABvwJG0/bpEqzUa9Ne9YNBNxVez+jD9yFrxctpk/p2Nv1w2tbDMFFP5+Lqg6a/wrsnEC80fiqq8Ex6e8dcPub8CRNRfHGnz1oeAQT+nAJ0/PTvI/ME8CfXOG0HMoHEiUpiHg6j6/quMZZBC/11x9bETJSpiyTt71hoH2sdWVFbHT516amX7nckJb8tMfAXdBL99tR3ViJsQAjvVLqqdzSc1BReSasJoKgTYVpzioXZIu/FHOte/qkQq+LfmUNhyoL5cqQWX5ZqFsyIf3VgSGaC7eOn1ZmESOYghf6LkivnnmL8646CfatOiHFDlmbMpeO5nfJBNn5nt3Wbz8zAQpSoc=';\n\n// fonts.js<test_widget> ends here\n"
  },
  {
    "path": "src/app/test_widget/test_results.js",
    "content": "/*global components */\n\n/**\n * @fileOverview This file registers the `test-results` component. This component is the main container and contains procedures for creating new `suites`. {@link test-results.js}, {@link test-widget.js}, {@link test-suite.js} should have executed already.\n * @name test_results.js<test_widget>\n * @author Etienne Prud’homme\n * @license MIT\n */\n\n/**\n * Main test container module.\n * @returns {Object} Method to build a new `suite` of tests.\n */\nvar testResults = (function() {\n  'use strict';\n  var exports = {};\n  var proto = {};\n\n  var template = '<!-- test-results component starts here -->' +\n        '<div class=\"test-results\">' +\n        '  <div class=\"upper-display\">' +\n        '    <em class=\"placeholder\">No tests loaded</em>' +\n        '    <button class=\"toggle-display shown\" disabled> Test Results</button>' +\n        '  </div>' +\n        '  <div class=\"test-suites\"></div>' +\n        '</div>' +\n        '<!-- test-results component ends here -->';\n\n  var buildSuiteElement = function() {};\n\n  proto.attachedCallback = function() {\n    var self = this;\n    // console.log(self);\n    var testSuites = self.querySelector('.test-suites');\n\n    var hideShowButton = self.querySelector('button.toggle-display');\n    var placeholder = self.querySelector('em.placeholder');\n\n    /**\n     * Builds a new suite of tests.\n     * @param {suite} newSuite - The suite to build\n     * @returns {HTMLElement} The newly created suite.\n     */\n    buildSuiteElement = function (newSuite) {\n      // toggle button and placeholder views\n      if (hideShowButton.disabled === true) {\n        hideShowButton.removeAttribute('disabled');\n      }\n      placeholder.textContent = '';\n\n      // actually create the suite\n      var _testSuiteFragment = components.createElement('test-suite');\n      var _testSuite = '';\n\n      // Take the first Node (not a comment)\n      for(var i=0, len=_testSuiteFragment.childNodes.length; i<len; i++) {\n        if(_testSuiteFragment.childNodes[i].nodeType !== 8) {\n          _testSuite = _testSuiteFragment.childNodes[i];\n          break;\n        }\n      }\n\n      _testSuite.dataset.name = newSuite.name;\n      _testSuite.dataset.suitePassed = false;\n      _testSuite.code = newSuite.code;  // to avoid leaving the code as an easy-to-spot attribute\n      _testSuite.suite = newSuite;\n\n      testSuites.appendChild(_testSuiteFragment);\n\n      return _testSuite;\n    };\n    exports.buildSuiteElement = buildSuiteElement;\n\n    /**\n     * Toggle visibility of tests\n     */\n    hideShowButton.onclick = function () {\n      testSuites.classList.toggle('hide');\n\n      this.classList.toggle('shown');\n      this.classList.toggle('hidden');\n\n      placeholder.classList.toggle('hide');\n\n      if (this.classList.contains('hidden')) {\n        placeholder.textContent = 'Tests hidden';\n      } else {\n        placeholder.textContent = '';\n      }\n    };\n  };\n\n  components.registerElement('test-results', template, proto);\n\n  // exports.buildSuiteElement(newSuite)\n  return exports;\n})();\n\n// test-results.js<test_widget> ends here\n"
  },
  {
    "path": "src/app/test_widget/test_suite.js",
    "content": "/*global components */\n\n/**\n * @fileOverview This file registers the `test-suite` component. {@link test-results} and {@link test-widget} should have executed already.\n * @name test_suite.js<test_widget>\n * @author Etienne Prud’homme\n * @license MIT\n */\n\n/**\n * Registers the `test-suite` component.\n */\n(function() {\n  'use strict';\n  var self = null;\n  var proto = {};\n\n  var template = '<!-- test-suite component ends here -->' +\n        '<div class=\"suite\">' +\n        '  <div class=\"suite-title\"></div>' +\n        '  <div class=\"active-tests\"></div>' +\n        '  <div class=\"suite-code-container\"><span class=\"suite-name\"></span> Code:<br><span class=\"suite-code\"></span></div>' +\n        '</div>' +\n        '<!-- test-suite component ends here -->';\n\n  function updateView() {\n    var suiteName = self.dataset.name;\n    var suitePassed = self.dataset.suitePassed;\n    var suiteCode = self.code;\n    var numberOfTests = self.dataset.numberOfTests;\n\n    // Is it ever used?\n    var suite = self;\n    var codeContainer = {\n      container: self.getElementsByClassName('suite-code-container')[0],\n      suiteName: self.getElementsByClassName('suite-name')[0],\n      suiteCode: self.getElementsByClassName('suite-code')[0]\n    };\n\n    var titleEnd = numberOfTests > 1 ? ' Tests' : ' Test';\n\n    self.querySelector('.suite-title').textContent = suiteName + titleEnd;\n\n    // Redefinition at each update?\n    /**\n     * Displays the secret code.\n     * @param {boolean} show - Whether the code should be shown.\n     */\n    function displayCode (show) {\n      if (show) {\n        codeContainer.container.style.display = 'block';\n        codeContainer.suiteName.textContent = suiteName;\n        codeContainer.suiteCode.textContent = suiteCode;\n      } else {\n        codeContainer.container.style.display = 'none';\n        codeContainer.suiteName.textContent = '';\n        codeContainer.suiteCode.textContent = '';\n      }\n    }\n\n    if (suitePassed === 'true') {\n      displayCode(true);\n    } else {\n      displayCode(false);\n    }\n  }\n\n  /**\n   * Called when the component is attached to the DOM.\n   */\n  proto.attachedCallback = function() {\n    var suite = this.suite;     // Is it ever used?\n    self = this;\n    updateView();\n  };\n\n\n  /**\n   * Called when the main container changed its attributes.\n   */\n  proto.attributeChangedCallback = function() {\n    self = this;\n    updateView();\n  };\n\n  components.registerElement('test-suite', template, proto);\n})();\n\n// test_suite.js<test_widget> ends here\n"
  },
  {
    "path": "src/app/test_widget/test_widget.js",
    "content": "/*global MutationObserver, components, sourceSansProFont */\n\n/**\n * @fileOverview This file provides the test widget module. It injects an iFrame inside the current document to display a list of tests.\n * @name test_widget.js<test_widget>\n * @author Etienne Prud’homme\n * @license MIT\n */\n\n/**\n * Module to handle the test widget.\n * @returns {Object} Methods to build the widget ({@link buildWidget}) and kill it ({@link killWidget}).\n * @throws {Error} Initialization errors.\n */\nvar testWidget = (function() {\n  'use strict';\n\n  var exports = {};\n  var frameId = null;\n  var frameElement = null;\n  var lastFrameHeight = 0;\n  var lastWindowHeight = null;\n\n  // TODO: Should we use a link element instead?\n  var outerStyles = '/* The iFrame class. Note that an iFrame acts like a normal element */' +\n        '.test-widget-display {' +\n        'resize: both;' +\n        'direction: rtl;' +\n        'position: fixed;' +\n        'min-width: 325px;' +\n        'max-width: 500px;' +\n        'max-height: 100%;' +\n        'overflow-y: auto;' +\n\n        'border: none;' +\n\n        'background-color: rgba(230, 230, 230, 0.9);' +\n        'opacity: 0.5;' +\n        'transition: opacity 0.3s, max-height 0.3s;' +\n        '' +\n        'top: 0px;' +\n        'right: 0px;' +\n        'text-align: left;' +\n        'z-index: 99999 !important;' +\n        '}' +\n\n        '.test-widget-display:hover {' +\n        'opacity: 1;' +\n        '}';\n\n  var innerStyles = '@font-face{' +\n        'font-family: \"Source Sans Pro\";' +\n        'src: url(data:font/ttf;base64,' +\n        sourceSansProFont +\n        ') format(\"truetype\");' +\n        '} ' +\n        '* {' +\n        'font-family: \"Source Sans Pro\", sans-serif;' +\n        '}' +\n        'body {' +\n        'padding: 0.5em;' +\n        'margin: 0;' +\n        '}' +\n\n        'img {' +\n        'height: 2.25em;' +\n        'margin-bottom: -0.75em;' +\n        '}' +\n\n        '.udacity-header {' +\n        'font-size: 2em;' +\n        '}' +\n\n        '.test-desc {' +\n        'width: 100%;' +\n        '}' +\n\n        '.correct {' +\n        'color: #060;' +\n        '-webkit-animation-duration: 0.5s;' +\n        '-webkit-animation-name: popin;' +\n        'animation-duration: 0.5s;' +\n        'animation-name: popin;' +\n        '}' +\n\n        '.correct::before {' +\n        'content: \"✓ \";' +\n        '}' +\n\n        '.incorrect {' +\n        'color: #900;' +\n        '}' +\n\n        '.incorrect::before {' +\n        'content: \"✗ \";' +\n        '}' +\n\n        '.error {' +\n        'color: #a48700;' +\n        '}' +\n\n        '.error::before {' +\n        'content: \"?? \";' +\n        '}' +\n\n        '.flex-container {' +\n        'display: flex;' +\n        'justify-content: space-between;' +\n        '}' +\n\n        '.toggle-display {' +\n        'display: inline-block;' +\n        'float: right;' +\n        'height: 2em;' +\n\n        'color: white;' +\n        'box-sizing: border-box;' +\n\n        'border-radius: 2px;' +\n        'border-color: #777;' +\n        'border: 1px solid transparent;' +\n\n        'background-color: #777;' +\n\n        'cursor: pointer;' +\n        '}' +\n\n        '.toggle-display:hover:not(:disabled) {' +\n        'border-color: #555;' +\n        'background-color: #555;' +\n        '}' +\n\n        '.toggle-display:disabled {' +\n        'background-color: #888;' +\n        'color: #ddd;' +\n        '}' +\n\n        '.hide {' +\n        'max-height: 0px;' +\n        'overflow: hidden;' +\n        '}' +\n\n        '.shown::before {' +\n        'content: \"Hide\";' +\n        '}' +\n\n        '.hidden::before {' +\n        'content: \"Show\";' +\n        '}' +\n\n        '.suite-title {' +\n        'font-size: 1.25em;' +\n        '}' +\n        '.suite-code-container {' +\n        'background: rgba(0,0,0,0.6);' +\n        'color: #eee;' +\n        'display: none;' +\n        'padding: 6px 0.5em;' +\n        'margin: 0.5em -0.5em;' +\n        'text-align: center;' +\n        '}' +\n\n        '/* Custom animation for the iFrame */' +\n        '@keyframes popin {' +\n        'from {' +\n        'font-size: 1em;' +\n        '}' +\n\n        '25% {' +\n        'font-size: 1.5em;' +\n        '}' +\n\n        'to {' +\n        'font-size: 1em;' +\n        '}' +\n        '}';\n\n  var template = {\n    head: '    <title>Udacity Feedback</title>' +\n      '    <meta charset=\"UTF-8\">' +\n      // Disabled until a solution is found. Because it’s an injected script, it\n      // wouldn’t be secure to pass the extension path.\n      // '    <link rel=\"stylesheet\" href=\"https://fonts.googleapis.com/css?family=Source+Sans+Pro\">' +\n      '    <style>' + innerStyles + '</style>' +\n      '  </head>',\n    body: '  <body>' +\n      '    <!-- test-widget component starts here -->' +\n      '    <div class=\"udacity-header\">Udacity Feedback</div>' +\n      '    <div class=\"view-container\">' +\n      '    </div>' +\n      '    <!-- test-widget component ends here -->' +\n      '  </body>' +\n      '<!-- test-widget.html ends here -->'\n  };\n\n  /**\n   * Returns the frame context.\n   * @returns {Document} The current\n   * @throws {Error} Errors about bad initialization.\n   * @private\n   */\n  var _frameContext = function () {\n    if(frameId === null) {\n      throw new Error('The widget must first be created.');\n    }\n    var tw = document.getElementById(frameId);\n\n    if(tw === null) {\n      throw new Error('The “' + frameId + '” iframe doesn’t exist.');\n    }\n\n    // Compatibility fix\n    return tw.contentWindow || tw.contentDocument.document || tw.contentDocument;\n  };\n\n  /**\n   * Get the widget document. It prevents direct access to the iFrame.\n   * @returns {Document}\n   */\n  var _frameDocument = function() {\n    return _frameContext().document;\n  };\n\n  /**\n   * Calculate the height of the test-widget could have. It can’t be bigger than the window since it has position of fixed.\n   * @returns {}\n   */\n  var _calculateFrameHeight = function() {\n    var frameHeight = _frameDocument().body.offsetHeight;\n    var windowHeight = window.innerHeight;\n    return frameHeight < windowHeight ? frameHeight : windowHeight;\n  };\n\n  /**\n   * Set the `testWidget` frame element height to its inner height (height of child document).\n   */\n  var _setFrameHeight = function() {\n    var frameHeight = _calculateFrameHeight();\n    // console.log(\"frameHeight = \", frameHeight);\n\n    if(window.innerHeight !== lastWindowHeight || frameHeight !== lastFrameHeight) {\n      lastWindowHeight = window.innerHeight;\n      lastFrameHeight = frameHeight;\n      frameElement.style.height =  frameHeight + 'px';\n      // console.log(\"frameElement.style.height = \", frameElement.style.height);\n    }\n    // console.log(\"lastFrameHeight = \", lastFrameHeight);\n    // console.log(\"lastWindowHeight = \", lastWindowHeight);\n  };\n\n  /**\n   * Execute a callback function when the iFrame document changes.\n   * @param {function} callback - The callback to call when the iFrame document changes.\n   */\n  var _onFrameChange = function(callback) {\n    var frameDocument = _frameDocument();\n    var observer = new MutationObserver(function(mutations) {\n      // debugger;\n      // console.log('Inside _onFrameChange MutationObserver. Mutation: ', mutations[i]);\n      // console.log('Callback: ', callback.toString());\n      callback(mutations);\n    });\n    observer.observe(frameDocument, {childList: true, attributes: true, characterData: true, subtree: true});\n  };\n\n  /**\n   * Initializes the widget with its random ID (Not really useful) and append the widget to the current Document. The widget is an iFrame\n   * @returns {Document} The iFrame document.\n   * @throws {Error} The test widget can’t be loaded.\n   */\n  var _buildFrame = function() {\n    frameId = 'tw-' + Math.floor(Math.random() * 100000000000).toString();\n\n    // Since the iFrame loading is asynchronous\n    var promise = new Promise(\n      function(resolve, reject) {\n        var tw = document.createElement('iframe');\n\n        tw.id = frameId;\n        tw.className = 'test-widget-display';\n        tw.srcdoc = '';\n\n        document.body.appendChild(tw);\n\n        tw.onload = function() {\n          frameElement = tw;\n\n          window.addEventListener('resize', function() {\n            _setFrameHeight();\n          });\n\n          _onFrameChange(_setFrameHeight);\n          resolve(tw);\n        };\n\n        tw.onerror = function(e) {\n          reject(e);\n        };\n      }).catch(function(e) {\n        throw new Error('Couldn’t load the test widget: ' + e.message);\n      });\n\n    return promise;\n  };\n\n\n  /**\n   * Calls {@link _buildFrame} and initialize {@link testResults}.\n   */\n  var _buildWidget = function() {\n    // Wait for the iFrame to load since it would return null\n    return _buildFrame().then(function() {\n      var testWidgetDisplay = _frameDocument();\n\n      // Reviewer: This is only local\n      testWidgetDisplay.head.innerHTML = template.head;\n      testWidgetDisplay.body.innerHTML = template.body;\n\n      var outerCSS = document.createElement('style');\n      outerCSS.id = 'outer-styles';\n\n      // Reviewer: This is only local\n      outerCSS.textContent = outerStyles;\n      document.head.appendChild(outerCSS);\n\n      // console.log(\"testWidgetDisplay = \", testWidgetDisplay);\n      var viewContainer = testWidgetDisplay.querySelector('.view-container');\n      // console.log(\"viewContainer = \", viewContainer);\n      // initialize the view options\n      var testResultsElem = components.createElement('test-results');\n      viewContainer.appendChild(testResultsElem);\n    });\n  };\n\n  /**\n   * Removes the widget from the current Document.\n   */\n  var _killWidget = function() {\n    var tw = document.getElementById(frameId);\n    var styles = document.getElementById('outer-styles');\n\n    document.body.removeChild(tw);\n    document.head.removeChild(styles);\n    frameId = null;\n  };\n\n  exports = {\n    buildWidget: _buildWidget,\n    killWidget: _killWidget,\n\n    // TODO: Doesn’t seem to be used outside\n    frameDocument: _frameDocument\n  };\n\n  return exports;\n})();\n\n// test-widget.js<test_widget> ends here\n"
  },
  {
    "path": "src/js/ActiveTest.js",
    "content": "/*global TA */\n\n/**\n * @fileOverview This file contains the prototype of a single running test.\n * @name ActiveTest.js<js>\n * @author Cameron Pittman\n * @license GPLv3\n */\n\n// Custom types documentation\n/**\n * An object with collector and reporter properties.\n * @typedef {Object} definition\n * @property {string} nodes - String containing a CSS selector (i.e. jQuery style).\n * @property {string} cssProperty - A CSS property written as camelCase (backgroundColor) that will be collected from {@link nodes}.\n * @property {string} attribute - An HTML attribute will be collected from {@link node}.\n * @property {AbsolutePosition} absolutePosition -\n */\n\n/**\n * An object containing boolean properties.\n * @typedef {Object} flags\n * @property {boolean} alwaysRun - The test continues to run even after it passes.\n * @property {boolean} noRepeat  - The test runs only once rather than repeatedly.\n */\n\n// Implementation\n/**\n * Construct a single test that will be run once or repeatedly.\n * @param {string} rawTest.description - Title that shows up in the test widget list.\n * @param {flags} rawTest.flags - Flags controlling the test behaviour.\n * @param {definition} rawTest.definition -\n * @returns {}\n * @throws {}\n */\nfunction ActiveTest(rawTest) {\n  // TODO: will need to validate all of these\n  this.description = rawTest.description;\n  this.flags = rawTest.flags || {};\n  this.id = parseInt(Math.random() * 1000000);\n  this.testPassed = false;\n  this.debugData = [];\n  this.incorrectInfo = [];\n\n  this.gradeRunner = function() {};\n  var self = this;\n\n  try {\n    // validate the description.\n    if (typeof this.description !== 'string') {\n      throw new TypeError('Every test needs a description string.');\n    }\n\n    // validate the flags\n    if (typeof this.flags !== 'object') {\n      throw new TypeError('If assigned, flags must be an object.');\n    }\n\n    if (typeof rawTest.definition !== 'object') {\n      throw new TypeError('Every test needs a definition');\n    }\n\n    // alwaysRun and noRepeat flags are mutually exclusive\n    if (this.flags.alwaysRun && this.flags.noRepeat) {\n      throw new TypeError('“alwaysRun” and “noRepeat” flags are mutually exclusive. Only one of them can be set.');\n    }\n  } catch(e) {\n\n  }\n\n  this.ta = new TA(this.description);\n\n  // translates json definitions to method calls\n  self.queueUp = (function(config) {\n    var methodsToQueue = self.ta._translateConfigToMethods(config);\n    return function() {\n      methodsToQueue.forEach(function(method) {\n        try {\n          method();\n        } catch (e) {\n          self.hasErred();\n          console.error(self.description + ' has an invalid definition.');\n        }\n      });\n    };\n\n  })(rawTest.definition);\n}\n\n/**\n * Set off the fireworks! A test passed! Assumes you mean test passed unless didPass is false.\n * @param  {Boolean}  didPass unless didPass === false, method assumes it to be true.\n * @return {Boolean}         [description]\n */\nActiveTest.prototype.hasPassed = function(didPass) {\n  var attribute = null;\n  if (!didPass) {\n    attribute = false;\n  } else {\n    attribute = true;\n    this.testPassed = true;\n\n    if (!this.flags.alwaysRun || this.flags.noRepeat) {\n      this.stopTest();\n    }\n\n    window.dispatchEvent(new CustomEvent('ud-test-pass', {'detail': this.description}));\n  }\n  this.element.dataset.testPassed = attribute;\n  this.suite.checkTests();\n};\n\nActiveTest.prototype.hasErred = function() {\n  this.stopTest();\n  this.element.dataset.testPassed = 'error';\n};\n\n/**\n Run a synchronous activeTest every 1000 ms\n */\nActiveTest.prototype.runTest = function() {\n  var self = this;\n\n  var noRepeat = this.flags.noRepeat || false; // run only once on load\n  var alwaysRun = this.flags.alwaysRun || false; // keep running even if test passes\n  var optional = this.flags.optional || false; // test does not affect code display\n\n  var testRunner = function() {\n    var promise = new Promise(function(resolve, reject) {\n      // clear for every run\n      self.debugData = [];\n      self.values = [];\n      self.incorrectInfo = [];\n      // resolve when the test finishes\n      self.ta.onresult = function(result) {\n        resolve(result);\n      };\n\n      self.ta.onerror = function(reason, keepGoing) {\n        self.debugData.push(reason);\n        if (!keepGoing) {\n          self.hasErred();\n        }\n      };\n\n      self.ta.onincorrect = function(reason) {\n        self.incorrectInfo.push(reason);\n      };\n\n      // clean out the queue from the last run\n      self.ta.queue.clear();\n\n      // this call actually runs the test\n      self.queueUp();\n\n    }).then(function(gradedTest) {\n      var testCorrect = gradedTest.isCorrect;\n      // TODO: nothing is done with the values. Do something?\n      var testValues = '';\n      gradedTest.questions.forEach(function(val) {\n        testValues = testValues + ' ' + val.value;\n        self.values.push(testValues);\n      });\n\n      self.hasPassed(testCorrect);\n    });\n  };\n\n  if (noRepeat) {\n    testRunner();\n  } else {\n    testRunner();\n    this.gradeRunner = window.setInterval(testRunner, 1000);\n  }\n};\n\nActiveTest.prototype.stopTest = function() {\n  var self = this;\n  clearInterval(self.gradeRunner);\n};\n\n// ActiveTest.js<js> ends here\n"
  },
  {
    "path": "src/js/GradeBook.js",
    "content": "/**\n * @fileOverview The GradeBook maintains and reports on the state of a set of questions registered by the TA. The GradeBook reports out on the final state of each active_test.\n * @name GradeBook.js<GE>\n * @author Cameron Pittman\n * @license GPLv3\n */\n\n/**\n * The GradeBook constructor sets questions and passed to default values.\n */\nfunction GradeBook() {\n  this.questions = [];\n  this.passed = false;\n};\n\nObject.defineProperties(GradeBook.prototype, {\n  numberOfQuestions: {\n    /**\n     * Find the number of questions.\n     * @return {Number} number of questions\n     */\n    get: function() {\n      return this.questions.length;\n    }\n  },\n  numberCorrectQuestions: {\n    /**\n     * Find the number of questions evaluated as correct.\n     * @return {Number} numberCorrect - number of correct questions.\n     */\n    get: function() {\n      var numberCorrect = 0;\n      this.questions.forEach(function(question) {\n        if (question.correct) {\n          numberCorrect += 1;\n        }\n      });\n      return numberCorrect;\n    }\n  },\n  allCorrect: {\n    /**\n     * Compares the total questions to total questions correct.\n     * @return {Boolean} isAllGood - true if all are correct and false otherwise.\n     */\n    get: function() {\n      var isAllGood = false;\n      if (this.numberOfQuestions === this.numberCorrectQuestions && this.numberOfQuestions > 0) {\n        isAllGood = true;\n      }\n      return isAllGood;\n    }\n  },\n  numberWrongQuestions: {\n    /**\n     * Find the number of wrong questions.\n     * @return {Number} numberWrong - the number of wrong questions.\n     */\n    get: function() {\n      var numberWrong = 0;\n      numberWrong = numberOfQuestions - numberCorrectQuestions;\n      return numberWrong;\n    }\n  },\n  report: {\n    /**\n     * Returns all questions and the overall correctness of the active_test. Note: this is the data returned to the active_test component.\n     * @return {Object} - contains a boolean indicating whether the test passes and an array of all questions.\n     */\n    get: function() {\n      return {\n        isCorrect: this.passed,\n        questions: this.questions\n      };\n    }\n  }\n});\n\n/**\n * Takes in a set of values from the target. Adds to gradebook.\n * @param {object} target - only what the GradeBook needs to know about the Target\n */\nGradeBook.prototype.recordQuestion = function(target) {\n  target.correct = false;\n  this.questions.push(target);\n};\n\n/**\n * Empties the questions array and ensures that the test hasn’t passed prematurely. Called each time a new question is registered.\n */\nGradeBook.prototype.reset = function() {\n  this.questions = [];\n  this.passed = false;\n};\n\n/**\n * Will iterate through all the questions and return if they meet grade criteria\n * @param  {Object} config - {String} config.strictness, {Boolean} config.not, {Function} config.callback\n * @return {Object} the report from the gradebook instance containing whether the test passed and all of the questions in consideration.\n */\nGradeBook.prototype.grade = function(config) {\n  var strictness;\n  var not;\n  var callback;\n  strictness = config.strictness;\n  not = config.not;\n  callback = config.callback;\n\n  this.questions.forEach(function(question) {\n    question.correct = callback(question);\n\n    if (not) {\n      question.correct = !question.correct;\n    }\n  });\n\n  if (strictness === 'some') {\n    if (this.numberCorrectQuestions <= this.numberOfQuestions && this.numberCorrectQuestions > 0) {\n      this.passed = true;\n    };\n  } else if (typeof strictness === 'number' && strictness > 0) {\n    if (this.numberCorrectQuestions <= strictness && this.numberCorrectQuestions > 0) {\n      this.passed = true;\n    }\n  } else {\n    this.passed = this.allCorrect;\n  }\n\n  // one last check to make sure there actually were questions\n  if (this.numberOfQuestions === 0 && not) {\n    this.passed = !this.passed;\n  };\n  return this.report;\n};\n\n// GradeBook.js<js> ends here\n"
  },
  {
    "path": "src/js/Queue.js",
    "content": "/**\n * @fileOverview This file contains a `queue` Data Structure implementation for chaining promises.\n * @see http://www.dustindiaz.com/async-method-queues\n * @see http://www.mattgreer.org/articles/promises-in-wicked-detail/\n * @name Queue.js<js>\n * @author Cameron Pittman\n * @license GPLv3\n */\n\n/**\n * Queue Data Structure implementation to chain promises.\n */\nfunction Queue() {\n  this._methods = [];\n  this._flushing = false;\n  this._blocked = false;\n}\n\nQueue.prototype = {\n  add: function(fn) {\n    this._methods.push(fn);\n    if (!this._flushing && !this._blocked) {\n      this.step();\n    }\n  },\n\n  clear: function() {\n    this._flushing = false;\n    this._methods = [];\n  },\n\n  step: function() {\n    var self = this;\n\n    if (!this._flushing) {\n      this._flushing = true;\n    }\n\n    function executeInPromise(fn) {\n      return new Promise(function (resolve, reject) {\n        if (fn) {\n          try {\n            var ret = fn();\n          } catch (e) {\n            self.block();\n          }\n        }\n        resolve(ret);\n      });\n    }\n    if (!this._blocked) {\n      executeInPromise(this._methods.shift()).then(function(resolve) {\n        if (self._methods.length > 0) {\n          self.step();\n        }\n      });\n    }\n  },\n\n  block: function() {\n    this._blocked = true;\n  },\n\n  unblock: function() {\n    this._blocked = false;\n    this.step();\n  }\n};\n\n// Queue.js<js> ends here\n"
  },
  {
    "path": "src/js/README.md",
    "content": "## Front-End Grading Engine\nThe files in this directory get concatenated into `ext/app/js/libs/GE.min.js`. See the build script for its order.\n\nBefore being an extension, the _Front-End Grading Engine_ was a JavaScript library to be used in the page itself.\n\n### Commentary\nFiles as class definitions are capitalized.\n"
  },
  {
    "path": "src/js/Suite.js",
    "content": "/*global ActiveTest, components */\n\n/**\n * @fileOverview This file contains the constructor for a `Suite` of tests.\n * @name Suite.js<js>\n * @author Cameron Pittman\n * @license GPLv3\n */\n\nfunction Suite(rawSuite) {\n  var name = rawSuite.name;\n  var code = rawSuite.code;\n  var activeTests = [];\n  var id = parseInt(Math.random() * 1000000);\n\n  // validate the name\n  if (typeof name !== 'string') {\n    throw new TypeError('Every suite needs a name string.');\n  }\n\n  // validate the code\n  if (typeof code !== 'string') {\n    throw new TypeError('Every suite needs a code string.');\n  }\n\n  this.name = name;\n  this.code = code;\n  this.activeTests = [];\n  this.id = id;\n  this.suitePassed = false; // put a setter on this to emit an event.\n}\n\nObject.defineProperties(Suite.prototype, {\n  numberOfTests: {\n    get: function() {\n      return this.activeTests.length || 0;\n    }\n  },\n  numberOfCorrectTests: {\n    get: function() {\n      var numberCorrect = 0;\n      this.activeTests.forEach(function(test) {\n        if (test.testPassed) {\n          numberCorrect += 1;\n        }\n      });\n      return numberCorrect;\n    }\n  },\n  numberOfCorrectOrOptionalTests: {\n    get: function() {\n      var numberCorrectOrOptional = 0;\n      this.activeTests.forEach(function(test) {\n        if (test.optional || test.testPassed) {\n          numberCorrectOrOptional += 1;\n        }\n      });\n      return numberCorrectOrOptional;\n    }\n  },\n  numberOfOptionalTests: {\n    get: function() {\n      var numberOptional = 0;\n      this.activeTests.forEach(function(test) {\n        if (test.optional) {\n          numberOptional += 1;\n        }\n      });\n    }\n  },\n  allCorrect: {\n    get: function() {\n      var allGood = false;\n      if (this.numberOfTests - this.numberOfCorrectOrOptionalTests <= 0) {\n        allGood = true;\n      }\n      return allGood;\n    }\n  }\n});\n\nSuite.prototype.getDebugData = function() {\n  this.activeTests.forEach(function(at) {\n    if (at.debugData.length > 0) {\n      console.warn('%c' + 'ERROR: ' + at.description + ': ' + at.debugData.join(' '), 'color: red;');\n    }\n  });\n};\n\nSuite.prototype.getIncorrectInfo = function() {\n  this.activeTests.forEach(function(at) {\n    if (at.incorrectInfo.length > 0) {\n      console.warn('Incorrect: ' + at.description + ': ' + at.incorrectInfo.join('\\n'));\n    }\n  });\n};\n\nSuite.prototype.getValues = function() {\n  this.activeTests.forEach(function(at) {\n    if (at.values.length > 0) {\n      console.warn('Collected Values: ' + at.description + ': ' + at.values.join('\\n'));\n    }\n  });\n};\n\nSuite.prototype.createTest = function(rawTest) {\n  var activeTest = new ActiveTest(rawTest);\n  activeTest.suite = this;\n\n  function createTestElement(newTest) {\n    var activeTestFragment = components.createElement('active-test');\n    var activeTestElement = '';\n\n    // When appending a fragment, it becomes void\n    for(var i=0, len=activeTestFragment.childNodes.length; i<len; i++) {\n      if(activeTestFragment.childNodes[i].nodeType !== 8) {\n        activeTestElement = activeTestFragment.childNodes[i];\n        break;\n      }\n    }\n\n    // find the suite element to which the test belongs\n    var activeTestsContainer = activeTest.suite.element.querySelector('.active-tests');\n    // attributes get applied to the view\n    activeTestElement.dataset.description = newTest.description;\n    activeTestElement.dataset.testPassed = newTest.testPassed;\n\n    // let the Test know which element belongs to it\n    activeTest.element = activeTestElement;\n\n    activeTestsContainer.appendChild(activeTestFragment);\n    return activeTestElement;\n  }\n\n  activeTest.element = createTestElement({\n    description: activeTest.description,\n    passed: activeTest.testPassed,\n    definition: activeTest.definition\n  });\n\n  this.activeTests.push(activeTest);\n  activeTest.runTest();\n};\n\nSuite.prototype.checkTests = function() {\n  var passed = this.allCorrect;\n  this.suitePassed = passed;\n  this.element.suitePassed = passed; // What’s that?\n  this.element.dataset.suitePassed = passed;\n  this.element.dataset.numberOfTests = this.activeTests.length;\n};\n\n// Suite.js<js> ends here\n"
  },
  {
    "path": "src/js/TACollectors.js",
    "content": "/*global Target, GradeBook, Queue, getDomNodeArray */\n\n/**\n * @fileOverview The Teaching Assistant (TA) is responsible for:\n *  • collecting data from the page and creating a tree of Targets (called a bullseye) representing the information\n *  • traverseing the bullseye and reporting relevant data from Targets and grading instructions into a GradeBook.\n *  • All collectors return the instance of the TA object for chaining.\n *  • Collectors register their operations with the GradeBook, which actually checks the results of the tests.\n * @name TACollectors.js<GE>\n * @author Cameron Pittman\n * @license GPLv3\n */\n\n/**\n * The TA constructor sets default values and instantiates a GradeBook.\n */\nfunction TA(description) {\n  this.target = null;\n  this.gradebook = new GradeBook();\n  this.operations = [];\n  this.gradeOpposite = false;\n  this.picky = false;\n  this.queue = new Queue();\n  this.description = description;\n}\n\nObject.defineProperties(TA.prototype, {\n  childPosition: {\n    /**\n     * To find a child node’s index in relation to its immediate siblings\n     * @return {object} TA - the TA instance for chaining.\n     */\n    get: function() {\n      var self = this;\n      this.queue.add(function() {\n        self._runAgainstBottomTargets(function(target) {\n          var elem = target.element;\n          var position = null;\n          // TODO: correct for other non-normal DOM elems?\n          var ignoreTheseNodes = 0;\n          Array.prototype.slice.apply(target.element.parentNode.children).forEach(function(val, index) {\n            if (val.nodeName === '#text') {\n              ignoreTheseNodes += 1;\n            }\n            if (val === elem) {\n              position = index - ignoreTheseNodes;\n            }\n          });\n          return position;\n        });\n      });\n      return this;\n    }\n  },\n  count: {\n    /**\n     * To count the number of children at the bottom level of the bullseye\n     * @return {object} TA - the TA instance for chaining.\n     */\n    get: function() {\n      var self = this;\n      this.queue.add(function() {\n        // doing more than accessing a property on existing target\n        // because counting can move up the bullseye to past\n        // Targets. Need to reset operations\n        self._registerOperation('count');\n        self._runAgainstNextToBottomTargets(function(target) {\n          var length = null;\n          try {\n            // A `element` is the result of calling `children` (with a\n            // query) that didn’t contain any elements.\n            length = target.children.reduce(function(previous, current) {\n              if(current.element !== null) {\n                return previous + 1;\n              }\n              return previous;\n            }, 0);\n          } catch (e) {\n            length = 0;\n          }\n          return length;\n        });\n      });\n      return this;\n    }\n  },\n  innerHTML: {\n    /**\n     * To pull the innerHTML of a DOM node.\n     * @return {object} TA - the TA instance for chaining.\n     */\n    get: function() {\n      var self = this;\n      this.queue.add(function() {\n        self._registerOperation('innerHTML');\n        self._runAgainstBottomTargetElements(function(element) {\n          var html = '';\n          try {\n            html = element.innerHTML;\n          } catch (e) {\n            self.onerror('Cannot get innerHTML. Element probably doesn’t exist.', true);\n          }\n          return html;\n        });\n      });\n      return this;\n    }\n  },\n  _targetIds: {\n    /**\n     * Not a collector! Private use only. Get an array of all target ids.\n     * @return {array} ids of all targets in the bullseye.\n     */\n    get: function() {\n      var ids = [];\n      this._traverseTargets(function(target) {\n        ids.push(target.id);\n      });\n      return ids;\n    }\n  },\n  UAString: {\n    /**\n     * Get the User-Agent string of the browser.\n     * @return {object} TA - the TA instance for chaining.\n     */\n    get: function() {\n      var self = this;\n      this.queue.add(function() {\n        self._registerOperation('UAString');\n        self.target = new Target();\n        self._runAgainstTopTargetOnly(function(topTarget) {\n          var ua = '';\n          try {\n            ua = navigator.userAgent;\n          } catch (e) {\n            self.onerror('Can’t find a user agent string.', true);\n          }\n          return ua;\n        });\n      });\n      return this;\n    }\n  },\n  DPR: {\n    /**\n     * Get the Device Pixel Ratio of the viewport.\n     * @return {object} TA - the TA instance for chaining.\n     */\n    get: function() {\n      var self = this;\n      this.queue.add(function() {\n        self._registerOperation('DPR');\n        self.target = new Target();\n        self._runAgainstTopTargetOnly(function(topTarget) {\n          var dpr = null;\n          try {\n            dpr = +window.devicePixelRatio;\n          } catch (e) {\n            self.onerror('Can’t find device pixel ratio.', true);\n          }\n          return dpr;\n        });\n      });\n      return this;\n    }\n  }\n});\n\n/**\n * Initialized for async call later.\n */\nTA.prototype.onresult = function(testResult) {};\n\n/**\n * Let the TA know this just happened and refresh the questions in the GradeBook.\n * @param {string} operation - the thing that just happened\n */\nTA.prototype._registerOperation = function(operation) {\n  this.operations.push(operation);\n  this.gradebook.reset();\n};\n\n/**\n * Private method to traverse all targets in the bullseye.\n * @param  {Function} callback - method to call against each target\n */\nTA.prototype._traverseTargets = function(callback) {\n  // http://www.timlabonne.com/2013/07/tree-traversals-with-javascript/\n\n  /**\n   * Recursively dive into a tree structure from the top. Used on the Target structure here.\n   * @param  {object} node - a target of bullseye. Start with the top.\n   * @param  {function} callback - function to run against each node\n   */\n  function visitDfs (node, callback) {\n    if (callback) {\n      callback(node);\n    }\n\n    node.children.forEach(function(child, index, arr) {\n      visitDfs(child, callback);\n    });\n  }\n  visitDfs(this.target, callback);\n};\n\n/**\n * Run a function against the top-level Target in the bullseye\n * @param  {function} callback - the function to run against specified Targets\n */\nTA.prototype._runAgainstTopTargetOnly = function(callback) {\n  var self = this;\n  this.target.value = callback(this.target);\n\n  if (this.target.value !== undefined &&\n      this.target.value !== null) {\n    self.gradebook.recordQuestion(this.target);\n  } else {\n    this.target.children.forEach(function(kid) {\n      self.gradebook.recordQuestion(kid);\n    });\n  }\n};\n\n/**\n * Run a function against bottom targets in the bullseye\n * @param  {function} callback - the function to run against specified Targets\n */\nTA.prototype._runAgainstBottomTargets = function(callback) {\n  var self = this;\n\n  var allTargets = this._targetIds;\n\n  this._traverseTargets(function(target) {\n    if (!target.hasChildren && allTargets.indexOf(target.id) > -1) {\n      target.value = callback(target);\n\n      if (target.value !== undefined &&\n          target.value !== null) {\n        self.gradebook.recordQuestion(target);\n      } else {\n        target.children.forEach(function(kid) {\n          self.gradebook.recordQuestion(kid);\n        });\n      }\n    }\n  });\n};\n\n/**\n * Run a function against the elements of the bottom targets in the bullseye\n * @param  {function} callback - the function to run against specified elements\n */\nTA.prototype._runAgainstBottomTargetElements = function(callback) {\n  var self = this;\n\n  var allTargets = this._targetIds;\n\n  this._traverseTargets(function(target) {\n    if (!target.hasChildren && allTargets.indexOf(target.id) > -1) {\n      target.value = callback(target.element);\n\n      if (target.value !== undefined &&\n          target.value !== null) {\n        self.gradebook.recordQuestion(target);\n      } else {\n        target.children.forEach(function(kid) {\n          self.gradebook.recordQuestion(kid);\n        });\n      }\n    }\n  });\n};\n\n/**\n * Run a function against the next to bottom targets in the bullseye\n * @param  {function} callback - the function to run against specified elements\n */\nTA.prototype._runAgainstNextToBottomTargets = function(callback) {\n  var self = this;\n\n  this._traverseTargets(function(target) {\n    if (target.hasChildren && !target.hasGrandkids) {\n      target.value = callback(target);\n\n      if (target.value !== undefined &&\n          target.value !== null) {\n        self.gradebook.recordQuestion(target);\n      } else {\n        target.children.forEach(function(kid) {\n          self.gradebook.recordQuestion(kid);\n        });\n      }\n    }\n  });\n};\n\n/**\n * Generates the top-level target. Matched elements end up as children targets. It will not have a element.\n * @param  {string} CSS selector - the selector of the elements you want to query\n * @return {object} TA - the TA instance for chaining.\n */\nTA.prototype.theseElements = function(selector) {\n  var self = this;\n  this.queue.add(function() {\n    self._registerOperation('gatherElements');\n\n    self.target = new Target();\n\n    self._runAgainstTopTargetOnly(function(topTarget) {\n      var elems = getDomNodeArray(selector);\n\n      if (!selector) {\n        self.onerror('Cannot find elements without a selector.', true);\n      } else if (elems.length > 0) {\n        elems.forEach(function(elem, index, arr) {\n          var target = new Target();\n          target.element = elem;\n          target.index = index;\n          topTarget.children.push(target);\n        });\n      }\n    });\n  });\n  return this;\n};\n// more common syntax\nTA.prototype.nodes = TA.prototype.theseElements;\n\n/**\n * Will run a query against the lowest level targets in the Target tree. Note it will traverse all the way down the DOM.\n * @param  {string} CSS selector - the selector of the children you want to query\n * @return {object} TA - the TA instance for chaining.\n */\nTA.prototype.deepChildren = function(selector) {\n  var self = this;\n  this.queue.add(function() {\n    self._registerOperation('gatherDeepChildElements');\n\n    self._runAgainstBottomTargets(function(target) {\n      var elems = getDomNodeArray(selector, target.element);\n\n      if (!selector) {\n        self.onerror('Cannot find elements without a selector.', true);\n        throw new Error();\n      } else if (target.element) {\n        if(elems.length === 0) {\n          var childTarget = new Target();\n          childTarget.element = null;\n          childTarget.index = null;\n          target.children.push(childTarget);\n        }\n        elems.forEach(function(newElem, index) {\n          var childTarget = new Target();\n          childTarget.element = newElem;\n          childTarget.index = index;\n          target.children.push(childTarget);\n        });\n      }\n    });\n  });\n};\n// for alternate syntax options\nTA.prototype.children = TA.prototype.deepChildren;\n\nTA.prototype.get = function(typeOfValue) {\n  var self = this;\n  switch (typeOfValue) {\n  case 'count':\n    self.count;\n    break;\n  case 'childPosition':\n    self.childPosition;\n    break;\n  case 'innerHTML':\n    self.innerHTML;\n    break;\n  case 'UAString':\n    self.UAString;\n    break;\n  case 'DPR':\n    self.DPR;\n    break;\n  default:\n    self.onerror('Cannot “get”: “' + typeOfValue + '”. Options include: “count”, “childPosition”, “DPR”, “innerHTML”, and “UAString”.');\n    throw new Error();\n  }\n};\n\nTA.prototype.limit = function(limit) {\n  var self = this;\n\n  if (!limit || limit < 1) {\n    self.onerror('Illegal “limit”. Options include: any positive number, “all” or “some”. Defaults to “all”');\n    throw new Error();\n  }\n\n  this.queue.add(function() {\n    self.strictness = limit;\n  });\n\n  return this;\n};\n\n/**\n * Get any CSS style of any element.\n * @param  {string} property - the CSS property to examine. Should be camelCased.\n * @return {object} TA - the TA instance for chaining.\n */\nTA.prototype.cssProperty = function(property) {\n  var self = this;\n  this.queue.add(function() {\n    self._registerOperation('cssProperty');\n\n    self._runAgainstBottomTargetElements(function(elem) {\n      var style = null;\n      try {\n        // TODO: this causes a FSL that could affect framerate?\n        style = self._getComputedValue(property, elem);\n      } catch (e) {\n        self.onerror('Cannot get CSS property: “' + property + '”.', true);\n      }\n      return style;\n    });\n  });\n  return this;\n};\n\n/**\n * Get a specified CSS property value.\n * @param {string} property - The CSS property name.\n * @param {HTMLElement} elem - The Element to get the CSS property value.\n * @returns {string} Either the CSS computed value or a tweaked value (depending\n * on the property name).\n * @throws {Error} Bad arguments.\n */\nTA.prototype._getComputedValue = function(property, elem) {\n  var self = this,\n      computedStyles = window.getComputedStyle(elem),\n      value = null;\n\n  /**\n   * Calculates the margin from a given side. It should only be used with\n   * element having a normal flow.\n   * @param {string} marginName - The margin side.\n   * @returns {string} The tweaked margin value.\n   * @throws {Error} Bad arguments or the CSS property is invalid.\n   * @todo Implement `marginRight` and `marginBottom`\n   */\n  function getMarginSide(marginName) {\n    var parent = elem.parentElement,\n        // An other container is used to prevent getting the parent padding\n        wrapper = document.createElement('div'),\n\n        // We need children for calculation (min/max)\n        clone = elem.cloneNode(true),\n        result;\n\n    // If the position is different than static, it may use the left property\n    // and it’s also hard to take them into account.\n    if(computedStyles.position !== 'static') {\n      // When both left and right are set, left has precedence over right when\n      // the direction is ltr or right when rtl.\n      throw new Error('“getMargin” only support the “static” position');\n    }\n\n    // Because the wrapper must be without any of those\n    wrapper.style.border = 'none';\n    wrapper.style.padding = '0';\n    wrapper.style.margin = '0';\n    wrapper.style.position = 'static';\n    wrapper.style.display = 'block';\n    wrapper.style.height = 'auto';\n    wrapper.style.width = 'auto';\n\n    wrapper.appendChild(clone);\n    // The parent element of `elem` will get `wrapper` before the `elem` Node\n    parent.insertBefore(wrapper, elem);\n\n    /**\n     * Calculate the offset from a given side. It thus give the margin if used\n     * We never know about custom styleswith a static position and if the actual\n     * We never know about custom stylesside was set.\n     * @param {string} marginName - The name of the margin as camel case.\n     * @returns {int} The calculated margin.\n     * @throws {Error} The {@link marginName} argument isn’t valid.\n     */\n    function calculateMarginForSide(marginName) {\n      var value;\n      switch(marginName) {\n      case 'marginLeft':\n        value = clone.offsetLeft - wrapper.offsetLeft;\n        break;\n      case 'marginTop':\n        value = clone.offsetTop - wrapper.offsetTop;\n        break;\n      case 'marginRight':\n        value = wrapper.clientWidth - (parseInt(window.getComputedStyle(clone).width) +\n                                       calculateMarginForSide('marginLeft'));\n        break;\n      case 'marginBottom':\n        value = wrapper.clientHeight - (parseInt(window.getComputedStyle(clone).height) +\n                                        calculateMarginForSide('marginTop'));\n        break;\n      default:\n        throw new Error('Wrong type of arguments for “marginName”');\n      }\n      return value;\n    }\n\n    // Cache the result if we want to remove the wrapper\n    result = calculateMarginForSide(marginName);\n    wrapper.remove();\n    return result;\n  }\n\n  // Specific tweaks for CSS properties\n  switch(property) {\n  case 'marginTop':\n  case 'marginRight':\n  case 'marginBottom':\n  case 'marginLeft':\n    // Firefox (and Safari?) don’t use the CSS2 specs to calculate the margin\n    // when set to `auto`\n    if(computedStyles[property] === '0px' && computedStyles.display === 'block') {\n      value = getMarginSide(property) + 'px';\n    }\n    break;\n  default:\n    break;\n  }\n\n  // No special tweaks\n  if(value === null) {\n    value = computedStyles[property];\n\n    // A valid CSS value should never be undefined\n    if(value === undefined) {\n      throw new Error();\n    }\n  }\n\n  // Return the tweaked computed value or the actual value if no tweaks\n  return value;\n};\n\n/**\n * Get any attribute of any element.\n * @param  {string} attribute - the attribute under examination.\n * @return {object} TA - the TA instance for chaining.\n */\nTA.prototype.attribute = function(attribute) {\n  var self = this;\n  this.queue.add(function() {\n    self._registerOperation('attribute');\n\n    self._runAgainstBottomTargetElements(function(elem) {\n      var attrValue = null;\n      try {\n        attrValue = elem.getAttribute(attribute);\n      } catch (e) {\n        self.onerror('Cannot get attribute “' + attribute + '”.', true);\n      }\n      if (attrValue === '') {\n        attrValue = true;\n      }\n      return attrValue;\n    });\n  });\n  return this;\n};\n\n// TODO: Is this even used? Seems to be duplicate of {@link TA.prototype.attribute}\n/**\n * Get any property of an object.\n * @param  {string} attribute - the attribute under examination.\n * @return {object} TA - the TA instance for chaining.\n */\nTA.prototype.property = function(key) {\n  var self = this;\n  this.queue.add(function() {\n    self._registerOperation('property');\n\n    self._runAgainstBottomTargetElements(function(obj) {\n      var propertyValue = null;\n      try {\n        propertyValue = obj[key];\n      } catch (e) {\n        self.onerror('Cannot get attribute “' + attribute + '”.', true);\n      }\n      if (propertyValue === '') {\n        propertyValue = true;\n      }\n      return propertyValue;\n    });\n  });\n  return this;\n};\n\n/**\n * Get the position of one side of an element relative to the viewport\n * @param  {string} side - the side of the element in question\n * @return {object} TA - the TA instance for chaining.\n */\nTA.prototype.absolutePosition = function(side) {\n  var self = this;\n  this.queue.add(function() {\n    self._registerOperation('absolutePosition');\n    // http://stackoverflow.com/questions/2880957/detect-inline-block-type-of-a-dom-element\n    function getDisplayType (element) {\n      var cStyle = element.currentStyle || window.getComputedStyle(element, '');\n      return cStyle.display;\n    };\n\n    function isValidSide(side) {\n      if(side === 'top' || side === 'left' || 'bottom' || 'right') {\n        return true;\n      }\n      console.warn('You didn’t pick a side for absolutePosition! Options are “top”, “left”, “bottom” and “right”.');\n      return false;\n    }\n\n    function getOffsetBySide(element, sideName) {\n      var offset = NaN;\n\n      switch (sideName) {\n      case 'top':\n        offset = element.offsetTop;\n        break;\n      case 'left':\n        offset = element.offsetLeft;\n        break;\n      case 'bottom':\n        offset = element.offsetTop + element.offsetHeight;\n        break;\n      case 'right':\n        offset = element.offsetLeft + element.offsetWidth;\n        break;\n      }\n\n      return offset;\n    }\n\n    var selectorFunc = function(elem) {\n      var displayType = getDisplayType(elem);\n      var value = NaN;\n      var maxSize;\n\n      if(!isValidSide(side)) {\n        return value;\n      }\n\n\n      if (displayType === 'block') {\n        value = getOffsetBySide(elem, side);\n      } else if (displayType === 'inline') {\n        value = elem.getBoundingClientRect()[side];\n      }\n\n      // To get the widest size of the window, we need to get the biggest value of client<Size> and inner<Size>.\n      if(side === 'bottom') {\n        // Get the widest window height\n        maxSize = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);\n        value = value === maxSize ? 'max' : value ;\n      } else if(side === 'right') {\n        // Get the widest window width\n        maxSize = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);\n        value = value === maxSize ? 'max' : value;\n      }\n\n      return value;\n    };\n\n    self._runAgainstBottomTargetElements(function(elem) {\n      var absPos = null;\n      try {\n        absPos = selectorFunc(elem);\n      } catch (e) {\n        self.onerror('Cannot get absolute position of “' + side + '”.', true);\n        throw new Error();\n      }\n      return absPos;\n    });\n  });\n  return this;\n};\n\n/**\n * Must be used with noRepeat: true\n * Waits for an event. Grades against event.detail\n * @param  {String} eventName - custom event to listen for\n * @return {Object} TA for chaining\n */\nTA.prototype.waitForEvent = function(eventName) {\n  var self = this;\n  self.queue.block();\n  window.addEventListener(eventName, function(e) {\n    self.queue.unblock();\n    self._runAgainstTopTargetOnly(function(topTarget) {\n      return e.detail;\n    });\n  });\n  this.queue.add(function() {\n    self._registerOperation('gatherElements');\n    self.target = new Target();\n  });\n  return this;\n};\n\n// TACollectors.js<js> ends here\n"
  },
  {
    "path": "src/js/TAReporters.js",
    "content": "/**\n * @fileOverview Reporters live on the TA and are responsible for:\n   * giving the GradeBook instructions for evaluating the questions it has collected.\n   * instantiating the grading process by calling gradebook.grade()\n * @name TAReporters.js<js>\n * @author Cameron Pittman\n * @license GPLv3\n */\n\n/**\n * Checks that either values or elements exist on questions in GradeBook.\n */\nTA.prototype.exists = function(bool) {\n  var self = this;\n\n  if (bool === false && typeof bool === 'boolean') {\n    self.not(true);\n  }\n\n  this.queue.add(function() {\n    var typeOfOperation = self.operations[self.operations.length - 1];\n\n    var doesExistFunc = function() {};\n    switch (typeOfOperation) {\n      case 'gatherElements':\n        doesExistFunc = function(topTarget) {\n          var doesExist = false;\n          if (topTarget.children.length > 0 || topTarget.element || topTarget.value) {\n            doesExist = true;\n          }\n          if (!doesExist) {\n            self.onincorrect('does not exist');\n          }\n          return doesExist;\n        };\n        break;\n      case 'gatherDeepChildElements':\n        doesExistFunc = function(target) {\n          var doesExist = false;\n          if (target.element) {\n            doesExist = true;\n          }\n          if (!doesExist) {\n            self.onincorrect('does not exist');\n          }\n          return doesExist;\n        };\n        break;\n      default:\n        doesExistFunc = function(target) {\n          var doesExist = false;\n          if (target.value || target.element) {\n            doesExist = true;\n          }\n          if (!doesExist) {\n            self.onincorrect('does not exist');\n          }\n          return doesExist;\n        };\n        break;\n    }\n\n    var testResult = self.gradebook.grade({\n      callback: doesExistFunc,\n      not: self.gradeOpposite,\n      strictness: self.strictness\n    });\n    self.onresult(testResult);\n  });\n};\n\n\n/**\n * Used by the GradeBook to negate the correctness of a test.\n * @param  {Boolean} bool The gradeOpposite param gets set to this. Will default to true if it isn’t present or is not specifically false.\n */\nTA.prototype.not = function(bool) {\n  var self = this;\n\n  if (typeof bool !== 'boolean') {\n    bool = true;\n  }\n\n  this.queue.add(function() {\n    if (bool) {\n      self.gradeOpposite = true;\n    }\n  });\n};\n\n/**\n * Check that question values match an expected value. Always uses strict equality.\n * @param  {*} expected - string, number or array of string and numbers.\n */\nTA.prototype.equals = function(config) {\n  var self = this;\n  this.queue.add(function() {\n    var expected;\n    if (typeof config === 'object' && !(config instanceof Array)) {\n      expected = config.expected;\n    } else {\n      expected = config;\n    }\n\n    if (typeof expected !== 'string' && typeof expected !== 'number' && !(expected instanceof Array)) {\n      self.onerror('“equals” needs a string, a number, or an array of string and number values.');\n      throw new Error();\n    }\n\n    if (!(expected instanceof Array)) {\n      expected = [expected];\n    }\n\n    var equalityFunc = function(target) {\n      var isCorrect = false;\n\n      expected.forEach(function(e) {\n        if (target.value === e) {\n          isCorrect = true;\n        }\n      });\n\n      if (!isCorrect) {\n        self.onincorrect(target.value.toString() + ' is not one of: [' + expected.join(', ') + '].');\n      }\n      return isCorrect;\n    };\n\n    var testResult = self.gradebook.grade({\n      callback: equalityFunc,\n      not: self.gradeOpposite,\n      strictness: self.strictness\n    });\n    self.onresult(testResult);\n  });\n};\n\n/**\n * Check that the target value is greater than the given value.\n * @param  {Number} expected - the number for comparison\n * @param  {boolean} orEqualTo - if true, run as >= instead of >\n */\nTA.prototype.isGreaterThan = function(config) {\n  var self = this;\n  this.queue.add(function() {\n    var expected = config.expected || config;\n    var orEqualTo = config.orEqualTo || false;\n\n    if (typeof expected !== 'number') {\n      self.onerror('“isGreaterThan” needs a number.');\n      throw new Error();\n    }\n\n    var greaterThanFunc = function() {};\n    switch (orEqualTo) {\n      case true:\n        greaterThanFunc = function(target) {\n          var isGreaterThan = false;\n          if (getUnitlessMeasurement(target.value) >= getUnitlessMeasurement(expected)) {\n            isGreaterThan = true;\n          }\n          if (!isGreaterThan) {\n            self.onincorrect(target.value + ' is not greater than ' + expected);\n          }\n          return isGreaterThan;\n        };\n        break;\n      default:\n        greaterThanFunc = function(target) {\n          var isGreaterThan = false;\n          if (getUnitlessMeasurement(target.value) > getUnitlessMeasurement(expected)) {\n            isGreaterThan = true;\n          }\n          if (!isGreaterThan) {\n            self.onincorrect(target.value + ' is not greater than ' + expected);\n          }\n          return isGreaterThan;\n        };\n        break;\n    }\n\n    var testResult = self.gradebook.grade({\n      callback: greaterThanFunc,\n      not: self.gradeOpposite,\n      strictness: self.strictness\n    });\n    self.onresult(testResult);\n  });\n};\n\n/**\n * Check that the target value is less than the given value.\n * @param  {Number} expected - the number for comparison\n * @param  {boolean} orEqualTo - if true, run as <= instead of <\n */\nTA.prototype.isLessThan = function(config) {\n  var self = this;\n  this.queue.add(function() {\n    var expected = config.expected || config;\n    var orEqualTo = config.orEqualTo || false;\n\n    if (typeof expected !== 'number') {\n      self.onerror('“isLessThan” needs a value.');\n      throw new Error();\n    }\n\n    var lessThanFunc = function() {};\n    switch (orEqualTo) {\n      case true:\n        lessThanFunc = function(target) {\n          var isLessThan = false;\n          if (getUnitlessMeasurement(target.value) <= getUnitlessMeasurement(expected)) {\n            isLessThan = true;\n          }\n          if (!isLessThan) {\n            self.onincorrect(target.value + ' is not less than ' + expected);\n          }\n          return isLessThan;\n        };\n        break;\n      default:\n        lessThanFunc = function(target) {\n          var isLessThan = false;\n          if (getUnitlessMeasurement(target.value) < getUnitlessMeasurement(expected)) {\n            isLessThan = true;\n          }\n          if (!isLessThan) {\n            self.onincorrect(target.value + ' is not less than ' + expected);\n          }\n          return isLessThan;\n        };\n        break;\n    }\n\n    var testResult = self.gradebook.grade({\n      callback: lessThanFunc,\n      not: self.gradeOpposite,\n      strictness: self.strictness\n    });\n    self.onresult(testResult);\n  });\n};\n\n/**\n * Check that the target value is between upper and lower.\n * @param  {Number} lower - the lower bounds of the comparison\n * @param  {Number} upper - the upper bounds of the comparison\n * @param  {Boolean} lowerInclusive - if true, run lower check as >= instead of >\n * @param  {Boolean} upperInclusive - if true, run upper check as <= instead of <\n */\nTA.prototype.isInRange = function(config) {\n  // TODO: would be fantastic to use isLessThan and isGreaterThan instead\n  var self = this;\n  this.queue.add(function() {\n    var lower = getUnitlessMeasurement(config.lower);\n    var upper = getUnitlessMeasurement(config.upper);\n    var lowerInclusive = config.lowerInclusive || true;\n    var upperInclusive = config.upperInclusive || true;\n\n    // just in case someone screws up the order\n    if (lower > upper) {\n      var temp = lower;\n      lower = upper;\n      upper = temp;\n    };\n\n    if (typeof lower !== 'number' || typeof upper !== 'number') {\n      self.onerror(\"“isInRange” needs an upper and a lower value in its config object.\");\n      throw new Error();\n    }\n\n    var xIsLessThan = function() {};\n    switch (upperInclusive) {\n      case true:\n        xIsLessThan = function(target) {\n          var isInRange = false;\n          if (getUnitlessMeasurement(target.value) <= getUnitlessMeasurement(upper)) {\n            isInRange = true;\n          }\n          if (!isInRange) {\n            self.onincorrect(target.value + ' is not less than ' + upper);\n          }\n          return isInRange;\n        };\n        break;\n      default:\n        xIsLessThan = function(target) {\n          var isInRange = false;\n          if (getUnitlessMeasurement(target.value) < getUnitlessMeasurement(upper)) {\n            isInRange = true;\n          }\n          if (!isInRange) {\n            self.onincorrect(target.value + ' is not less than ' + upper);\n          }\n          return isInRange;\n        };\n        break;\n    }\n\n    var xIsGreaterThan = function() {};\n    switch (lowerInclusive) {\n      case true:\n        xIsGreaterThan = function(target) {\n          var isInRange = false;\n          if (getUnitlessMeasurement(target.value) >= getUnitlessMeasurement(lower)) {\n            isInRange = true;\n          }\n          if (!isInRange) {\n            self.onincorrect(target.value + ' is not greater than ' + lower);\n          }\n          return isInRange;\n        };\n        break;\n      default:\n        xIsGreaterThan = function(target) {\n          var isInRange = false;\n          if (getUnitlessMeasurement(target.value) > getUnitlessMeasurement(lower)) {\n            isInRange = true;\n          }\n          if (!isInRange) {\n            self.onincorrect(target.value + ' is not greater than ' + lower);\n          }\n          return isInRange;\n        };\n        break;\n    }\n\n    var inRangeFunc = function(target) {\n      var isInRange = false;\n      if (xIsLessThan(target) && xIsGreaterThan(target)) {\n        isInRange = true;\n      }\n      return isInRange;\n    };\n\n    var testResult = self.gradebook.grade({\n      callback: inRangeFunc,\n      not: self.gradeOpposite,\n      strictness: self.strictness\n    });\n    self.onresult(testResult);\n  });\n};\n\n/**\n * Check that the value includes at least one of the given expected values.\n * @param  {Array} expectedValues - search for one of the values in the array using regex\n * @param  {Object} config - includes: nValues, minValues, maxValues. Designate the number of values in expectedValues expected to be found in the target value. Defaults to at least one value needs to be found.\n * @return {object} result - the GradeBook’s list of questions and overall correctness.\n */\nTA.prototype.hasSubstring = function(config) {\n  var self = this;\n  this.queue.add(function() {\n    config = config || '';\n    var expectedValues = config.expected;\n\n    // this simplifies JSON syntax\n    if (typeof config === 'string' || config instanceof Array) {\n      expectedValues = config;\n    }\n\n    // make sure expectedValues are an array\n    if (!(expectedValues instanceof Array)) {\n      expectedValues = [expectedValues];\n    };\n\n    var nValues      = config.nValues || false;\n    var minValues    = config.minValues || 1;\n    var maxValues    = config.maxValues || expectedValues.length;\n\n    if (!expectedValues || expectedValues.length === 0) {\n      self.onerror('“hasSubstring” needs at least one regex comparison.');\n      throw new Error();\n    };\n\n    if (typeof minValues !== 'number' || typeof maxValues !== 'number') {\n      self.onerror('“hasSubstring” “minValue” and “maxValue” need to be numbers.');\n      throw new Error();\n    };\n\n    /**\n     * Is there a substring in a string? This will answer that question.\n     * @param  {object} target - the Target in question\n     * @return {boolean} - whether or not expected substring is in target.value\n     */\n    var substringFunc = function(target) {\n      var hasNumberOfValsExpected = false;\n      var hits = 0;\n      expectedValues.forEach(function(val) {\n        var matches = target.value.match(new RegExp(val)) || [];\n        if (matches.length > 0) {\n          hits += 1;\n        } else {\n          self.onincorrect(val + ' did not hit against ' + target.value.slice(0, 20));\n        }\n      });\n\n      if (nValues) {\n        (hits === nValues) ? hasNumberOfValsExpected = true : hasNumberOfValsExpected = false;\n      } else if (hits >= minValues && hits <= maxValues) {\n        hasNumberOfValsExpected = true;\n      };\n\n      return hasNumberOfValsExpected;\n    };\n\n    var testResult = self.gradebook.grade({\n      callback: substringFunc,\n      not: self.gradeOpposite,\n      strictness: self.strictness\n    });\n    self.onresult(testResult);\n  });\n};\n\n// get all the exposed methods so that the translator knows what’s acceptable\nvar taAvailableMethods = Object.getOwnPropertyNames(TA.prototype).filter(function(key) {\n  return key.indexOf('_') === -1 && key !== 'constructor';\n});\n\nTA.prototype._translateConfigToMethods = function(config) {\n  var self = this;\n  // return an array of anonymous functions that are closed over this scope.\n  var methods = [];\n\n  // so either nodes or elements works in config object\n  config['nodes'] = config['nodes'] || config['elements'];\n\n  var definitions = Object.keys(config);\n\n  methods = definitions.map(function(method) {\n    return function() {\n      try {\n        self[method](config[method]);\n      } catch (e) {\n        self.onerror('Method “' + method + '” did not execute. ' + e);\n        throw new Error();\n      }\n    };\n  });\n\n  return methods;\n};\n\n// TAReporters.js<js> ends here\n"
  },
  {
    "path": "src/js/Target.js",
    "content": "/**\n * @fileOverview Targets are:\n *  • nested into a tree-like structure called a bullseye\n *  • usually mapped 1:1 with DOM elements\n *\n *  The top-level target living directly on the TA will not map to any element. But it contains children which do map 1:1 with elements.\n * @name Target.js<GE>\n * @author Cameron Pittman\n * @license GPLv3\n */\n\n/**\n * Target constructor sets the target defaults. It includes a unique id number for private tracking.\n */\nfunction Target() {\n  this.id = parseInt(Math.random() * 1000000);\n  this.element = null;\n  this.value = null;\n  this.operation = null;\n  this.children = [];\n  this.index = null;\n  this.correct = false;\n};\n\nObject.defineProperties(Target.prototype, {\n  hasChildren: {\n    /**\n     * Public method for determining if a Target has child Targets.\n     * @return {Boolean} hasKids - true if there are chldren, false otherwise.\n     */\n    get: function() {\n      var hasKids = false;\n      if (this.children.length > 0) {\n        hasKids = true;\n      };\n      return hasKids;\n    }\n  },\n  hasValue: {\n    /**\n     * Public method for determining if a value exists on a Target.\n     * @return {Boolean} somethingThere - true if a value exists, false otherwise.\n     */\n    get: function() {\n      var somethingThere = false;\n      if (this.value !== null && this.value !== undefined) {\n        somethingThere = true;\n      };\n      return somethingThere;\n    }\n  },\n  hasGrandkids: {\n    /**\n     * Public method for determining if a Target’s children have children.\n     * @return {Boolean} hasGrandKids - true if there are grandchildren, false otherwise.\n     */\n    get: function() {\n      var gotGrandKids = false;\n      gotGrandKids = this.children.some(function (kid) {\n        return kid.hasChildren;\n      });\n      return gotGrandKids;\n    }\n  }\n});\n\n// Target.js<js> ends here\n"
  },
  {
    "path": "src/js/helpers.js",
    "content": "/**\n * @fileOverview This file contains helpers for the Grading Engine.\n * @name helpers.js<js>\n * @author Cameron Pittman\n * @license GPLv3\n */\n\n// http://stackoverflow.com/questions/7837456/comparing-two-arrays-in-javascript\nfunction arrEquals(array1, array2) {\n  if (!array1 || !array2) {\n    return false;\n  }\n  if (array1.length != array2.length) {\n    return false;\n  }\n  for (var i = 0, l = array1.length; i < l; i++) {\n    if (array1[i] instanceof Array && array2[i] instanceof Array) {\n      if (!array1[i].equals(array2[i])) {\n        return false;\n      }\n    } else if (array1[i] != array2[i]) {\n      // Warning - two different object instances will never be equal: {x:20} != {x:20}\n      return false;\n    }\n  }\n  return true;\n}\n\n/**\n * Creates an Array of DOM nodes that match the selector\n * @param selector {string} CSS selector - selector to match against\n * @param  {DOM node} parent - parent for starting point\n * @return {array} Array of DOM nodes\n */\nfunction getDomNodeArray(selector, parent) {\n  if (!selector) {\n    return [];\n  }\n  parent = parent || document;\n  var nodes = Array.prototype.slice.apply(parent.querySelectorAll(selector));\n  return nodes;\n}\n\n// modified from http://stackoverflow.com/questions/7960335/javascript-is-given-function-empty\nFunction.prototype.getBody = function() {\n  // Get content between first { and last }\n  var m = this.toString().match(/\\{([\\s\\S]*)\\}/m)[1];\n  // strip whitespace http://stackoverflow.com/questions/14540094/javascript-regular-expression-for-removing-all-spaces-except-for-what-between-do\n  m = m.replace(/([^\"]+)|(\"[^\"]+\")/g, function($0, $1, $2) {\n    if ($1) {\n      return $1.replace(/\\s/g, '');\n    } else {\n      return $2;\n    }\n  });\n  // Strip comments\n  return m.replace(/^\\s*\\/\\/.*$/mg, '');\n};\n\n// http://stackoverflow.com/questions/359788/how-to-execute-a-javascript-function-when-i-have-its-name-as-a-string\n// Use only if necessary...\nfunction executeFunctionByName(functionName, context) {\n  var args = [].slice.call(arguments).splice(2);\n  var namespaces = functionName.split('.');\n  var func = namespaces.pop();\n  for (var i = 0; i < namespaces.length; i++) {\n    context = context[namespaces[i]];\n  }\n  return context[func].apply(this, args);\n}\n\n/**\n * Get the actual number from a measurement.\n * @param  {String} measurement - the measurement to strip\n * @return {Number} - the number inside\n */\nfunction getUnitlessMeasurement(measurement) {\n  if (typeof measurement === 'number') {\n    return measurement;\n  } else if (typeof measurement === 'string') {\n    return measurement.match(/\\d+/g)[0];\n  } else {\n    return NaN;\n  }\n}\n\n// helper.js<js> ends here\n"
  },
  {
    "path": "src/js/intro.js",
    "content": "/**\n * @fileOverview Udacity’s library for immediate front-end feedback.\n * @name intro.js<js>\n * @author Cameron Pittman\n * @license GPLv3\n */\n\n/**\n * Exposes UdacityFEGradingEngine (Grading Engine) interface\n * @return {Object} exports - the functions on the exports object\n */\n;window.UdacityFEGradingEngine ? window.UdacityFEGradingEngine = window.UdacityFEGradingEngine : window.UdacityFEGradingEngine = (function(window, undefined) {\n  'use strict';\n  var exports = {};\n\n// intro.js<js> ends here\n"
  },
  {
    "path": "src/js/outro.js",
    "content": "/**\n * @fileOverview This file contains the closing statements of the Grading Engine.\n * @name outro.js<js>\n * @author Cameron Pittman\n * @license GPLv3\n */\n/* jshint ignore:start */\nreturn exports;\n}(window));\nwindow.dispatchEvent(new CustomEvent('GE-on', {detail: true}));\n/* jshint ignore:end */\n\n// outro<js>.js ends here\n// GE.js ends here\n"
  },
  {
    "path": "src/js/registrar.js",
    "content": "/*global testWidget, Suite, testResults */\n\n/**\n * @fileOverview  Expose functions that create and monitor tests.\n * @name registrar.js<js>\n * @author Cameron Pittman\n * @author Etienne Prud’homme\n * @license GPLv3\n */\n\nvar numberOfTests = 0,\n    registeredTests = 0;\n/*\n The hotel simply changes the attributes on each web component\n */\nvar hotel = {\n  occupiedSuites: [],\n  createSuite: function (rawSuite) {\n    var suite = new Suite(rawSuite);\n\n    // pass the whole suite to the testResults so you can modify it there later.\n    suite.element = testResults.buildSuiteElement(suite);\n    this.occupiedSuites.push(suite);\n    return suite;\n  }\n};\n\nObject.defineProperties(hotel, {\n  numberOfPassedSuites: {\n    get: function () {\n      var numberPassed = 0;\n      this.occupiedSuites.forEach(function (suite) {\n        if (suite.suitePassed) {\n          numberPassed += 1;\n        }\n      });\n      return numberPassed;\n    }\n  },\n  numberOfSuites: {\n    get: function () {\n      return this.occupiedSuites.length;\n    }\n  },\n  allCorrect: {\n    get: function () {\n      var allCorrect = (this.numberOfSuites === this.numberOfPassedSuites);\n      // TODO: maybe emit an event if all of them pass?\n      return allCorrect;\n    }\n  }\n});\n\n/**\n * Register a suite of tests with the grading engine.\n * @param  {Object} _suite - contains a test’s name and code to display upon completion.\n * @return {Function} registerTest - a method to register a single test with the grading engine.\n */\nfunction registerSuite(rawSuite) {\n  var self = this;\n\n  var newSuite = hotel.createSuite(rawSuite);\n\n  /**\n   * Register a new test on a specific suite. The test will contain an activeTest. Each active test much return a boolean called isCorrect and an array of the targets in question.\n   * @param  {Object} _test - contains a description, activeTest and flags.\n   * @return {Object} self - for chaining tests registrations together (if you’re into that sort of syntax.)\n   */\n  function registerTest(_test) {\n    newSuite.createTest({\n      description: _test.description,\n      definition: _test.definition,\n      flags: _test.flags\n    });\n    return self;\n  }\n  return {\n    registerTest: registerTest\n  };\n}\n\nvar userData = [];\nvar isOn = false;\n\nfunction startTests() {\n\n  userData.forEach(function(_suite) {\n    numberOfTests += _suite.tests.length;\n  });\n\n  return new Promise(function(resolve, reject) {\n    userData.forEach(function (_suite) {\n      var newSuite = registerSuite({\n        name: _suite.name,\n        code: _suite.code\n      });\n      _suite.tests.forEach(function (test) {\n        registeredTests++;\n\n        // console.log('test number: ', registeredTests);\n        try {\n          newSuite.registerTest({\n            description: test.description,\n            definition: test.definition,\n            flags: test.flags\n          });\n        } catch(e) {\n          console.warn(e.message);\n        }\n      });\n    });\n  });\n}\n\n/**\n * For use only when loading a new JSON with user data about the tests they want to run\n * @param  {JSON} suitesJSON Everything the GE needs to know about your tests\n */\nfunction registerSuites(suitesJSON) {\n  try {\n    if (suitesJSON.length > 0) {\n      userData = JSON.parse(suitesJSON);\n    }\n  } catch (e) {\n    throw new Error('Invalid JSON format.');\n  }\n  if (userData instanceof Array !== true) {\n    throw new TypeError('Invalid test format. Tests must be wrapped in an array.');\n  }\n  if (isOn) {\n    startTests();\n    // console.log('startTests');\n  }\n}\n\nfunction turnOn() {\n  if (!isOn) {\n    testWidget.buildWidget().then(function() {\n      isOn = true;\n      // console.log('enters startTests');\n      startTests();\n\n      if(registeredTests === numberOfTests) {\n        window.dispatchEvent(new CustomEvent('tests-registered', {\n          numberOfTests: numberOfTests\n        }));\n      }\n      // console.log('registeredTests = ', registeredTests);\n      // console.log('numberOfTests = ', numberOfTests);\n      // console.log('leaves startTests');\n    });\n  }\n}\n\nfunction turnOff () {\n  hotel.occupiedSuites.forEach(function (suite) {\n    suite.activeTests.forEach(function (activeTest) {\n      activeTest.stopTest();\n    });\n  });\n  hotel.occupiedSuites = [];\n  testWidget.killWidget();\n  isOn = false;\n}\n\nfunction debug() {\n  hotel.occupiedSuites.forEach(function (suite) {\n    suite.getDebugData();\n    suite.getIncorrectInfo();\n    suite.getValues();\n  });\n}\n\nexports.debug = debug;\nexports.turnOn = turnOn;\nexports.turnOff = turnOff;\nexports.registerSuites = registerSuites;\n\n// registrar.js<js> ends here\n"
  }
]