<commit_before>/* eslint-disable max-len */
/* globals i18next */

const template = document.createElement('template');
const notification = i18next.t('notification.editorPreferencesMsg');
const prefs_and_content = i18next.t('properties.prefs_and_content');
const prefs_only = i18next.t('properties.prefs_only');
const no_prefs_or_content = i18next.t('properties.no_prefs_or_content');
const remember_this_choice = i18next.t('tools.remember_this_choice');
const remember_this_choice_title = i18next.t('notification.remember_this_choice_title');
const ok = i18next.t('common.ok');
const cancel = i18next.t('common.cancel');
template.innerHTML = `

  <elix-dialog id="dialog_box" aria-label="SVG-Edit storage preferences" closed>

          ${notification}

        <select id="se-storage-pref">
          <option value="prefsAndContent">${prefs_and_content}</option>
          <option value="prefsOnly">${prefs_only}</option>
          <option value="noPrefsOrContent">${no_prefs_or_content}</option>
        </select>

        ${remember_this_choice}<input type="checkbox" id="se-remember" value="" checked>

        <button id="storage_ok">

          ${ok}
        </button>
        <button id="storage_cancel">

          ${cancel}
        </button>

  </elix-dialog>
`;
/**
 * @class SeStorageDialog
 */
export class SeStorageDialog extends HTMLElement {
  /**
    * @function constructor
    */
  constructor () {
    super();
    // create the shadowDom and insert the template
    this._shadowRoot = this.attachShadow({ mode: 'open' });
    this._shadowRoot.append(template.content.cloneNode(true));
    this.$dialog = this._shadowRoot.querySelector('#dialog_box');
    this.$storage = this._shadowRoot.querySelector('#js-storage');
    this.$okBtn = this._shadowRoot.querySelector('#storage_ok');
    this.$cancelBtn = this._shadowRoot.querySelector('#storage_cancel');
    this.$storageInput = this._shadowRoot.querySelector('#se-storage-pref');
    this.$rememberInput = this._shadowRoot.querySelector('#se-remember');
  }
  /**
   * @function observedAttributes
   * @returns {any} observed
   */
  static get observedAttributes () {
    return [ 'dialog', 'storage' ];
  }
  /**
   * @function attributeChangedCallback
   * @param {string} name
   * @param {string} oldValue
   * @param {string} newValue
   * @returns {void}
   */
  attributeChangedCallback (name, oldValue, newValue) {
    switch (name) {
    case 'dialog':
      if (newValue === 'open') {
        this.$dialog.open();
      } else {
        this.$dialog.close();
      }
      break;
    case 'storage':
      if (newValue === 'true') {
        this.$storageInput.options[0].disabled = false;
      } else {
        this.$storageInput.options[0].disabled = true;
      }
      break;
    default:
      // super.attributeChangedCallback(name, oldValue, newValue);
      break;
    }
  }
  /**
   * @function get
   * @returns {any}
   */
  get dialog () {
    return this.getAttribute('dialog');
  }
  /**
   * @function set
   * @returns {void}
   */
  set dialog (value) {
    this.setAttribute('dialog', value);
  }
  /**
   * @function connectedCallback
   * @returns {void}
   */
  connectedCallback () {
    const onSubmitHandler = (e, action) => {
      const triggerEvent = new CustomEvent('change', { detail: {
        trigger: action,
        select: this.$storageInput.value,
        checkbox: this.$rememberInput.checked
      } });
      this.dispatchEvent(triggerEvent);
    };
    this.$okBtn.addEventListener('click', (evt) => onSubmitHandler(evt, 'ok'));
    this.$cancelBtn.addEventListener('click', (evt) => onSubmitHandler(evt, 'cancel'));
  }
  /**
 * Sets SVG content as a string with "svgedit-" and the current
 *   canvas name as namespace.
 * @param {string} val
 * @returns {void}
 */
  setSVGContentStorage (val) {
    if (this.storage) {
      const name = 'svgedit-' + this.configObj.curConfig.canvasName;
      if (!val) {
        this.storage.removeItem(name);
      } else {
        this.storage.setItem(name, val);
      }
    }
  }
}

// Register
customElements.define('se-storage-dialog', SeStorageDialog);
<commit_msg>#98 storage title issue fixed<commit_after>/* eslint-disable max-len */
/* globals i18next */

const template = document.createElement('template');
const notification = i18next.t('notification.editorPreferencesMsg');
const prefs_and_content = i18next.t('properties.prefs_and_content');
const prefs_only = i18next.t('properties.prefs_only');
const no_prefs_or_content = i18next.t('properties.no_prefs_or_content');
const remember_this_choice = i18next.t('tools.remember_this_choice');
const remember_this_choice_title = i18next.t('tools.remember_this_choice_title');
const ok = i18next.t('common.ok');
const cancel = i18next.t('common.cancel');
template.innerHTML = `

  <elix-dialog id="dialog_box" aria-label="SVG-Edit storage preferences" closed>

          ${notification}

        <select id="se-storage-pref">
          <option value="prefsAndContent">${prefs_and_content}</option>
          <option value="prefsOnly">${prefs_only}</option>
          <option value="noPrefsOrContent">${no_prefs_or_content}</option>
        </select>

        ${remember_this_choice}<input type="checkbox" id="se-remember" value="" checked>

        <button id="storage_ok">

          ${ok}
        </button>
        <button id="storage_cancel">

          ${cancel}
        </button>

  </elix-dialog>
`;
/**
 * @class SeStorageDialog
 */
export class SeStorageDialog extends HTMLElement {
  /**
    * @function constructor
    */
  constructor () {
    super();
    // create the shadowDom and insert the template
    this._shadowRoot = this.attachShadow({ mode: 'open' });
    this._shadowRoot.append(template.content.cloneNode(true));
    this.$dialog = this._shadowRoot.querySelector('#dialog_box');
    this.$storage = this._shadowRoot.querySelector('#js-storage');
    this.$okBtn = this._shadowRoot.querySelector('#storage_ok');
    this.$cancelBtn = this._shadowRoot.querySelector('#storage_cancel');
    this.$storageInput = this._shadowRoot.querySelector('#se-storage-pref');
    this.$rememberInput = this._shadowRoot.querySelector('#se-remember');
  }
  /**
   * @function observedAttributes
   * @returns {any} observed
   */
  static get observedAttributes () {
    return [ 'dialog', 'storage' ];
  }
  /**
   * @function attributeChangedCallback
   * @param {string} name
   * @param {string} oldValue
   * @param {string} newValue
   * @returns {void}
   */
  attributeChangedCallback (name, oldValue, newValue) {
    switch (name) {
    case 'dialog':
      if (newValue === 'open') {
        this.$dialog.open();
      } else {
        this.$dialog.close();
      }
      break;
    case 'storage':
      if (newValue === 'true') {
        this.$storageInput.options[0].disabled = false;
      } else {
        this.$storageInput.options[0].disabled = true;
      }
      break;
    default:
      // super.attributeChangedCallback(name, oldValue, newValue);
      break;
    }
  }
  /**
   * @function get
   * @returns {any}
   */
  get dialog () {
    return this.getAttribute('dialog');
  }
  /**
   * @function set
   * @returns {void}
   */
  set dialog (value) {
    this.setAttribute('dialog', value);
  }
  /**
   * @function connectedCallback
   * @returns {void}
   */
  connectedCallback () {
    const onSubmitHandler = (e, action) => {
      const triggerEvent = new CustomEvent('change', { detail: {
        trigger: action,
        select: this.$storageInput.value,
        checkbox: this.$rememberInput.checked
      } });
      this.dispatchEvent(triggerEvent);
    };
    this.$okBtn.addEventListener('click', (evt) => onSubmitHandler(evt, 'ok'));
    this.$cancelBtn.addEventListener('click', (evt) => onSubmitHandler(evt, 'cancel'));
  }
  /**
 * Sets SVG content as a string with "svgedit-" and the current
 *   canvas name as namespace.
 * @param {string} val
 * @returns {void}
 */
  setSVGContentStorage (val) {
    if (this.storage) {
      const name = 'svgedit-' + this.configObj.curConfig.canvasName;
      if (!val) {
        this.storage.removeItem(name);
      } else {
        this.storage.setItem(name, val);
      }
    }
  }
}

// Register
customElements.define('se-storage-dialog', SeStorageDialog);
<|endoftext|>


<commit_before>/* jslint node: true */
/* global before, afterEach, after, featureFile, scenarios, steps */
"use strict";

var webdriver = require('selenium-webdriver');

var Yadda = require('yadda');
var path = require('path');
Yadda.plugins.mocha.AsyncStepLevelPlugin.init();

var library = require('./AddPlayer');
var fs = require('fs');

// checking sauce credential
if(!process.env.SAUCE_USERNAME || !process.env.SAUCE_ACCESS_KEY){
    console.warn(
        '\nPlease configure your sauce credential:\n\n' +
        'export SAUCE_USERNAME=<SAUCE_USERNAME>\n' +
        'export SAUCE_ACCESS_KEY=<SAUCE_ACCESS_KEY>\n\n'
    );
    throw new Error("Missing sauce credentials");
}

var desired = JSON.parse(process.env.DESIRED || '{browserName: "chrome"}');
desired.name = 'example with ' + desired.browserName;
desired.tags = ['Add Player'];
var driver;

//creating a path that works for locations, Yaddas calls is not as good as node's require and you need
//to be in the folder itself
var featureFilePath = path.resolve(__dirname, '../features/AddPlayer.feature');
featureFile(featureFilePath, function(feature) {

    var allPassed = true;

    before(function(done) {
        var username = process.env.SAUCE_USERNAME;
        var accessKey = process.env.SAUCE_ACCESS_KEY;
        desired.username = username;
        desired.accessKey = accessKey;

        var remoteUrl = "http://ondemand.saucelabs.com:80/wd/hub";
        driver = new webdriver.Builder().usingServer(remoteUrl).withCapabilities(desired).build();
        driver.manage().timeouts().implicitlyWait(10000);
        done();
    });

    afterEach(function(done) {
        //takeScreenshotOnFailure(this.currentTest);
        allPassed = allPassed && (this.currentTest.state === 'passed');
        done();
    });

    after(function(done) {
        // ensure a clean environment
        // clear down the players storage using our API.  Let's try this out but I'm not feeling that great about this.
        // Known as going in through the front door
        // But we are enacting the principle: Simplicity -- the art of maximising the work not done
        // we should be in a state of preparedness to make the refactoring if and when needed
        // maybe a feature request for Yadda here.  Maybe we pull down the Yadda code and submit a code change ourselves!

        var Pms = require('../../../lib/PlayerManagementService'); // The library that you wish to test
        var pms = new Pms();
	    pms.Open(null, null);
        pms.DeletePlayers(function(err) {
            if (err)
                console.log('Error in deleting %s', err);
            driver
                .quit()
                .then(done);
        });
    });

    scenarios(feature.scenarios, function(scenario) {
        steps(scenario.steps, function(step, done) {
            executeInFlow(function() {

                var interpreter_context = { teamname: null, year: null, driver: driver };
                new Yadda.Yadda(library, interpreter_context).yadda(step);

            }, done);
        });
    });

});

function executeInFlow(fn, done) {
    webdriver.promise.controlFlow().execute(fn).then(function() {
        done();
    }, done);
}

function takeScreenshotOnFailure(test) {
    if (test.status != 'passed') {

        var scrpath = path.resolve(__dirname, 'screenshots/') + test.title.replace(/\W+/g, '_').toLowerCase() + '.png';
        driver.takeScreenshot().then(function(data) {
            fs.writeFileSync(scrpath, data, 'base64');
        });
    }
}<commit_msg>Readying Saucelabs integration<commit_after>/* jslint node: true */
/* global before, afterEach, after, featureFile, scenarios, steps */
"use strict";

var webdriver = require('selenium-webdriver');

var Yadda = require('yadda');
var path = require('path');
Yadda.plugins.mocha.AsyncStepLevelPlugin.init();

var library = require('./AddPlayer');
var fs = require('fs');

// checking sauce credential
if(!process.env.SAUCE_USERNAME || !process.env.SAUCE_ACCESS_KEY){
    console.warn(
        '\nPlease configure your sauce credential:\n\n' +
        'export SAUCE_USERNAME=<SAUCE_USERNAME>\n' +
        'export SAUCE_ACCESS_KEY=<SAUCE_ACCESS_KEY>\n\n'
    );
    throw new Error("Missing sauce credentials");
}

var desired = JSON.parse(process.env.DESIRED || '{browserName: "chrome"}');
desired.name = 'example with ' + desired.browserName;
desired.tags = ['Add Player'];
var driver;

//creating a path that works for locations, Yaddas calls is not as good as node's require and you need
//to be in the folder itself
var featureFilePath = path.resolve(__dirname, '../features/AddPlayer.feature');
featureFile(featureFilePath, function(feature) {

    var allPassed = true;

    before(function(done) {
        var username = process.env.SAUCE_USERNAME;
        var accessKey = process.env.SAUCE_ACCESS_KEY;
        desired.username = username;
        desired.accessKey = accessKey;

        var remoteUrl = "http://ondemand.saucelabs.com:80/wd/hub";
        driver = new webdriver.Builder().usingServer(remoteUrl).withCapabilities(desired).build();
        driver.manage().timeouts().implicitlyWait(10000);
        done();
    });

    afterEach(function(done) {
        //takeScreenshotOnFailure(this.currentTest);
        allPassed = allPassed && (this.currentTest.state === 'passed');
        done();
    });

    after(function(done) {
        // ensure a clean environment
        // clear down the players storage using our API.  Let's try this out but I'm not feeling that great about this.
        // Known as going in through the front door
        // But we are enacting the principle: Simplicity -- the art of maximising the work not done
        // we should be in a state of preparedness to make the refactoring if and when needed
        // maybe a feature request for Yadda here.  Maybe we pull down the Yadda code and submit a code change ourselves!

        var Pms = require('../../../lib/PlayerManagementService'); // The library that you wish to test
        var pms = new Pms();
	    pms.Open(null, null);
        pms.DeletePlayers(function(err) {
            if (err)
                console.log('Error in deleting %s', err);
            driver
                .quit()
                .then(done);
        });
    });

    scenarios(feature.scenarios, function(scenario) {
        steps(scenario.steps, function(step, done) {
            executeInFlow(function() {

                var interpreter_context = { teamname: null, year: null, driver: driver };
                new Yadda.Yadda(library, interpreter_context).yadda(step);

            }, done);
        });
    });

});

function executeInFlow(fn, done) {
    webdriver.promise.controlFlow().execute(fn).then(function() {
        done();
    }, done);
}

function takeScreenshotOnFailure(test) {
    if (test.status != 'passed') {

        var scrpath = path.resolve(__dirname, 'screenshots/') + test.title.replace(/\W+/g, '_').toLowerCase() + '.png';
        driver.takeScreenshot().then(function(data) {
            fs.writeFileSync(scrpath, data, 'base64');
        });
    }
}
<|endoftext|>


<commit_before>// @name         Pogdesign-Widgets.require
// @namespace    https://github.com/fabiencrassat
// @version      1.0.0
// @description  Add the core object for the Pogdesign-Widgets.user.js
// @author       Fabien Crassat <fabien@crassat.com>

/*global $, fabiencrassat */
"use strict";

function checkProtocol() {
    if (location.protocol === "http:") {
        window.location.replace("https:" + window.location.href.substring(5));
    }
}
checkProtocol();

var tools = function() {
    function addZeroToOneNumber(number) {
        if (number.length < 2) { number = "0" + number; }
        return number;
    }
    function getPixelStyle(key, value) {
        if (key && value) {
            return " " + key + ": " + value + "px;";
        }
        return "";
    }

    return {
        addZeroToOneNumber,
        getPixelStyle
    };
};

var model = function() {
    var tools = fabiencrassat.tools;

    var show = {
        title: "",
        season: "",
        episode: "",
        getTitle() { return show.title; },
        setTitle(title) { show.title = title; },
        getSeason() { return show.season; },
        setSeason(season) {
            show.season = tools.addZeroToOneNumber(season);
        },
        getEpisode() { return show.episode; },
        setEpisode(episode) {
            show.episode = tools.addZeroToOneNumber(episode);
        },
        getSeasonAndEpisode() { return "S" + show.getSeason() + "E" + show.getEpisode(); },
        setSeasonAndEpisode() {
            if (arguments.length === 1) {
                var regex = /^s(\d{1,})e(\d{1,})/gi;
                show.setSeason(arguments[0].replace(regex, "$1"));
                show.setEpisode(arguments[0].replace(regex, "$2"));
                return;
            }
            if (arguments.length === 2) {
                show.setSeason(arguments[0]);
                show.setEpisode(arguments[1]);
                return;
            }
            throw new RangeError("Exception in setSeasonAndEpisode");
        },

        getSearch() {
            return show.getTitle().replace(/ /gm, ".") + "." + show.getSeasonAndEpisode();
        }
    };

    return {
        show: {
            getSearch: show.getSearch,
            getTitle: show.getTitle,
            setTitle: show.setTitle,
            getSeason: show.getSeason,
            getSeasonAndEpisode: show.getSeasonAndEpisode,
            setSeasonAndEpisode: show.setSeasonAndEpisode
        }
    };
};

var view = function() {
    var tools = fabiencrassat.tools;
    var show = fabiencrassat.model.show;

    var popup = {
        links: [
            {name: "Streaming",
                sites : [
                    {name: "google",
                        icon: "",
                        url() { return "https://www.google.fr/search?q=" + show.getSearch() + "+vostfr+streaming"; }
                    }
                ]
            },
            {name: "Download",
                sites: [
                    {name: "google",
                        icon: "",
                        url() { return "https://www.google.fr/search?q=" + show.getSearch() + "+direct+download"; }
                    },
                    {name: "yourserie",
                        icon: "",
                        url() { return "http://www.yourserie.com/?s=" + show.getTitle() + "+season+" + show.getSeason(); }
                    },
                    {name: "binsearch",
                        icon: "",
                        url() { return "https://binsearch.info/?q=" + show.getSearch(); }
                    }
                ]
            },
            {name: "Subtitle",
                sites : [
                    {name: "subscene",
                        icon: "",
                        url() { return "https://subscene.com/subtitles/release?q=" + show.getSearch(); }
                    }
                ]
            }
        ],
        getLinks() {
            var links = "";
            for (var i = 0; i < this.links.length; i++) {
                links += this.links[i].name + ": ";
                for (var j = 0; j < this.links[i].sites.length; j++) {
                    if (j !== 0) {
                        links += " | ";
                    }
                    links += "" + this.links[i].sites[j].name + "";
                }
                links += "
";
            }
            links += "";
            return links;
        },

        popupId: "fcr-external-links-element",
        getContainer() {
            return $("#" + popup.popupId);
        },
        close() {
            var container = popup.getContainer();
            if(container) {
                container.remove();
            }
        },
        removeOnOutsideClickEvent() {
            $(document).mouseup(function (event) {
                var container = popup.getContainer();
                if (!container.is(event.target) &&          // if the target of the click isn't the container
                container.has(event.target).length === 0) { // nor a descendant of the container
                    container.remove();
                }
            });
        },
        create(element, cssClass, cssDisplay, top, left) {
            var result = `
            <div id='` + popup.popupId + `'
            style='position: absolute; width: 350px; z-index: 97; display: ` + cssDisplay + ";" + tools.getPixelStyle("top", top) + tools.getPixelStyle("left", left) + `'
            class='cluetip ui-widget ui-widget-content ui-cluetip clue-right-default cluetip-default ` + cssClass + `'>

                    X
                    ` + show.getTitle() + " " + show.getSeasonAndEpisode() + `

` + popup.getLinks() + `

` + show.getSearch() + `

`;
            return(result);
        }
    };

    return {
        externalLinks : {
            removeOnOutsideClickEvent: popup.removeOnOutsideClickEvent,
            close: popup.close,
            create: popup.create
        }
    };
};

var main = function() {
    var externalLinks = fabiencrassat.view.externalLinks;
    var show = fabiencrassat.model.show;

    var page = {
        controller: {
            insertStylesheets(stylesheets) {
                var style = document.createElement("style");
                style.appendChild(document.createTextNode(stylesheets));
                (document.body || document.head || document.documentElement).appendChild(style);
            },
            extractTitle(pageElement, element) {
                var title = $.trim(pageElement.extractTitle(element));
                show.setTitle(title);
            },
            extractSeasonAndEpisode(pageElement, element) {
                var seasonAndEpisode = pageElement.extractSeasonAndEpisode(element);
                if (typeof seasonAndEpisode === "string") {
                    show.setSeasonAndEpisode(seasonAndEpisode);
                    return;
                }
                show.setSeasonAndEpisode(seasonAndEpisode.season, seasonAndEpisode.episode);
            },
            extractShow(pageElement, element) {
                page.controller.extractTitle(pageElement, element);
                page.controller.extractSeasonAndEpisode(pageElement, element);
            },
            getExternalLinksPopup(pageElement, element) {
                page.controller.extractShow(pageElement, element);
                pageElement.displayExternalLinksPopup(element);
            },
            loadClickEventOnLinkElement(pageElement) {
                $("." + page.shared.externalLinksLinkClass).on("click", function(event) {
                    event.preventDefault();
                    externalLinks.close();
                    page.controller.getExternalLinksPopup(pageElement, $(this));
                });
                externalLinks.removeOnOutsideClickEvent();
            },
            isInLocationPage(regex) {
              return regex.test(window.location.href);
            },
            canAddExternalLink(isInLocationPage, element) {
                if (!isInLocationPage()) { return false; }
                if ($(element).length === 0) { return false; }
                return true;
            },
            addExternalLink(pageElement, element) {
                if (!page.controller.canAddExternalLink(pageElement.isInLocationPage, element)) { return; }
                page.controller.insertStylesheets(page.shared.stylesheets(pageElement));
                pageElement.insertExternalLink(element);
                page.controller.loadClickEventOnLinkElement(pageElement);
            }
        },
        shared: {
            linkImage: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAZdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuMTM0A1t6AAAA20lEQVQoU33RuQrCQBDG8YgHeIIHinhgZyNWgg8iCoqIpW/jg5nG0oew8b7j/wsZCSkM/Nbs7MzuuHE8z/snhlxIyhbaGEb0MMAb9myUvMAJR1xwxQEvJLCCPVsVKKGOMqqBAipIw8UTOskv0E55WHtGyRsocYYlXC3cUEQ0WTsrWS1bPKNBx9VCQSXv8MEEHZTgr2t4oGkBdKFLGAdz/cd58O4XnBFtKRN6V8tTm2tQS7pvSwjTh9tjZDENfehY7XSHbk2/immzNVT4K5A4smghGcwb0DexHHjOFwrY3c0uEFwZAAAAAElFTkSuQmCC",
            stylesheets(pageElement) {
                return `a.fcr-closePopup {
                    float: right;
                    color: #66bbff !important;
                }` + pageElement.stylesheets();
            },
            externalLinksLinkClass: "fcr-externalLinksLink",
            externalLink(classText, linkText) {
                return "" +
                        linkText +
                    "";
            },
            externalImageLink() {
                return page.shared.externalLink("fcr-externalLink-image", "");
            },
            externalTextLink() {
                return page.shared.externalLink("", "<Links>");
            }
        }
    };

    return {
        controller: {
            isInLocationPage: page.controller.isInLocationPage,
            addExternalLink: page.controller.addExternalLink
        },
        shared: {
          linkImage: page.shared.linkImage,
          externalImageLink: page.shared.externalImageLink,
          externalTextLink: page.shared.externalTextLink
        }
    };
};

var script = document.createElement("script");
script.appendChild(document.createTextNode("var fabiencrassat = fabiencrassat || {}; fabiencrassat.tools = ("+ tools +")();"));
script.appendChild(document.createTextNode("var fabiencrassat = fabiencrassat || {}; fabiencrassat.model = ("+ model +")();"));
script.appendChild(document.createTextNode("var fabiencrassat = fabiencrassat || {}; fabiencrassat.view = ("+ view +")();"));
script.appendChild(document.createTextNode("var fabiencrassat = fabiencrassat || {}; fabiencrassat.main = ("+ main +")();"));
(document.body || document.head || document.documentElement).appendChild(script);

<commit_msg>Fix encoding simple quote in the url<commit_after>// @name         Pogdesign-Widgets.require
// @namespace    https://github.com/fabiencrassat
// @version      1.0.1
// @description  Add the core object for the Pogdesign-Widgets.user.js
// @author       Fabien Crassat <fabien@crassat.com>

/*global $, fabiencrassat */
"use strict";

function checkProtocol() {
    if (location.protocol === "http:") {
        window.location.replace("https:" + window.location.href.substring(5));
    }
}
checkProtocol();

var tools = function() {
    function addZeroToOneNumber(number) {
        if (number.length < 2) { number = "0" + number; }
        return number;
    }
    function getPixelStyle(key, value) {
        if (key && value) {
            return " " + key + ": " + value + "px;";
        }
        return "";
    }
    function encodeURL(urlToEncode) {
        return encodeURIComponent(urlToEncode).replace(/'/g, '%27');
    }

    return {
        addZeroToOneNumber,
        getPixelStyle,
        encodeURL
    };
};

var model = function() {
    var tools = fabiencrassat.tools;

    var show = {
        title: "",
        season: "",
        episode: "",
        getTitle() { return show.title; },
        setTitle(title) { show.title = title; },
        getSeason() { return show.season; },
        setSeason(season) {
            show.season = tools.addZeroToOneNumber(season);
        },
        getEpisode() { return show.episode; },
        setEpisode(episode) {
            show.episode = tools.addZeroToOneNumber(episode);
        },
        getSeasonAndEpisode() { return "S" + show.getSeason() + "E" + show.getEpisode(); },
        setSeasonAndEpisode() {
            if (arguments.length === 1) {
                var regex = /^s(\d{1,})e(\d{1,})/gi;
                show.setSeason(arguments[0].replace(regex, "$1"));
                show.setEpisode(arguments[0].replace(regex, "$2"));
                return;
            }
            if (arguments.length === 2) {
                show.setSeason(arguments[0]);
                show.setEpisode(arguments[1]);
                return;
            }
            throw new RangeError("Exception in setSeasonAndEpisode");
        },

        getSearch() {
            return show.getTitle().replace(/ /gm, ".") + "." + show.getSeasonAndEpisode();
        }
    };

    return {
        show: {
            getSearch: show.getSearch,
            getTitle: show.getTitle,
            setTitle: show.setTitle,
            getSeason: show.getSeason,
            getSeasonAndEpisode: show.getSeasonAndEpisode,
            setSeasonAndEpisode: show.setSeasonAndEpisode
        }
    };
};

var view = function() {
    var tools = fabiencrassat.tools;
    var show = fabiencrassat.model.show;

    var popup = {
        links: [
            {name: "Streaming",
                sites : [
                    {name: "google",
                        icon: "",
                        url() { return "https://www.google.fr/search?q=" + tools.encodeURL(show.getSearch()) + "+vostfr+streaming"; }
                    }
                ]
            },
            {name: "Download",
                sites: [
                    {name: "google",
                        icon: "",
                        url() { return "https://www.google.fr/search?q=" + tools.encodeURL(show.getSearch()) + "+direct+download"; }
                    },
                    {name: "yourserie",
                        icon: "",
                        url() { return "http://www.yourserie.com/?s=" + tools.encodeURL(show.getTitle()) + "+season+" + tools.encodeURL(show.getSeason()); }
                    },
                    {name: "binsearch",
                        icon: "",
                        url() { return "https://binsearch.info/?q=" + tools.encodeURL(show.getSearch()); }
                    }
                ]
            },
            {name: "Subtitle",
                sites : [
                    {name: "subscene",
                        icon: "",
                        url() { return "https://subscene.com/subtitles/release?q=" + tools.encodeURL(show.getSearch()); }
                    }
                ]
            }
        ],
        getLinks() {
            var links = "";
            for (var i = 0; i < this.links.length; i++) {
                links += this.links[i].name + ": ";
                for (var j = 0; j < this.links[i].sites.length; j++) {
                    if (j !== 0) {
                        links += " | ";
                    }
                    links += "" + this.links[i].sites[j].name + "";
                }
                links += "
";
            }
            links += "";
            return links;
        },

        popupId: "fcr-external-links-element",
        getContainer() {
            return $("#" + popup.popupId);
        },
        close() {
            var container = popup.getContainer();
            if(container) {
                container.remove();
            }
        },
        removeOnOutsideClickEvent() {
            $(document).mouseup(function (event) {
                var container = popup.getContainer();
                if (!container.is(event.target) &&          // if the target of the click isn't the container
                container.has(event.target).length === 0) { // nor a descendant of the container
                    container.remove();
                }
            });
        },
        create(element, cssClass, cssDisplay, top, left) {
            var result = `
            <div id='` + popup.popupId + `'
            style='position: absolute; width: 350px; z-index: 97; display: ` + cssDisplay + ";" + tools.getPixelStyle("top", top) + tools.getPixelStyle("left", left) + `'
            class='cluetip ui-widget ui-widget-content ui-cluetip clue-right-default cluetip-default ` + cssClass + `'>

                    X
                    ` + show.getTitle() + " " + show.getSeasonAndEpisode() + `

` + popup.getLinks() + `

` + show.getSearch() + `

`;
            return(result);
        }
    };

    return {
        externalLinks : {
            removeOnOutsideClickEvent: popup.removeOnOutsideClickEvent,
            close: popup.close,
            create: popup.create
        }
    };
};

var main = function() {
    var externalLinks = fabiencrassat.view.externalLinks;
    var show = fabiencrassat.model.show;

    var page = {
        controller: {
            insertStylesheets(stylesheets) {
                var style = document.createElement("style");
                style.appendChild(document.createTextNode(stylesheets));
                (document.body || document.head || document.documentElement).appendChild(style);
            },
            extractTitle(pageElement, element) {
                var title = $.trim(pageElement.extractTitle(element));
                show.setTitle(title);
            },
            extractSeasonAndEpisode(pageElement, element) {
                var seasonAndEpisode = pageElement.extractSeasonAndEpisode(element);
                if (typeof seasonAndEpisode === "string") {
                    show.setSeasonAndEpisode(seasonAndEpisode);
                    return;
                }
                show.setSeasonAndEpisode(seasonAndEpisode.season, seasonAndEpisode.episode);
            },
            extractShow(pageElement, element) {
                page.controller.extractTitle(pageElement, element);
                page.controller.extractSeasonAndEpisode(pageElement, element);
            },
            getExternalLinksPopup(pageElement, element) {
                page.controller.extractShow(pageElement, element);
                pageElement.displayExternalLinksPopup(element);
            },
            loadClickEventOnLinkElement(pageElement) {
                $("." + page.shared.externalLinksLinkClass).on("click", function(event) {
                    event.preventDefault();
                    externalLinks.close();
                    page.controller.getExternalLinksPopup(pageElement, $(this));
                });
                externalLinks.removeOnOutsideClickEvent();
            },
            isInLocationPage(regex) {
              return regex.test(window.location.href);
            },
            canAddExternalLink(isInLocationPage, element) {
                if (!isInLocationPage()) { return false; }
                if ($(element).length === 0) { return false; }
                return true;
            },
            addExternalLink(pageElement, element) {
                if (!page.controller.canAddExternalLink(pageElement.isInLocationPage, element)) { return; }
                page.controller.insertStylesheets(page.shared.stylesheets(pageElement));
                pageElement.insertExternalLink(element);
                page.controller.loadClickEventOnLinkElement(pageElement);
            }
        },
        shared: {
            linkImage: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAZdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuMTM0A1t6AAAA20lEQVQoU33RuQrCQBDG8YgHeIIHinhgZyNWgg8iCoqIpW/jg5nG0oew8b7j/wsZCSkM/Nbs7MzuuHE8z/snhlxIyhbaGEb0MMAb9myUvMAJR1xwxQEvJLCCPVsVKKGOMqqBAipIw8UTOskv0E55WHtGyRsocYYlXC3cUEQ0WTsrWS1bPKNBx9VCQSXv8MEEHZTgr2t4oGkBdKFLGAdz/cd58O4XnBFtKRN6V8tTm2tQS7pvSwjTh9tjZDENfehY7XSHbk2/immzNVT4K5A4smghGcwb0DexHHjOFwrY3c0uEFwZAAAAAElFTkSuQmCC",
            stylesheets(pageElement) {
                return `a.fcr-closePopup {
                    float: right;
                    color: #66bbff !important;
                }` + pageElement.stylesheets();
            },
            externalLinksLinkClass: "fcr-externalLinksLink",
            externalLink(classText, linkText) {
                return "" +
                        linkText +
                    "";
            },
            externalImageLink() {
                return page.shared.externalLink("fcr-externalLink-image", "");
            },
            externalTextLink() {
                return page.shared.externalLink("", "<Links>");
            }
        }
    };

    return {
        controller: {
            isInLocationPage: page.controller.isInLocationPage,
            addExternalLink: page.controller.addExternalLink
        },
        shared: {
          linkImage: page.shared.linkImage,
          externalImageLink: page.shared.externalImageLink,
          externalTextLink: page.shared.externalTextLink
        }
    };
};

var script = document.createElement("script");
script.appendChild(document.createTextNode("var fabiencrassat = fabiencrassat || {}; fabiencrassat.tools = ("+ tools +")();"));
script.appendChild(document.createTextNode("var fabiencrassat = fabiencrassat || {}; fabiencrassat.model = ("+ model +")();"));
script.appendChild(document.createTextNode("var fabiencrassat = fabiencrassat || {}; fabiencrassat.view = ("+ view +")();"));
script.appendChild(document.createTextNode("var fabiencrassat = fabiencrassat || {}; fabiencrassat.main = ("+ main +")();"));
(document.body || document.head || document.documentElement).appendChild(script);
<|endoftext|>


<commit_before>(function() {
    var metal = {
      resource: 'metal',
      current: model.currentMetal,
      max: model.maxMetal,
      currentGain: model.metalGain,
      currentLoss: model.metalLoss,
      net: model.metalNet,
      netString: model.metalNetString,
      fractionString: model.metalFractionString,
      min: 20,
      tick: 10,
    }

    var energy = {
      resource: 'energy',
      current: model.currentEnergy,
      max: model.maxEnergy,
      currentGain: model.energyGain,
      currentLoss: model.energyLoss,
      net: model.energyNet,
      netString: model.energyNetString,
      fractionString: model.energyFractionString,
      min: 4000,
      tick: 1000,
    }

    var series = function(value, scale) {
      var history = []

      var s = {
        scale: scale,
        value: value,
        percent: ko.computed(function() {
          return '' + (100 * value() / scale()) + '%';
        }),
        max: ko.observable(0),
        min: ko.observable(1000000000)
      }

      value.subscribe(function(v) {
        history.unshift(v)
        history.splice(10,10)

        s.max(Math.max.apply(Math, history))
        s.min(Math.min.apply(Math, history))
      })

      s.rangeStart = ko.computed(function() {
        return '' + (100 * s.min() / scale()) + '%'
      })
      s.rangeEnd = ko.computed(function() {
        return '' + (100 * (s.max() - s.min()) / scale()) + '%'
      })

      return s
    }

    var extendResource = function(resource) {
      var highestSeen = 0;
      var gainHistory = [];
      var lossHistory = [];
      resource.highest = ko.computed(function() {
        highestSeen = Math.max(resource.currentGain(), resource.currentLoss(), highestSeen)
        return highestSeen
      })
      resource.scale = ko.computed(function() {
        return Math.max(resource.min, resource.highest())
      })
      resource.ticks = ko.computed(function() {
        var s = resource.scale()
        var axis = []
        var dx = resource.tick
        var weight = Math.sqrt(dx/s)
        if (weight < 0.15) { return axis }
        var c = Math.min(15, Math.floor(16 * weight)).toString(16)
        var color = '#' + c + c + c
        for(var x = 0;x < s;x += dx) {
          axis.push({x: '' + (100 * x / s) + '%', color: color})
        }
        console.log(axis)
        return axis
      })

      resource.gain = series(resource.currentGain, resource.scale)
      resource.loss = series(resource.currentLoss, resource.scale)
    }

    extendResource(metal)
    extendResource(energy)

    var loadTemplate = function ($after, html, model) {
      var $parent = $after.parent()
      $parent.find('.div_status_bar_midpsan').remove()
      $parent.addClass(model.resource)
      $(html).insertAfter($after)
      ko.applyBindings(model, $parent[0]);
    };

    $.get('coui://ui/mods/gross_economy/status_bar_resource.html', function(html) {
      console.log("Loading html ");
      loadTemplate($('.div_status_bar_cont .left_angle'), html, metal);
      loadTemplate($('.div_status_bar_cont .right_flat'), html, energy);
    });

})()
<commit_msg>multilevel scales<commit_after>(function() {
    var metal = {
      resource: 'metal',
      current: model.currentMetal,
      max: model.maxMetal,
      currentGain: model.metalGain,
      currentLoss: model.metalLoss,
      net: model.metalNet,
      netString: model.metalNetString,
      fractionString: model.metalFractionString,
      min: 20,
      tick: 10,
    }

    var energy = {
      resource: 'energy',
      current: model.currentEnergy,
      max: model.maxEnergy,
      currentGain: model.energyGain,
      currentLoss: model.energyLoss,
      net: model.energyNet,
      netString: model.energyNetString,
      fractionString: model.energyFractionString,
      min: 4000,
      tick: 1000,
    }

    var series = function(value, scale) {
      var history = []

      var s = {
        scale: scale,
        value: value,
        percent: ko.computed(function() {
          return '' + (100 * value() / scale()) + '%';
        }),
        max: ko.observable(0),
        min: ko.observable(1000000000)
      }

      value.subscribe(function(v) {
        history.unshift(v)
        history.splice(10,10)

        s.max(Math.max.apply(Math, history))
        s.min(Math.min.apply(Math, history))
      })

      s.rangeStart = ko.computed(function() {
        return '' + (100 * s.min() / scale()) + '%'
      })
      s.rangeEnd = ko.computed(function() {
        return '' + (100 * (s.max() - s.min()) / scale()) + '%'
      })

      return s
    }

    var tickColor = function(weight) {
      var c = Math.min(15, Math.floor(16 * weight)).toString(16)
      return '#' + c + c + c
    }

    var extendResource = function(resource) {
      var highestSeen = 0;
      var gainHistory = [];
      var lossHistory = [];
      resource.highest = ko.computed(function() {
        highestSeen = Math.max(resource.currentGain(), resource.currentLoss(), highestSeen)
        return highestSeen
      })
      resource.scale = ko.computed(function() {
        return Math.max(resource.min, resource.highest())
      })
      resource.ticks = ko.computed(function() {
        var s = resource.scale()
        var axis = []
        var dx = resource.tick
        var w1 = Math.sqrt(dx/s)
        while (w1 < 0.15) {
          dx = dx * 5
          w1 = Math.sqrt(dx/s)
        }
        var w2 = Math.sqrt(5*dx/s)
        var w3 = Math.sqrt(25*dx/s)
        var c1 = tickColor(w1)
        var c2 = tickColor(w2)
        var c3 = tickColor(w3)
        for(var x = 0, i = 0;x < s;x += dx,i+=1) {
          if (i % 25 == 0) {
            axis.push({x: '' + (100 * x / s) + '%', color: c3})
          } else if (i % 5 == 0) {
            axis.push({x: '' + (100 * x / s) + '%', color: c2})
          } else {
            axis.push({x: '' + (100 * x / s) + '%', color: c1})
          }
        }
        return axis
      })

      resource.gain = series(resource.currentGain, resource.scale)
      resource.loss = series(resource.currentLoss, resource.scale)
    }

    extendResource(metal)
    extendResource(energy)

    var loadTemplate = function ($after, html, model) {
      var $parent = $after.parent()
      $parent.find('.div_status_bar_midpsan').remove()
      $parent.addClass(model.resource)
      $(html).insertAfter($after)
      ko.applyBindings(model, $parent[0]);
    };

    $.get('coui://ui/mods/gross_economy/status_bar_resource.html', function(html) {
      console.log("Loading html ");
      loadTemplate($('.div_status_bar_cont .left_angle'), html, metal);
      loadTemplate($('.div_status_bar_cont .right_flat'), html, energy);
    });

})()
<|endoftext|>


<commit_before>(function() {
  var metal = {
    resource: 'metal',
    current: model.currentMetal,
    max: model.maxMetal,
    currentGain: model.metalGain,
    currentLoss: model.metalLoss,
    net: model.metalNet,
    netString: ko.computed(function() {
      return ((model.metalNet() > 0) ? '+' : '') + Math.round(model.metalNet()/10)
    }),
    fractionString: model.metalFractionString,
    min: 20,
    tick: 10,
  }

  var energy = {
    resource: 'energy',
    current: model.currentEnergy,
    max: model.maxEnergy,
    currentGain: model.energyGain,
    currentLoss: model.energyLoss,
    net: model.energyNet,
    netString: ko.computed(function() {
      return ((model.energyNet() > 0) ? '+' : '') + Math.round(model.energyNet()/1000)
    }),
    fractionString: model.energyFractionString,
    min: 4000,
    tick: 1000,
  }

  var series = function(value, scale) {
    var valueHistory = []
    var timeHistory = []

    var s = {
      scale: scale,
      value: value,
      percent: ko.computed(function() {
        return '' + (100 * value() / scale()) + '%';
      }),
      max: ko.observable(0),
      min: ko.observable(1000000000)
    }

    value.subscribe(function(v) {
      var t = Date.now()
      valueHistory.push(v)
      timeHistory.push(t)
      while (timeHistory.length > 0 && t - timeHistory[0] > 30000) {
        valueHistory.shift()
        timeHistory.shift()
      }

      s.max(Math.max.apply(Math, valueHistory))
      s.min(Math.min.apply(Math, valueHistory))
    })

    s.rangeStart = ko.computed(function() {
      return '' + (100 * s.min() / scale()) + '%'
    })
    s.rangeEnd = ko.computed(function() {
      return '' + (100 * (s.max() - s.min()) / scale()) + '%'
    })

    return s
  }

  var tickColor = function(weight) {
    var c = Math.min(15, Math.floor(16 * weight)).toString(16)
    return '#' + c + c + c
  }

  var extendResource = function(resource) {
    var highestSeen = 0;
    var gainHistory = [];
    var lossHistory = [];
    resource.highest = ko.computed(function() {
      highestSeen = Math.max(resource.currentGain(), resource.currentLoss(), highestSeen)
      return highestSeen
    })
    resource.scale = ko.computed(function() {
      return Math.max(resource.min, resource.highest())
    })
    resource.ticks = ko.computed(function() {
      var s = resource.scale()
      var axis = []
      var dx = resource.tick
      var w1 = Math.sqrt(dx/s)
      while (w1 < 0.15) {
        dx = dx * 5
        w1 = Math.sqrt(dx/s)
      }
      var w2 = Math.sqrt(5*dx/s)
      var w3 = Math.sqrt(25*dx/s)
      var c1 = tickColor(w1)
      var c2 = tickColor(w2)
      var c3 = tickColor(w3)
      for(var x = 0, i = 0;x < s;x += dx,i+=1) {
        if (i % 25 == 0) {
          axis.push({x: '' + (100 * x / s) + '%', color: c3})
        } else if (i % 5 == 0) {
          axis.push({x: '' + (100 * x / s) + '%', color: c2})
        } else {
          axis.push({x: '' + (100 * x / s) + '%', color: c1})
        }
      }
      return axis
    })

    resource.gain = series(resource.currentGain, resource.scale)
    resource.loss = series(resource.currentLoss, resource.scale)
  }

  extendResource(metal)
  extendResource(energy)

  var loadTemplate = function ($after, html, model) {
    var $parent = $after.parent()
    $parent.find('.div_status_bar_midpsan').remove()
    $parent.addClass(model.resource)
    $(html).insertAfter($after)
    ko.applyBindings(model, $parent[0]);
  };

  $.get('coui://ui/mods/gross_economy/status_bar_resource.html', function(html) {
    console.log("Loading html ");
    loadTemplate($('.div_status_bar_cont .left_angle'), html, metal);
    loadTemplate($('.div_status_bar_cont .right_flat'), html, energy);
  });
})()
<commit_msg>strict mode<commit_after>(function() {
  "use strict";

  var metal = {
    resource: 'metal',
    current: model.currentMetal,
    max: model.maxMetal,
    currentGain: model.metalGain,
    currentLoss: model.metalLoss,
    net: model.metalNet,
    netString: ko.computed(function() {
      return ((model.metalNet() > 0) ? '+' : '') + Math.round(model.metalNet()/10)
    }),
    fractionString: model.metalFractionString,
    min: 20,
    tick: 10,
  }

  var energy = {
    resource: 'energy',
    current: model.currentEnergy,
    max: model.maxEnergy,
    currentGain: model.energyGain,
    currentLoss: model.energyLoss,
    net: model.energyNet,
    netString: ko.computed(function() {
      return ((model.energyNet() > 0) ? '+' : '') + Math.round(model.energyNet()/1000)
    }),
    fractionString: model.energyFractionString,
    min: 4000,
    tick: 1000,
  }

  var series = function(value, scale) {
    var valueHistory = []
    var timeHistory = []

    var s = {
      scale: scale,
      value: value,
      percent: ko.computed(function() {
        return '' + (100 * value() / scale()) + '%';
      }),
      max: ko.observable(0),
      min: ko.observable(1000000000)
    }

    value.subscribe(function(v) {
      var t = Date.now()
      valueHistory.push(v)
      timeHistory.push(t)
      while (timeHistory.length > 0 && t - timeHistory[0] > 30000) {
        valueHistory.shift()
        timeHistory.shift()
      }

      s.max(Math.max.apply(Math, valueHistory))
      s.min(Math.min.apply(Math, valueHistory))
    })

    s.rangeStart = ko.computed(function() {
      return '' + (100 * s.min() / scale()) + '%'
    })
    s.rangeEnd = ko.computed(function() {
      return '' + (100 * (s.max() - s.min()) / scale()) + '%'
    })

    return s
  }

  var tickColor = function(weight) {
    var c = Math.min(15, Math.floor(16 * weight)).toString(16)
    return '#' + c + c + c
  }

  var extendResource = function(resource) {
    var highestSeen = 0;
    var gainHistory = [];
    var lossHistory = [];
    resource.highest = ko.computed(function() {
      highestSeen = Math.max(resource.currentGain(), resource.currentLoss(), highestSeen)
      return highestSeen
    })
    resource.scale = ko.computed(function() {
      return Math.max(resource.min, resource.highest())
    })
    resource.ticks = ko.computed(function() {
      var s = resource.scale()
      var axis = []
      var dx = resource.tick
      var w1 = Math.sqrt(dx/s)
      while (w1 < 0.15) {
        dx = dx * 5
        w1 = Math.sqrt(dx/s)
      }
      var w2 = Math.sqrt(5*dx/s)
      var w3 = Math.sqrt(25*dx/s)
      var c1 = tickColor(w1)
      var c2 = tickColor(w2)
      var c3 = tickColor(w3)
      for(var x = 0, i = 0;x < s;x += dx,i+=1) {
        if (i % 25 == 0) {
          axis.push({x: '' + (100 * x / s) + '%', color: c3})
        } else if (i % 5 == 0) {
          axis.push({x: '' + (100 * x / s) + '%', color: c2})
        } else {
          axis.push({x: '' + (100 * x / s) + '%', color: c1})
        }
      }
      return axis
    })

    resource.gain = series(resource.currentGain, resource.scale)
    resource.loss = series(resource.currentLoss, resource.scale)
  }

  extendResource(metal)
  extendResource(energy)

  var loadTemplate = function ($after, html, model) {
    var $parent = $after.parent()
    $parent.find('.div_status_bar_midpsan').remove()
    $parent.addClass(model.resource)
    $(html).insertAfter($after)
    ko.applyBindings(model, $parent[0]);
  };

  $.get('coui://ui/mods/gross_economy/status_bar_resource.html', function(html) {
    console.log("Loading html ");
    loadTemplate($('.div_status_bar_cont .left_angle'), html, metal);
    loadTemplate($('.div_status_bar_cont .right_flat'), html, energy);
  });
})()
<|endoftext|>


<commit_before>/* eslint-env browser*/
import _ from 'underscore';
import pathwaysActions from './pathways';
import rootRef from '../libs/firebase';
import { hashToCollection } from '../libs/hashToCollection.js';
import request from 'request';
import objectWithSnakeKeysFromCamel from '../libs/objectWithSnakeKeysFromCamel';

const C = require('../constants').default;
const moment = require('moment');

const responsesRef = rootRef.child('responses');

export function deleteStatus(questionId) {
  return { type: C.DELETE_RESPONSE_STATUS, data: { questionId, }, };
}

export function updateStatus(questionId, status) {
  return { type: C.UPDATE_RESPONSE_STATUS, data: { questionId, status, }, };
}

export function updateData(questionId, responses) {
  return { type: C.UPDATE_RESPONSE_DATA, data: { questionId, responses, }, };
}

function responsesForQuestionRef(questionId) {
  return responsesRef.orderByChild('questionUID').equalTo(questionId);
}

function getQuestionLoadedStatusForGroupedResponses(groupedResponses) {
  const questionsKeys = _.keys(groupedResponses);
  const statuses = {};
  questionsKeys.forEach((key) => {
    statuses[key] = 'LOADED';
  });
  console.log(statuses);
  return statuses;
}

function groupResponsesByQuestion(snapshot) {
  const groupedResponses = {};
  for (const responseKey in snapshot) {
    if (snapshot.hasOwnProperty(responseKey)) {
      const response = snapshot[responseKey];
      if (response.questionUID) {
        if (groupedResponses[response.questionUID]) {
          groupedResponses[response.questionUID][responseKey] = response;
        } else {
          groupedResponses[response.questionUID] = {};
          groupedResponses[response.questionUID][responseKey] = response;
        }
      }
    }
  }
  return groupedResponses;
}

export function loadAllResponseData() {
  return (dispatch) => {
    responsesRef.once('value', (snapshot) => {
      const data = groupResponsesByQuestion(snapshot.val());
      const status = getQuestionLoadedStatusForGroupedResponses(data);
      dispatch({ type: 'BULK UPDATE', data: { data, status, }, });
    });
  };
}

export function loadResponseData(questionId) {
  return (dispatch) => {
    // dispatch(updateStatus(questionId, 'LOADING'));
    responsesForQuestionRef(questionId).once('value', (snapshot) => {
      dispatch(updateData(questionId, snapshot.val()));
      // dispatch(updateStatus(questionId, 'LOADED'));
    });
  };
}

export function loadMultipleResponses(arrayOfQuestionIDs, cb) {
  return (dispatch) => {
    const newValues = {};
    const it = makeIterator(arrayOfQuestionIDs);
    const firstID = it.next().value;
    const doneTask = (newResponseData) => {
      dispatch({ type: 'BULK UPDATE', data: { data: newResponseData, status: {}, }, });
      cb();
    };
    loadResponseDataAndCallback(firstID, newValues, it, doneTask);
  };
}

function loadResponseDataAndCallback(questionId, dataHash, iterator, cb) {
  if (questionId === undefined) {
    cb(dataHash);
  } else {
    responsesForQuestionRef(questionId).once('value', (snapshot) => {
      dataHash[questionId] = snapshot.val();
      loadResponseDataAndCallback(iterator.next().value, dataHash, iterator, cb);
    });
  }
}

export function loadResponseDataAndListen(questionId) {
  return (dispatch) => {
    dispatch(updateStatus(questionId, 'LOADING'));
    responsesForQuestionRef(questionId).on('value', (snapshot) => {
      dispatch(updateData(questionId, snapshot.val()));
      dispatch(updateStatus(questionId, 'LOADED'));
    });
  };
}

export function stopListeningToResponses(questionId) {
  return () => {
    responsesForQuestionRef(questionId).off('value');
  };
}

export function submitResponse(content, prid, isFirstAttempt) {
  delete content.gradeIndex;
  const rubyConvertedResponse = objectWithSnakeKeysFromCamel(content);
  rubyConvertedResponse.created_at = moment().format('x');
  rubyConvertedResponse.first_attempt_count = isFirstAttempt ? 1 : 0;
  rubyConvertedResponse.is_first_attempt = isFirstAttempt;
  return (dispatch) => {
    request.post({
      url: `${process.env.QUILL_CMS}/responses/create_or_increment`,
      form: { response: rubyConvertedResponse, }, },
      (error, httpStatus, body) => {
        if (error) {
          dispatch({ type: C.DISPLAY_ERROR, error: `Submission failed! ${error}`, });
        } else if (httpStatus.statusCode === 204 || httpStatus.statusCode === 200) {
          dispatch({ type: C.DISPLAY_MESSAGE, message: 'Submission successfully saved!', });
        } else {
          console.log(body);
        }
      },
    );
  };
}

export function submitMassEditFeedback(ids, properties, qid) {
  return (dispatch) => {
    const updated_attribute = properties;
    console.log(updated_attribute);
    request.put({
      url: `${process.env.QUILL_CMS}/responses/mass_edit/edit_many`,
      json: { ids, updated_attribute, }, },
      (error, httpStatus, body) => {
        if (error) {
          dispatch({ type: C.DISPLAY_ERROR, error: `Submission failed! ${error}`, });
        } else if (httpStatus.statusCode === 204 || httpStatus.statusCode === 200) {
          dispatch({ type: C.DISPLAY_MESSAGE, message: 'Submission successfully saved!', });
          dispatch({ type: C.SHOULD_RELOAD_RESPONSES, qid, });
        } else {
          console.log(body);
        }
      });
  };
}

export function submitMassEditConceptResults(ids, conceptResults, qid) {
  return (dispatch) => {
    const updated_attribute = {
      concept_results: conceptResults,
    };
    request.put({
      url: `${process.env.QUILL_CMS}/responses/mass_edit/edit_many`,
      json: { ids, updated_attribute, }, },
      (error, httpStatus, body) => {
        if (error) {
          dispatch({ type: C.DISPLAY_ERROR, error: `Submission failed! ${error}`, });
        } else if (httpStatus.statusCode === 204 || httpStatus.statusCode === 200) {
          dispatch({ type: C.DISPLAY_MESSAGE, message: 'Submission successfully saved!', });
          dispatch({ type: C.SHOULD_RELOAD_RESPONSES, qid, });
        } else {
          console.log(body);
        }
      });
  };
}

export function massEditDeleteResponses(ids, qid) {
  return (dispatch) => {
    request.post({
      url: `${process.env.QUILL_CMS}/responses/mass_edit/delete_many`,
      json: { ids, }, },
      (error, httpStatus, body) => {
        if (error) {
          dispatch({ type: C.DISPLAY_ERROR, error: `Submission failed! ${error}`, });
        } else if (httpStatus.statusCode === 204 || httpStatus.statusCode === 200) {
          dispatch({ type: C.DISPLAY_MESSAGE, message: 'Submission successfully saved!', });
          dispatch({ type: C.SHOULD_RELOAD_RESPONSES, qid, });
        } else {
          console.log(body);
        }
      });
  };
}

export function submitResponseEdit(rid, content, qid) {
  const rubyConvertedResponse = objectWithSnakeKeysFromCamel(content, false);
  return (dispatch) => {
    request.put({
      url: `${process.env.QUILL_CMS}/responses/${rid}`,
      form: { response: rubyConvertedResponse, }, },
      (error, httpStatus, body) => {
        if (error) {
          dispatch({ type: C.DISPLAY_ERROR, error: `Submission failed! ${error}`, });
        } else if (httpStatus.statusCode === 204 || httpStatus.statusCode === 200) {
          dispatch({ type: C.DISPLAY_MESSAGE, message: 'Submission successfully saved!', });
          dispatch({ type: C.SHOULD_RELOAD_RESPONSES, qid, });
        } else {
          console.log(body);
        }
      });
  };
}

export function addNewConceptResult(rid, content, qid) {
  const rubyConvertedResponse = objectWithSnakeKeysFromCamel(content, false);
  return (dispatch) => {
    request.put({
      url: `${process.env.QUILL_CMS}/responses/${rid}`,
      form: { response: rubyConvertedResponse, }, },
      (error, httpStatus, body) => {
        if (error) {
          dispatch({ type: C.DISPLAY_ERROR, error: `Submission failed! ${error}`, });
        } else if (httpStatus.statusCode === 204 || httpStatus.statusCode === 200) {
          dispatch({ type: C.DISPLAY_MESSAGE, message: 'Submission successfully saved!', });
        } else {
          console.log(body);
        }
      });
  };
}

export function deleteConceptResult(rid, content, qid) {
  const rubyConvertedResponse = objectWithSnakeKeysFromCamel(content, false);
  return (dispatch) => {
    request.put({
      url: `${process.env.QUILL_CMS}/responses/${rid}`,
      form: { response: rubyConvertedResponse, }, },
      (error, httpStatus, body) => {
        if (error) {
          dispatch({ type: C.DISPLAY_ERROR, error: `Submission failed! ${error}`, });
        } else if (httpStatus.statusCode === 204 || httpStatus.statusCode === 200) {
          dispatch({ type: C.DISPLAY_MESSAGE, message: 'Submission successfully saved!', });
          dispatch({ type: C.SHOULD_RELOAD_RESPONSES, qid, });
          dispatch({ type: C.START_RESPONSE_EDIT, qid, rid, });
        } else {
          console.log(body);
        }
      });
  };
}

export function deleteResponse(qid, rid) {
  return (dispatch) => {
    request.delete(
      `${process.env.QUILL_CMS}/responses/${rid}`,
      (error, httpStatus, body) => {
        if (error) {
          dispatch({ type: C.DISPLAY_ERROR, error: `Submission failed! ${error}`, });
        } else if (httpStatus.statusCode === 204 || httpStatus.statusCode === 200) {
          dispatch({ type: C.DISPLAY_MESSAGE, message: 'Submission successfully saved!', });
          dispatch({ type: C.SHOULD_RELOAD_RESPONSES, qid, });
        } else {
          console.log(body);
        }
      },
    );
  };
}

export function setUpdatedResponse(rid, content) {
  return (dispatch) => {
    responsesRef.child(rid).set(content, (error) => {
      if (error) {
        dispatch({ type: C.DISPLAY_ERROR, error: `Update failed! ${error}`, });
      } else {
        dispatch({ type: C.DISPLAY_MESSAGE, message: 'Update successfully saved!', });
      }
    });
  };
}

export function incrementFirstAttemptCount(rid) {
  return (dispatch) => {
    responsesRef.child(`${rid}/firstAttemptCount`).transaction(currentCount => currentCount + 1, (error) => {
      if (error) {
        dispatch({ type: C.DISPLAY_ERROR, error: `increment failed! ${error}`, });
      } else {
        dispatch({ type: C.DISPLAY_MESSAGE, message: 'first attempt count successfully incremented!', });
      }
    });
  };
}

export function incrementResponseCount(qid, rid, prid, isFirstAttempt) {
  return (dispatch) => {
    const responseRef = responsesRef.child(rid);
    responseRef.child('/count').transaction(currentCount => currentCount + 1, (error) => {
      if (error) {
        dispatch({ type: C.DISPLAY_ERROR, error: `increment failed! ${error}`, });
      } else {
        dispatch(pathwaysActions.submitNewPathway(rid, prid, qid));
        dispatch({ type: C.DISPLAY_MESSAGE, message: 'Response successfully incremented!', });
        if (isFirstAttempt) {
          dispatch(incrementFirstAttemptCount(rid));
        }
      }
    });
    responseRef.child('parentID').once('value', (snap) => {
      if (snap.val()) {
        dispatch(incrementChildResponseCount(snap.val()));
      }
    });
  };
}

export function incrementChildResponseCount(rid) {
  return (dispatch) => {
    responsesRef.child(`${rid}/childCount`).transaction(currentCount => currentCount + 1, (error) => {
      if (error) {
        dispatch({ type: C.DISPLAY_ERROR, error: `increment failed! ${error}`, });
      } else {
        dispatch({ type: C.DISPLAY_MESSAGE, message: 'Child Response successfully incremented!', });
      }
    });
  };
}

export function removeLinkToParentID(rid) {
  return (dispatch) => {
    responsesRef.child(`${rid}/parentID`).remove((error) => {
      if (error) {
        dispatch({ type: C.DISPLAY_ERROR, error: `Deletion failed! ${error}`, });
      } else {
        dispatch({ type: C.DISPLAY_MESSAGE, message: 'Response successfully deleted!', });
      }
    });
  };
}

function makeIterator(array) {
  let nextIndex = 0;

  return {
    next() {
      return nextIndex < array.length ?
               { value: array[nextIndex++], done: false, } :
               { done: true, };
    },
  };
}

export function getResponsesWithCallback(questionID, callback) {
  responsesForQuestionRef(questionID).once('value', (snapshot) => {
    callback(snapshot.val());
    console.log('Loaded responses for ', questionID);
  });
}

export function listenToResponsesWithCallback(questionID, callback) {
  responsesForQuestionRef(questionID).on('value', (snapshot) => {
    callback(snapshot.val());
    console.log('Listened to responses for ', questionID);
  });
}

function gradedResponsesForQuestionRef(questionId) {
  return responsesRef.orderByChild('gradeIndex').equalTo(`human${questionId}`);
}

export function getGradedResponsesWithCallback(questionID, callback) {
  request(`${process.env.QUILL_CMS}/questions/${questionID}/responses`, (error, response, body) => {
    if (error) {
      console.log('error:', error); // Print the error if one occurred
    }
    const bodyToObj = {};
    JSON.parse(body).forEach((resp) => {
      bodyToObj[resp.id] = resp;
      if (typeof resp.concept_results === 'string') {
        resp.concept_results = JSON.parse(resp.concept_results);
      }
      for (const cr in resp.concept_results) {
        const formatted_cr = {};
        formatted_cr.conceptUID = cr;
        formatted_cr.correct = resp.concept_results[cr];
        resp.concept_results[cr] = formatted_cr;
      }
      resp.conceptResults = resp.concept_results;
      delete resp.concept_results;
    });
    callback(bodyToObj);
  });
}

export function getGradedResponsesWithoutCallback(questionID) {
  request(`${process.env.QUILL_CMS}/questions/${questionID}/responses`, (error, response, body) => {
    if (error) {
      console.log('error:', error); // Print the error if one occurred
    }
    const bodyToObj = {};
    JSON.parse(body).forEach((resp) => {
      bodyToObj[resp.id] = resp;
      if (typeof resp.concept_results === 'string') {
        resp.concept_results = JSON.parse(resp.concept_results);
      }
      for (const cr in resp.concept_results) {
        const formatted_cr = {};
        formatted_cr.conceptUID = cr;
        formatted_cr.correct = resp.concept_results[cr];
        resp.concept_results[cr] = formatted_cr;
      }
      resp.conceptResults = resp.concept_results;
      delete resp.concept_results;
    });
    return bodyToObj;
  });
}

export function findResponseByText(text, questionUID, cb) {
  responsesRef.orderByChild('text').equalTo(text).once('value', (snapshot) => {
    const response = _.findWhere(hashToCollection(snapshot.val()), { questionUID, });
    cb(response);
  });
}
<commit_msg>Updated empty concept result object for deletion<commit_after>/* eslint-env browser*/
import _ from 'underscore';
import pathwaysActions from './pathways';
import rootRef from '../libs/firebase';
import { hashToCollection } from '../libs/hashToCollection.js';
import request from 'request';
import objectWithSnakeKeysFromCamel from '../libs/objectWithSnakeKeysFromCamel';

const C = require('../constants').default;
const moment = require('moment');

const responsesRef = rootRef.child('responses');

export function deleteStatus(questionId) {
  return { type: C.DELETE_RESPONSE_STATUS, data: { questionId, }, };
}

export function updateStatus(questionId, status) {
  return { type: C.UPDATE_RESPONSE_STATUS, data: { questionId, status, }, };
}

export function updateData(questionId, responses) {
  return { type: C.UPDATE_RESPONSE_DATA, data: { questionId, responses, }, };
}

function responsesForQuestionRef(questionId) {
  return responsesRef.orderByChild('questionUID').equalTo(questionId);
}

function getQuestionLoadedStatusForGroupedResponses(groupedResponses) {
  const questionsKeys = _.keys(groupedResponses);
  const statuses = {};
  questionsKeys.forEach((key) => {
    statuses[key] = 'LOADED';
  });
  console.log(statuses);
  return statuses;
}

function groupResponsesByQuestion(snapshot) {
  const groupedResponses = {};
  for (const responseKey in snapshot) {
    if (snapshot.hasOwnProperty(responseKey)) {
      const response = snapshot[responseKey];
      if (response.questionUID) {
        if (groupedResponses[response.questionUID]) {
          groupedResponses[response.questionUID][responseKey] = response;
        } else {
          groupedResponses[response.questionUID] = {};
          groupedResponses[response.questionUID][responseKey] = response;
        }
      }
    }
  }
  return groupedResponses;
}

export function loadAllResponseData() {
  return (dispatch) => {
    responsesRef.once('value', (snapshot) => {
      const data = groupResponsesByQuestion(snapshot.val());
      const status = getQuestionLoadedStatusForGroupedResponses(data);
      dispatch({ type: 'BULK UPDATE', data: { data, status, }, });
    });
  };
}

export function loadResponseData(questionId) {
  return (dispatch) => {
    // dispatch(updateStatus(questionId, 'LOADING'));
    responsesForQuestionRef(questionId).once('value', (snapshot) => {
      dispatch(updateData(questionId, snapshot.val()));
      // dispatch(updateStatus(questionId, 'LOADED'));
    });
  };
}

export function loadMultipleResponses(arrayOfQuestionIDs, cb) {
  return (dispatch) => {
    const newValues = {};
    const it = makeIterator(arrayOfQuestionIDs);
    const firstID = it.next().value;
    const doneTask = (newResponseData) => {
      dispatch({ type: 'BULK UPDATE', data: { data: newResponseData, status: {}, }, });
      cb();
    };
    loadResponseDataAndCallback(firstID, newValues, it, doneTask);
  };
}

function loadResponseDataAndCallback(questionId, dataHash, iterator, cb) {
  if (questionId === undefined) {
    cb(dataHash);
  } else {
    responsesForQuestionRef(questionId).once('value', (snapshot) => {
      dataHash[questionId] = snapshot.val();
      loadResponseDataAndCallback(iterator.next().value, dataHash, iterator, cb);
    });
  }
}

export function loadResponseDataAndListen(questionId) {
  return (dispatch) => {
    dispatch(updateStatus(questionId, 'LOADING'));
    responsesForQuestionRef(questionId).on('value', (snapshot) => {
      dispatch(updateData(questionId, snapshot.val()));
      dispatch(updateStatus(questionId, 'LOADED'));
    });
  };
}

export function stopListeningToResponses(questionId) {
  return () => {
    responsesForQuestionRef(questionId).off('value');
  };
}

export function submitResponse(content, prid, isFirstAttempt) {
  delete content.gradeIndex;
  const rubyConvertedResponse = objectWithSnakeKeysFromCamel(content);
  rubyConvertedResponse.created_at = moment().format('x');
  rubyConvertedResponse.first_attempt_count = isFirstAttempt ? 1 : 0;
  rubyConvertedResponse.is_first_attempt = isFirstAttempt;
  return (dispatch) => {
    request.post({
      url: `${process.env.QUILL_CMS}/responses/create_or_increment`,
      form: { response: rubyConvertedResponse, }, },
      (error, httpStatus, body) => {
        if (error) {
          dispatch({ type: C.DISPLAY_ERROR, error: `Submission failed! ${error}`, });
        } else if (httpStatus.statusCode === 204 || httpStatus.statusCode === 200) {
          dispatch({ type: C.DISPLAY_MESSAGE, message: 'Submission successfully saved!', });
        } else {
          console.log(body);
        }
      },
    );
  };
}

export function submitMassEditFeedback(ids, properties, qid) {
  return (dispatch) => {
    const updated_attribute = properties;
    console.log(updated_attribute);
    request.put({
      url: `${process.env.QUILL_CMS}/responses/mass_edit/edit_many`,
      json: { ids, updated_attribute, }, },
      (error, httpStatus, body) => {
        if (error) {
          dispatch({ type: C.DISPLAY_ERROR, error: `Submission failed! ${error}`, });
        } else if (httpStatus.statusCode === 204 || httpStatus.statusCode === 200) {
          dispatch({ type: C.DISPLAY_MESSAGE, message: 'Submission successfully saved!', });
          dispatch({ type: C.SHOULD_RELOAD_RESPONSES, qid, });
        } else {
          console.log(body);
        }
      });
  };
}

export function submitMassEditConceptResults(ids, conceptResults, qid) {
  return (dispatch) => {
    const updated_attribute = {
      concept_results: conceptResults,
    };
    request.put({
      url: `${process.env.QUILL_CMS}/responses/mass_edit/edit_many`,
      json: { ids, updated_attribute, }, },
      (error, httpStatus, body) => {
        if (error) {
          dispatch({ type: C.DISPLAY_ERROR, error: `Submission failed! ${error}`, });
        } else if (httpStatus.statusCode === 204 || httpStatus.statusCode === 200) {
          dispatch({ type: C.DISPLAY_MESSAGE, message: 'Submission successfully saved!', });
          dispatch({ type: C.SHOULD_RELOAD_RESPONSES, qid, });
        } else {
          console.log(body);
        }
      });
  };
}

export function massEditDeleteResponses(ids, qid) {
  return (dispatch) => {
    request.post({
      url: `${process.env.QUILL_CMS}/responses/mass_edit/delete_many`,
      json: { ids, }, },
      (error, httpStatus, body) => {
        if (error) {
          dispatch({ type: C.DISPLAY_ERROR, error: `Submission failed! ${error}`, });
        } else if (httpStatus.statusCode === 204 || httpStatus.statusCode === 200) {
          dispatch({ type: C.DISPLAY_MESSAGE, message: 'Submission successfully saved!', });
          dispatch({ type: C.SHOULD_RELOAD_RESPONSES, qid, });
        } else {
          console.log(body);
        }
      });
  };
}

export function submitResponseEdit(rid, content, qid) {
  const rubyConvertedResponse = objectWithSnakeKeysFromCamel(content, false);
  return (dispatch) => {
    request.put({
      url: `${process.env.QUILL_CMS}/responses/${rid}`,
      form: { response: rubyConvertedResponse, }, },
      (error, httpStatus, body) => {
        if (error) {
          dispatch({ type: C.DISPLAY_ERROR, error: `Submission failed! ${error}`, });
        } else if (httpStatus.statusCode === 204 || httpStatus.statusCode === 200) {
          dispatch({ type: C.DISPLAY_MESSAGE, message: 'Submission successfully saved!', });
          dispatch({ type: C.SHOULD_RELOAD_RESPONSES, qid, });
        } else {
          console.log(body);
        }
      });
  };
}

export function addNewConceptResult(rid, content, qid) {
  const rubyConvertedResponse = objectWithSnakeKeysFromCamel(content, false);
  return (dispatch) => {
    request.put({
      url: `${process.env.QUILL_CMS}/responses/${rid}`,
      form: { response: rubyConvertedResponse, }, },
      (error, httpStatus, body) => {
        if (error) {
          dispatch({ type: C.DISPLAY_ERROR, error: `Submission failed! ${error}`, });
        } else if (httpStatus.statusCode === 204 || httpStatus.statusCode === 200) {
          dispatch({ type: C.DISPLAY_MESSAGE, message: 'Submission successfully saved!', });
        } else {
          console.log(body);
        }
      });
  };
}

export function deleteConceptResult(rid, content, qid) {
  const rubyConvertedResponse = objectWithSnakeKeysFromCamel(content, false);
  let updatedResponse;
  if (Object.keys(rubyConvertedResponse.concept_results).length === 0) {
    updatedResponse = Object.assign({}, rubyConvertedResponse, {concept_results: null})
    //updatedResponse = rubyConvertedResponse;
  } else {
    updatedResponse = rubyConvertedResponse;
  }
  debugger;
  return (dispatch) => {
    request.put({
      url: `${process.env.QUILL_CMS}/responses/${rid}`,
      form: { response: updatedResponse, }, },
      (error, httpStatus, body) => {
        if (error) {
          dispatch({ type: C.DISPLAY_ERROR, error: `Submission failed! ${error}`, });
        } else if (httpStatus.statusCode === 204 || httpStatus.statusCode === 200) {
          dispatch({ type: C.DISPLAY_MESSAGE, message: 'Submission successfully saved!', });
          dispatch({ type: C.SHOULD_RELOAD_RESPONSES, qid, });
          dispatch({ type: C.START_RESPONSE_EDIT, qid, rid, });
        } else {
          console.log(body);
        }
      });
  };
}

export function deleteResponse(qid, rid) {
  return (dispatch) => {
    request.delete(
      `${process.env.QUILL_CMS}/responses/${rid}`,
      (error, httpStatus, body) => {
        if (error) {
          dispatch({ type: C.DISPLAY_ERROR, error: `Submission failed! ${error}`, });
        } else if (httpStatus.statusCode === 204 || httpStatus.statusCode === 200) {
          dispatch({ type: C.DISPLAY_MESSAGE, message: 'Submission successfully saved!', });
          dispatch({ type: C.SHOULD_RELOAD_RESPONSES, qid, });
        } else {
          console.log(body);
        }
      },
    );
  };
}

export function setUpdatedResponse(rid, content) {
  return (dispatch) => {
    responsesRef.child(rid).set(content, (error) => {
      if (error) {
        dispatch({ type: C.DISPLAY_ERROR, error: `Update failed! ${error}`, });
      } else {
        dispatch({ type: C.DISPLAY_MESSAGE, message: 'Update successfully saved!', });
      }
    });
  };
}

export function incrementFirstAttemptCount(rid) {
  return (dispatch) => {
    responsesRef.child(`${rid}/firstAttemptCount`).transaction(currentCount => currentCount + 1, (error) => {
      if (error) {
        dispatch({ type: C.DISPLAY_ERROR, error: `increment failed! ${error}`, });
      } else {
        dispatch({ type: C.DISPLAY_MESSAGE, message: 'first attempt count successfully incremented!', });
      }
    });
  };
}

export function incrementResponseCount(qid, rid, prid, isFirstAttempt) {
  return (dispatch) => {
    const responseRef = responsesRef.child(rid);
    responseRef.child('/count').transaction(currentCount => currentCount + 1, (error) => {
      if (error) {
        dispatch({ type: C.DISPLAY_ERROR, error: `increment failed! ${error}`, });
      } else {
        dispatch(pathwaysActions.submitNewPathway(rid, prid, qid));
        dispatch({ type: C.DISPLAY_MESSAGE, message: 'Response successfully incremented!', });
        if (isFirstAttempt) {
          dispatch(incrementFirstAttemptCount(rid));
        }
      }
    });
    responseRef.child('parentID').once('value', (snap) => {
      if (snap.val()) {
        dispatch(incrementChildResponseCount(snap.val()));
      }
    });
  };
}

export function incrementChildResponseCount(rid) {
  return (dispatch) => {
    responsesRef.child(`${rid}/childCount`).transaction(currentCount => currentCount + 1, (error) => {
      if (error) {
        dispatch({ type: C.DISPLAY_ERROR, error: `increment failed! ${error}`, });
      } else {
        dispatch({ type: C.DISPLAY_MESSAGE, message: 'Child Response successfully incremented!', });
      }
    });
  };
}

export function removeLinkToParentID(rid) {
  return (dispatch) => {
    responsesRef.child(`${rid}/parentID`).remove((error) => {
      if (error) {
        dispatch({ type: C.DISPLAY_ERROR, error: `Deletion failed! ${error}`, });
      } else {
        dispatch({ type: C.DISPLAY_MESSAGE, message: 'Response successfully deleted!', });
      }
    });
  };
}

function makeIterator(array) {
  let nextIndex = 0;

  return {
    next() {
      return nextIndex < array.length ?
               { value: array[nextIndex++], done: false, } :
               { done: true, };
    },
  };
}

export function getResponsesWithCallback(questionID, callback) {
  responsesForQuestionRef(questionID).once('value', (snapshot) => {
    callback(snapshot.val());
    console.log('Loaded responses for ', questionID);
  });
}

export function listenToResponsesWithCallback(questionID, callback) {
  responsesForQuestionRef(questionID).on('value', (snapshot) => {
    callback(snapshot.val());
    console.log('Listened to responses for ', questionID);
  });
}

function gradedResponsesForQuestionRef(questionId) {
  return responsesRef.orderByChild('gradeIndex').equalTo(`human${questionId}`);
}

export function getGradedResponsesWithCallback(questionID, callback) {
  request(`${process.env.QUILL_CMS}/questions/${questionID}/responses`, (error, response, body) => {
    if (error) {
      console.log('error:', error); // Print the error if one occurred
    }
    const bodyToObj = {};
    JSON.parse(body).forEach((resp) => {
      bodyToObj[resp.id] = resp;
      if (typeof resp.concept_results === 'string') {
        resp.concept_results = JSON.parse(resp.concept_results);
      }
      for (const cr in resp.concept_results) {
        const formatted_cr = {};
        formatted_cr.conceptUID = cr;
        formatted_cr.correct = resp.concept_results[cr];
        resp.concept_results[cr] = formatted_cr;
      }
      resp.conceptResults = resp.concept_results;
      delete resp.concept_results;
    });
    callback(bodyToObj);
  });
}

export function getGradedResponsesWithoutCallback(questionID) {
  request(`${process.env.QUILL_CMS}/questions/${questionID}/responses`, (error, response, body) => {
    if (error) {
      console.log('error:', error); // Print the error if one occurred
    }
    const bodyToObj = {};
    JSON.parse(body).forEach((resp) => {
      bodyToObj[resp.id] = resp;
      if (typeof resp.concept_results === 'string') {
        resp.concept_results = JSON.parse(resp.concept_results);
      }
      for (const cr in resp.concept_results) {
        const formatted_cr = {};
        formatted_cr.conceptUID = cr;
        formatted_cr.correct = resp.concept_results[cr];
        resp.concept_results[cr] = formatted_cr;
      }
      resp.conceptResults = resp.concept_results;
      delete resp.concept_results;
    });
    return bodyToObj;
  });
}

export function findResponseByText(text, questionUID, cb) {
  responsesRef.orderByChild('text').equalTo(text).once('value', (snapshot) => {
    const response = _.findWhere(hashToCollection(snapshot.val()), { questionUID, });
    cb(response);
  });
}
<|endoftext|>


<commit_before>import "./statistic.js";
import {CodeMap} from "../data/model/codeMap.js";
import {STATISTIC_OPS} from "./aggregate.service";
import {DataModel} from "../data/model/dataModel";
import {Settings} from "../settings/model/settings";

xdescribe("app.codeCharta.core.statistic", function() {

    var data,settings;

    const file1 = new CodeMap(
        "file",
        "Sample Project",
        {
            "name": "root",
            "attributes": {},
            "children": [
                {
                    "name": "big leaf",
                    "attributes": {"rloc": 100, "functions": 10, "mcc": 1},
                    "link": "http://www.google.de"
                },
                {
                    "name": "Parent Leaf",
                    "attributes": {},
                    "children": [
                        {
                            "name": "other small leaf",
                            "attributes": {"rloc": 70, "functions": 1000, "mcc": 10}
                        }
                    ]
                }
            ]
        }
    );

    const file2 = new CodeMap(
        "file",
        "Sample Project",
        {
            "name": "root",
            "attributes": {},
            "children": [
                {
                    "name": "big leaf",
                    "attributes": {"rloc": 200, "functions": 20, "mcc": 2},
                    "link": "http://www.google.de"
                },
                {
                    "name": "Parent Leaf",
                    "attributes": {},
                    "children": [
                        {
                            "name": "small leaf",
                            "attributes": {"rloc": 60, "functions": 200, "mcc": 200}
                        }
                    ]
                }
            ]
        }
    );

    const file_mean = new CodeMap(
        "MEAN_file_file",
        "Sample Project",
        {
            "name": "root",
            "attributes": {},
            "children": [
                {
                    "name": "big leaf",
                    "attributes": {"rloc": 150, "functions": 15, "mcc": 1.5},
                    "link": "http://www.google.de"
                },
                {
                    "name": "Parent Leaf",
                    "attributes": {},
                    "children": [
                        {
                            "name": "other small leaf",
                            "attributes": {"rloc": 35, "functions": 500, "mcc": 5}
                        },
                        {
                            "name": "small leaf",
                            "attributes": {"rloc": 30, "functions": 100, "mcc": 100}
                        }
                    ]
                }
            ]
        }
    );

    const file_median = new CodeMap(
        "MEDIAN_file_file",
        "Sample Project",
        {
            "name": "root",
            "attributes": {},
            "children": [
                {
                    "name": "big leaf",
                    "attributes": {"rloc": 200, "functions": 20, "mcc": 2},
                    "link": "http://www.google.de"
                },
                {
                    "name": "Parent Leaf",
                    "attributes": {},
                    "children": [
                        {
                            "name": "other small leaf",
                            "attributes": {"rloc": 70, "functions": 1000, "mcc": 10}
                        },
                        {
                            "name": "small leaf",
                            "attributes": {"rloc": 60, "functions": 200, "mcc": 200}
                        }
                    ]
                }
            ]
        }
    );

    const file_max = new CodeMap(
        "MAX_file_file",
        "Sample Project",
        {
            "name": "root",
            "attributes": {},
            "children": [
                {
                    "name": "big leaf",
                    "attributes": {"rloc": 200, "functions": 20, "mcc": 2},
                    "link": "http://www.google.de"
                },
                {
                    "name": "Parent Leaf",
                    "attributes": {},
                    "children": [
                        {
                            "name": "other small leaf",
                            "attributes": {"rloc": 70, "functions": 1000, "mcc": 10}
                        },
                        {
                            "name": "small leaf",
                            "attributes": {"rloc": 60, "functions": 200, "mcc": 200}
                        }
                    ]
                }
            ]
        }
    );

    const file_min = new CodeMap(
        "MIN_file_file",
        "Sample Project",
        {
            "name": "root",
            "attributes": {},
            "children": [
                {
                    "name": "big leaf",
                    "attributes": {"rloc": 100, "functions": 10, "mcc": 1},
                    "link": "http://www.google.de"
                },
                {
                    "name": "Parent Leaf",
                    "attributes": {},
                    "children": [
                        {
                            "name": "other small leaf",
                            "attributes": {"rloc": 70, "functions": 1000, "mcc": 10}
                        },
                        {
                            "name": "small leaf",
                            "attributes": {"rloc": 60, "functions": 200, "mcc": 200}
                        }
                    ]
                }
            ]
        }
    );

    const file_fashion = new CodeMap(
        "FASHION_file_file",
        "Sample Project",
        {
            "name": "root",
            "attributes": {},
            "children": [
                {
                    "name": "big leaf",
                    "attributes": {"rloc": 100, "functions": 10, "mcc": 1},
                    "link": "http://www.google.de"
                },
                {
                    "name": "Parent Leaf",
                    "attributes": {},
                    "children": [
                        {
                            "name": "other small leaf",
                            "attributes": {"rloc": 70, "functions": 1000, "mcc": 10}
                        },
                        {
                            "name": "small leaf",
                            "attributes": {"rloc": 60, "functions": 200, "mcc": 200}
                        }
                    ]
                }
            ]
        }
    );

    beforeEach(angular.mock.module("app.codeCharta.core.statistic"));
    beforeEach(() =>{
        data = new DataModel();
        data.renderMap = file1;
        settings = new Settings();
    });

    /**
     * @test {statisticMapService}
     */
    it("instance", angular.mock.inject(function(statisticMapService){
        expect(statisticMapService).to.not.equal(undefined);
    }));

    /**
     * @test {statisticMapService}
     */
    it("test mean", angular.mock.inject(function(statisticMapService){
        data.revisions = [ file1, file2];
        settings.operation = STATISTIC_OPS.MEAN;
        const resultingMap = statisticMapService.unifyMaps(data, settings);
        expect(resultingMap).to.deep.equal(file_mean);
    }));

    /**
     * @test {statisticMapService}
     */
    it("test median", angular.mock.inject(function(statisticMapService){
        data.revisions = [ file1, file2];
        settings.operation = STATISTIC_OPS.MEDIAN;
        const resultingMap = statisticMapService.unifyMaps(data, settings);
        expect(resultingMap).to.deep.equal(file_median);
    }));

    /**
     * @test {statisticMapService}
     */
    it("test max", angular.mock.inject(function(statisticMapService){
        data.revisions = [ file1, file2];
        settings.operation = STATISTIC_OPS.MAX;
        const resultingMap = statisticMapService.unifyMaps(data, settings);
        expect(resultingMap).to.deep.equal(file_max);
    }));

    /**
     * @test {statisticMapService}
     */
    it("test min", angular.mock.inject(function(statisticMapService){
        data.revisions = [ file1, file2];
        settings.operation = STATISTIC_OPS.MIN;
        const resultingMap = statisticMapService.unifyMaps(data, settings);
        expect(resultingMap).to.deep.equal(file_min);
    }));

    /**
     * @test {statisticMapService}
     */
    it("test fashion", angular.mock.inject(function(statisticMapService){
        data.revisions = [ file1, file2];
        settings.operation = STATISTIC_OPS.FASHION;
        const resultingMap = statisticMapService.unifyMaps(data, settings);
        expect(resultingMap).to.deep.equal(file_fashion);
    }));

    /**
     * @test {statisticMapService}
     */
    it("test one", angular.mock.inject(function(statisticMapService){
        data.revisions = [file1];
        settings.operation = STATISTIC_OPS.MEAN;
        const resultingMapMean = statisticMapService.unifyMaps(data, settings);
        settings.operation = STATISTIC_OPS.MEDIAN;
        const resultingMapMedian = statisticMapService.unifyMaps(data, settings);
        settings.operation = STATISTIC_OPS.MAX;
        const resultingMapMax = statisticMapService.unifyMaps(data, settings);
        settings.operation = STATISTIC_OPS.MIN;
        const resultingMapMin = statisticMapService.unifyMaps(data, settings);
        settings.operation = STATISTIC_OPS.FASHION;
        const resultingMapFashion = statisticMapService.unifyMaps(data, settings);

        expect(resultingMapMean).to.deep.equal(file1);
        expect(resultingMapMedian).to.deep.equal(file1);
        expect(resultingMapMax).to.deep.equal(file1);
        expect(resultingMapMin).to.deep.equal(file1);
        expect(resultingMapFashion).to.deep.equal(file1);
    }));

    /**
     * @test {statisticMapService}
     */
    it("test repeated", angular.mock.inject(function(statisticMapService){
        data.revisions= [file1, file1, file1, file1];
        settings.operation = STATISTIC_OPS.MEAN;
        const resultingMapMean = statisticMapService.unifyMaps(data, settings);
        settings.operation = STATISTIC_OPS.MEDIAN;
        const resultingMapMedian = statisticMapService.unifyMaps(data, settings);
        settings.operation = STATISTIC_OPS.MAX;
        const resultingMapMax = statisticMapService.unifyMaps(data, settings);
        settings.operation = STATISTIC_OPS.MIN;
        const resultingMapMin = statisticMapService.unifyMaps(data, settings);
        settings.operation = STATISTIC_OPS.FASHION;
        const resultingMapFashion = statisticMapService.unifyMaps(data, settings);

        expect(resultingMapMean.root).to.deep.equal(file1.root);
        expect(resultingMapMedian.root).to.deep.equal(file1.root);
        expect(resultingMapMax.root).to.deep.equal(file1.root);
        expect(resultingMapMin.root).to.deep.equal(file1.root);
        expect(resultingMapFashion.root).to.deep.equal(file1.root);
    }));

    /**
     * @test {statisticMapService}
     * It is checked if when introduced in different order the result is the same, not necesarily in the same order
     */
    it("test order", angular.mock.inject(function(statisticMapService){

        data.revisions= [file1, file2];
        settings.operation = STATISTIC_OPS.MEAN;
        const resultingMapMean1 = statisticMapService.unifyMaps(data, settings);
        settings.operation = STATISTIC_OPS.MEDIAN;
        const resultingMapMedian1 = statisticMapService.unifyMaps(data, settings);
        settings.operation = STATISTIC_OPS.MAX;
        const resultingMapMax1 = statisticMapService.unifyMaps(data, settings);
        settings.operation = STATISTIC_OPS.MIN;
        const resultingMapMin1 = statisticMapService.unifyMaps(data, settings);
        settings.operation = STATISTIC_OPS.FASHION;
        const resultingMapFashion1 = statisticMapService.unifyMaps(data, settings);

        data.revisions= [file2, file1];
        settings.operation = STATISTIC_OPS.MEAN;
        const resultingMapMean2 = statisticMapService.unifyMaps(data, settings);
        settings.operation = STATISTIC_OPS.MEDIAN;
        const resultingMapMedian2 = statisticMapService.unifyMaps(data, settings);
        settings.operation = STATISTIC_OPS.MAX;
        const resultingMapMax2 = statisticMapService.unifyMaps(data, settings);
        settings.operation = STATISTIC_OPS.MIN;
        const resultingMapMin2 = statisticMapService.unifyMaps(data, settings);
        settings.operation = STATISTIC_OPS.FASHION;
        const resultingMapFashion2 = statisticMapService.unifyMaps(data, settings);

        expect(statisticMapService.unorderedCompare(resultingMapMean1,resultingMapMean2)).to.be.true;
        expect(statisticMapService.unorderedCompare(resultingMapMedian1,resultingMapMedian2)).to.be.true;
        expect(statisticMapService.unorderedCompare(resultingMapMax1,resultingMapMax2)).to.be.true;
        expect(statisticMapService.unorderedCompare(resultingMapMin1,resultingMapMin2)).to.be.true;
        expect(statisticMapService.unorderedCompare(resultingMapFashion1,resultingMapFashion2)).to.be.true;
    }));
});<commit_msg>js and js.map files should not be uploaded to git<commit_after><|endoftext|>


<commit_before>import moment from 'moment';

const startDate = '2002-01-01';

const format = momentDate => momentDate.format('YYYY-MM-DD');

export default function getOptions() {
  const fiveYearsAgo = format(moment().subtract(5, 'years'));
  const threeYearsAgo = format(moment().subtract(3, 'years'));
  const oneYearAgo = format(moment().subtract(1, 'year'));
  // const thisYear = format(moment().startOf('year'));

  return [
    { value: startDate, label: 'returnComparison.period.all' },
    { value: fiveYearsAgo, label: 'returnComparison.period.fiveYears' },
    { value: threeYearsAgo, label: 'returnComparison.period.threeYears' },
    { value: oneYearAgo, label: 'returnComparison.period.oneYear' },
    // { value: thisYear, label: 'returnComparison.period.thisYear' },
  ];
}
<commit_msg>add 10-year IRR calculation<commit_after>import moment from 'moment';

const startDate = '2002-01-01';

const format = momentDate => momentDate.format('YYYY-MM-DD');

export default function getOptions() {
  const tenYearsAgo = format(moment().subtract(10, 'years'));
  const fiveYearsAgo = format(moment().subtract(5, 'years'));
  const threeYearsAgo = format(moment().subtract(3, 'years'));
  const oneYearAgo = format(moment().subtract(1, 'year'));
  // const thisYear = format(moment().startOf('year'));

  return [
    { value: startDate, label: 'returnComparison.period.all' },
    { value: tenYearsAgo, label: 'returnComparison.period.tenYears' },
    { value: fiveYearsAgo, label: 'returnComparison.period.fiveYears' },
    { value: threeYearsAgo, label: 'returnComparison.period.threeYears' },
    { value: oneYearAgo, label: 'returnComparison.period.oneYear' },
    // { value: thisYear, label: 'returnComparison.period.thisYear' },
  ];
}
<|endoftext|>