<commit_before>/**
 * Class Humble Model
 */
Humble( function () {

    // Constructor
    var Model = function () {
        this.xml        = null;
        this.xmlDoc     = null;
        this.items      = null;
        this.keys       = null;
        // Ratio of my vs amount
        this.ratio      = null;
        // Construct formatter
        this.format     = new Humble.Formatter();
        this.dataSource = this._buildDataSource();
    }

    // Methods
    Model.prototype = {

        set : function (item, attribute, value) {

            if (this.setters[attribute]) {
                this.setters[attribute].apply(this, [item, attribute, value]);
            }

            Humble.Event.trigger('humble:dvc:modelUpdate');

            // Set attribute
            this._set(item, attribute, value);
        },

        setXML : function (xml) {
            this.xml        = xml;
            this.xmlDoc     = this._parse(xml);
            this.items      = this._getItems(this.xmlDoc);
            this.keys       = _.keys(this.items);
        },

		reset : function()	{
			this.setXML(this.xml);
		},

        get : function (key, attribute) {

            var items = this.items,
                item,
                value;

            // Existential insanity
            item  = (key in items ? items[key] : false);
            value = (attribute && attribute in item ? item[attribute] : false);

            return (value ? value : item);
        },

        getURL : function () {
            return this.url;
        },

        getKey : function (index) {
            return (this.keys[index] ? this.keys[index] : false);
        },

        getIndex : function (key) {
            return _.indexOf(this.keys, key);
        },

        getItems : function () {
            return this.items;
        },

        getItemCount : function () {
            return _.size(this.items);
        },

        requestData : function () {
            return false;
        },

        _parse : function (xml) {
            var xmlDoc = $(jQuery.parseXML(xml));
            return xmlDoc;
        },

        _parseItems : function (xmlDoc) {

            var items    = xmlDoc.find('item'),
                newItems = [];

            var dimensions = {};

            _.each(items, function (item) {

                var $item = $(item);
               newItems.push($item);

               // dimensions[$item.attr(this.key)] = $item.attr(this.key);
            }, this);

            return newItems;
        },

        _getItems : function (xmlDoc) {

            var items  = this._parseItems(xmlDoc),
                values = {};

            _.each(items, function (item, key) {

                var value = {},
                    id    = item.attr(this.key);

                // Fill Value Object
                _.each(Humble.Config.DVZ.budget.fields, function (field, key) {
                    var attr = item.attr(key);
                    if (this.parsers[key]) {
                        attr = this.parsers[key].apply(this, [attr]);
                    }
                    value[key] = attr;
                }, this);

                // Cache
                values['_'+id] = value;
            }, this);

            return values;
        },

        _getTotalNumeric : function (field) {

            var values = this.getItems(),
                total  = 0;

            _.each(values, function (value, key) {
                total += value[field];
            }, this);

            total = this.format.currencyNumeric(total);

            return total;
        },

        _set : function (item, attribute, value) {
            this.items[item][attribute] = value;
        },

        _buildDataSource : function () {

            var that = this,
                options,
                dataSource,
                onSuccess;

            onSuccess = function (data) {
                that.setXML(data);
            }

            options = {
                data    : this.requestData(),
                success : onSuccess,
                url     : this.getURL()
            }

            dataSource = new Humble.DataSource(options);

            return dataSource;
        }
    };

    // Namespace Hook
    Humble.Model = Model;
});
<commit_msg>Clean up spacing.<commit_after>/**
 * Class Humble Model
 */
Humble( function () {

    // Constructor
    var Model = function () {
        this.xml        = null;
        this.xmlDoc     = null;
        this.items      = null;
        this.keys       = null;
        // Ratio of my vs amount
        this.ratio      = null;
        // Construct formatter
        this.format     = new Humble.Formatter();
        this.dataSource = this._buildDataSource();
    }

    // Methods
    Model.prototype = {

        set : function (item, attribute, value) {

            if (this.setters[attribute]) {
                this.setters[attribute].apply(this, [item, attribute, value]);
            }

            Humble.Event.trigger('humble:dvc:modelUpdate');

            // Set attribute
            this._set(item, attribute, value);
        },

        setXML : function (xml) {
            this.xml        = xml;
            this.xmlDoc     = this._parse(xml);
            this.items      = this._getItems(this.xmlDoc);
            this.keys       = _.keys(this.items);
        },

		reset : function()	{
			this.setXML(this.xml);
		},

        get : function (key, attribute) {

            var items = this.items,
                item,
                value;

            // Existential insanity
            item  = (key in items ? items[key] : false);
            value = (attribute && attribute in item ? item[attribute] : false);

            return (value ? value : item);
        },

        getURL : function () {
            return this.url;
        },

        getKey : function (index) {
            return (this.keys[index] ? this.keys[index] : false);
        },

        getIndex : function (key) {
            return _.indexOf(this.keys, key);
        },

        getItems : function () {
            return this.items;
        },

        getItemCount : function () {
            return _.size(this.items);
        },

        requestData : function () {
            return false;
        },

        _parse : function (xml) {
            var xmlDoc = $(jQuery.parseXML(xml));
            return xmlDoc;
        },

        _parseItems : function (xmlDoc) {

            var items    = xmlDoc.find('item'),
                newItems = [];

            var dimensions = {};

            _.each(items, function (item) {
                var $item = $(item);
               newItems.push($item);
            }, this);

            return newItems;
        },

        _getItems : function (xmlDoc) {

            var items  = this._parseItems(xmlDoc),
                values = {};

            _.each(items, function (item, key) {

                var value = {},
                    id    = item.attr(this.key);

                // Fill Value Object
                _.each(Humble.Config.DVZ.budget.fields, function (field, key) {
                    var attr = item.attr(key);
                    if (this.parsers[key]) {
                        attr = this.parsers[key].apply(this, [attr]);
                    }
                    value[key] = attr;
                }, this);

                // Cache
                values['_'+id] = value;
            }, this);

            return values;
        },

        _getTotalNumeric : function (field) {

            var values = this.getItems(),
                total  = 0;

            _.each(values, function (value, key) {
                total += value[field];
            }, this);

            total = this.format.currencyNumeric(total);

            return total;
        },

        _set : function (item, attribute, value) {
            this.items[item][attribute] = value;
        },

        _buildDataSource : function () {

            var that = this,
                options,
                dataSource,
                onSuccess;

            onSuccess = function (data) {
                that.setXML(data);
            }

            options = {
                data    : this.requestData(),
                success : onSuccess,
                url     : this.getURL()
            }

            dataSource = new Humble.DataSource(options);

            return dataSource;
        }
    };

    // Namespace Hook
    Humble.Model = Model;
});
<|endoftext|>


<commit_before>/* Adapted from Clamato by Avi Bryant. http://www.clamato.net */

(function() {
    var scripts = document.getElementsByTagName("script");
    var src = scripts[ scripts.length - 1 ].src;
    var home = src.split("/").slice(0, -2).join("/") + "/";
    var nocache = '?' + (new Date()).getTime();
    var deploy = false;

    function loadJS(name, prefix) {
	var prefix = prefix || 'js';
	var name = name;
	if(!deploy) {
	    name = name + nocache;
	}
	document.write('<script src="' + home + prefix + '/' + name + '" type="text/javascript"></script>');
    }

    function loadCSS(name, prefix) {
	var prefix = prefix || 'css';
	var name = name;
	if(!deploy) {
	    name = name + nocache;
	}
	var link = document.createElement("link")
  	link.setAttribute("rel", "stylesheet")
  	link.setAttribute("type", "text/css")
  	link.setAttribute("href", home + prefix + '/' + name)
	document.getElementsByTagName("head")[0].appendChild(link);
    }

    function loadDependencies() {
	loadJS('lib/jQuery/jquery-1.6.4.min.js');
	loadJS('lib/jQuery/jquery-ui-1.8.9.custom.min.js');
    }

    function loadIDEDependencies() {
	loadJS('lib/jQuery/jquery.textarea.js');
	loadJS('lib/CodeMirror/lib/codemirror.js');
	loadCSS('lib/CodeMirror/lib/codemirror.css', 'js');
	loadJS('lib/CodeMirror/mode/smalltalk/smalltalk.js');
	loadCSS('lib/CodeMirror/theme/amber.css', 'js');
    }

    window.loadAmber = function(spec) {
	/*
	 example:
	 loadAmber({
	   files: ['MyCategory1.js', 'MyCategory2.js'],
	   ready: function() {smalltalk.Browser._open()}
	 })
	*/

	var spec = spec || {};

	// In deployment mode, only the compressed version of Kernel
	// and Canvas are loaded
	deploy = spec.deploy || false;

	// Specify a version string to avoid wrong browser caching
	if(spec.version) {
	    nocache = '?' + spec.version;
	}

	loadDependencies();
	if(deploy) {
	    loadJS("boot.js");
	    loadJS("Kernel.deploy.js");
	    loadJS("Canvas.deploy.js");
	} else {
	    loadIDEDependencies();
	    loadCSS('amber.css');
	    loadJS("boot.js");
	    loadJS("Kernel.js");
	    loadJS("Canvas.js");
	    loadJS("Compiler.js");
	    loadJS("parser.js");
	    loadJS("IDE.js");
	    loadJS("SUnit.js");
	    loadJS("Examples.js");
	    loadJS("Benchfib.js");
	    loadJS("Kernel-Tests.js");
	}

	// Load other files, possibly with another directory prefix than 'js'
	if(spec.files) {
	    for(var i=0; i < spec.files.length; i++) {
		loadJS(spec.files[i], spec.prefix);
	    }
	}

	smalltalkReady = function() {
	    if(spec.ready) {
		spec.ready();
	    }
	    if(deploy) {smalltalk.setDeploymentMode()}
	}

	// Be sure to setup & initialize smalltalk classes
	loadJS("init.js");
    }

})();<commit_msg>do not load jquery if already loaded<commit_after>/* Adapted from Clamato by Avi Bryant. http://www.clamato.net */

(function() {
    var scripts = document.getElementsByTagName("script");
    var src = scripts[ scripts.length - 1 ].src;
    var home = src.split("/").slice(0, -2).join("/") + "/";
    var nocache = '?' + (new Date()).getTime();
    var deploy = false;

    function loadJS(name, prefix) {
	var prefix = prefix || 'js';
	var name = name;
	if(!deploy) {
	    name = name + nocache;
	}
	document.write('<script src="' + home + prefix + '/' + name + '" type="text/javascript"></script>');
    }

    function loadCSS(name, prefix) {
	var prefix = prefix || 'css';
	var name = name;
	if(!deploy) {
	    name = name + nocache;
	}
	var link = document.createElement("link")
  	link.setAttribute("rel", "stylesheet")
  	link.setAttribute("type", "text/css")
  	link.setAttribute("href", home + prefix + '/' + name)
	document.getElementsByTagName("head")[0].appendChild(link);
    }

    function loadDependencies() {
	if (typeof jQuery == 'undefined') {
		loadJS('lib/jQuery/jquery-1.6.4.min.js');
		loadJS('lib/jQuery/jquery-ui-1.8.9.custom.min.js');
	}
    }

    function loadIDEDependencies() {
	loadJS('lib/jQuery/jquery.textarea.js');
	loadJS('lib/CodeMirror/lib/codemirror.js');
	loadCSS('lib/CodeMirror/lib/codemirror.css', 'js');
	loadJS('lib/CodeMirror/mode/smalltalk/smalltalk.js');
	loadCSS('lib/CodeMirror/theme/amber.css', 'js');
    }

    window.loadAmber = function(spec) {
	/*
	 example:
	 loadAmber({
	   files: ['MyCategory1.js', 'MyCategory2.js'],
	   ready: function() {smalltalk.Browser._open()}
	 })
	*/

	var spec = spec || {};

	// In deployment mode, only the compressed version of Kernel
	// and Canvas are loaded
	deploy = spec.deploy || false;

	// Specify a version string to avoid wrong browser caching
	if(spec.version) {
	    nocache = '?' + spec.version;
	}

	loadDependencies();
	if(deploy) {
	    loadJS("boot.js");
	    loadJS("Kernel.deploy.js");
	    loadJS("Canvas.deploy.js");
	} else {
	    loadIDEDependencies();
	    loadCSS('amber.css');
	    loadJS("boot.js");
	    loadJS("Kernel.js");
	    loadJS("Canvas.js");
	    loadJS("Compiler.js");
	    loadJS("parser.js");
	    loadJS("IDE.js");
	    loadJS("SUnit.js");
	    loadJS("Examples.js");
	    loadJS("Benchfib.js");
	    loadJS("Kernel-Tests.js");
	}

	// Load other files, possibly with another directory prefix than 'js'
	if(spec.files) {
	    for(var i=0; i < spec.files.length; i++) {
		loadJS(spec.files[i], spec.prefix);
	    }
	}

	smalltalkReady = function() {
	    if(spec.ready) {
		spec.ready();
	    }
	    if(deploy) {smalltalk.setDeploymentMode()}
	}

	// Be sure to setup & initialize smalltalk classes
	loadJS("init.js");
    }

})();<|endoftext|>


<commit_before>'use strict';

function bests_init(newprefix, bests, default_default){
    bests_default = default_default || bests_default;
    bests_prefix = newprefix;

    for(var best in bests){
        bests_bests[best] = parseFloat(window.localStorage.getItem(bests_prefix + best))
          || bests[best];
    }
}

function bests_reset(){
    if(!window.confirm(bests_reset_confirm)){
        return;
    }

    for(var best in bests_bests){
        bests_bests[best] = bests_default;
        bests_update(bests_bests[best]);
    }
}

function bests_update(key, value){
    if(value > bests_bests[key]){
        bests_bests[key] = value;
    }

    if(bests_bests[key] !== bests_default){
        window.localStorage.setItem(
          bests_prefix + key,
          bests_bests[key]
        );

    }else{
        window.localStorage.removeItem(bests_prefix + key);
    }
}

var bests_bests = {};
var bests_default = 0;
var bests_prefix = '';
var bests_reset_confirm = 'Reset best?';
<commit_msg>replaced bests_default with bests_info, added more/less progression<commit_after>'use strict';

function bests_init(newprefix, bests){
    bests_prefix = newprefix;

    for(var best in bests){
        bests_info[best] = {
          'default': bests[best]['default'],
          'more': bests[best]['more'] || false,
        };
        bests_bests[best] = parseFloat(window.localStorage.getItem(bests_prefix + best))
          || bests_info[best]['default'];
    }
}

function bests_reset(){
    if(!window.confirm(bests_reset_confirm)){
        return;
    }

    for(var best in bests_bests){
        bests_bests[best] = bests_info[best]['default'];
        bests_update(bests_bests[best]);
    }
}

function bests_update(key, value){
    if(!bests_info[key]['more'] || false){
        if(value < bests_bests[key]){
            bests_bests[key] = value;
        }

    }else if(value > bests_bests[key]){
        bests_bests[key] = value;
    }

    if(bests_bests[key] !== bests_info[key]['default']){
        window.localStorage.setItem(
          bests_prefix + key,
          bests_bests[key]
        );

    }else{
        window.localStorage.removeItem(bests_prefix + key);
    }
}

var bests_bests = {};
var bests_info = {};
var bests_prefix = '';
var bests_reset_confirm = 'Reset best?';
<|endoftext|>


<commit_before>document.write("
");
document.write("
");
document.write("文本	");
document.write("类型	");
document.write("<input type = 'button' value = '删除' class = 'deleteInfo' hidden>	");
document.write("
");
if (localStorage.count) {
    for (var i = 0; i < localStorage.count; i++) {
        var info = JSON.parse(localStorage.getItem("BlackList" + i));
        document.write("
");
        document.write("" + info.value + "	");
        if (info.type == "username") {
            info.type = "用户名"
        }
        else {
            info.type = "关键字";
        }
        document.write("" + info.type + "	");
        document.write("<input type = 'button' value = '删除' class = 'deleteInfo btn btn-xs btn-danger'>	");
        document.write("
");
    }
}
document.write("
");
function addInfo(type) {
    var value = document.getElementById("value").value;
    document.getElementById("value").value = "";
    if (type == "key") {
        value = value.toLowerCase();
    }
    if (value.length == 0) {
        return;
    }
    if (!localStorage.count) {
        localStorage.count = 1;
    }
    else {
        localStorage.count = Number(localStorage.count) + 1;
    }
    var info = {value: value, type: type};
    info = JSON.stringify(info);
    var id = Number(localStorage.count) - 1;
    localStorage.setItem("BlackList" + id, info);
    chrome.tabs.executeScript(null, {code: "localStorage.setItem('count', " + localStorage.count + ");"});
    chrome.tabs.executeScript(null, {code: "localStorage.setItem('BlackList" + id + "', '" + info + "');"});
    var row = document.getElementById("BlackList").insertRow(Number(id) + 1);
    row.insertCell(0).innerHTML = value;
    if (type == "username") {
        row.insertCell(1).innerHTML = "用户名";
    }
    else {
        row.insertCell(1).innerHTML = "关键字";
    }
    row.insertCell(2).innerHTML = "<input type = 'button' value = '删除' class = 'deleteInfo btn btn-xs btn-danger'>";

}
function deleteInfo(r) {
    var row = r.parentNode.parentNode.rowIndex;
    for (var i = Number(row) - 1; i < Number(localStorage.count) - 1; i++) {
        localStorage.setItem("BlackList" + i, localStorage.getItem("BlackList" + (Number(i) + 1)));
    }
    var id = (Number(localStorage.count) - 1);
    localStorage.removeItem("BlackList" + id);
    localStorage.count = Number(localStorage.count) - 1;
    document.getElementById("BlackList").deleteRow(row);
    chrome.tabs.executeScript(null, {code: "localStorage.setItem('count', " + localStorage.count + ");"});
    for (var i = 0; i < localStorage.count; i++) {
        var temp = localStorage.getItem("BlackList" + i);
        chrome.tabs.executeScript(null, {code: "localStorage.setItem('BlackList" + i + "', '" + temp + "');"});
    }
}
function addUser() {
    addInfo("username");
}
function addKey() {
    addInfo("key");
}
$("#addUser").click(function () {
    addUser();
});
$("#addKey").click(function () {
    addKey();
});
$("#BlackList").on("click", ".deleteInfo", function () {
    deleteInfo(this);
});<commit_msg>Add trim input values<commit_after>document.write("
");
document.write("
");
document.write("文本	");
document.write("类型	");
document.write("<input type = 'button' value = '删除' class = 'deleteInfo' hidden>	");
document.write("
");
if (localStorage.count) {
    for (var i = 0; i < localStorage.count; i++) {
        var info = JSON.parse(localStorage.getItem("BlackList" + i));
        document.write("
");
        document.write("" + info.value + "	");
        if (info.type == "username") {
            info.type = "用户名"
        }
        else {
            info.type = "关键字";
        }
        document.write("" + info.type + "	");
        document.write("<input type = 'button' value = '删除' class = 'deleteInfo btn btn-xs btn-danger'>	");
        document.write("
");
    }
}
document.write("
");
function addInfo(type) {
    var value = $.trim(document.getElementById("value").value);
    document.getElementById("value").value = "";
    if (type == "key") {
        value = value.toLowerCase();
    }
    if (value.length == 0) {
        return;
    }
    if (!localStorage.count) {
        localStorage.count = 1;
    }
    else {
        localStorage.count = Number(localStorage.count) + 1;
    }
    var info = {value: value, type: type};
    info = JSON.stringify(info);
    var id = Number(localStorage.count) - 1;
    localStorage.setItem("BlackList" + id, info);
    chrome.tabs.executeScript(null, {code: "localStorage.setItem('count', " + localStorage.count + ");"});
    chrome.tabs.executeScript(null, {code: "localStorage.setItem('BlackList" + id + "', '" + info + "');"});
    var row = document.getElementById("BlackList").insertRow(Number(id) + 1);
    row.insertCell(0).innerHTML = value;
    if (type == "username") {
        row.insertCell(1).innerHTML = "用户名";
    }
    else {
        row.insertCell(1).innerHTML = "关键字";
    }
    row.insertCell(2).innerHTML = "<input type = 'button' value = '删除' class = 'deleteInfo btn btn-xs btn-danger'>";

}
function deleteInfo(r) {
    var row = r.parentNode.parentNode.rowIndex;
    for (var i = Number(row) - 1; i < Number(localStorage.count) - 1; i++) {
        localStorage.setItem("BlackList" + i, localStorage.getItem("BlackList" + (Number(i) + 1)));
    }
    var id = (Number(localStorage.count) - 1);
    localStorage.removeItem("BlackList" + id);
    localStorage.count = Number(localStorage.count) - 1;
    document.getElementById("BlackList").deleteRow(row);
    chrome.tabs.executeScript(null, {code: "localStorage.setItem('count', " + localStorage.count + ");"});
    for (var i = 0; i < localStorage.count; i++) {
        var temp = localStorage.getItem("BlackList" + i);
        chrome.tabs.executeScript(null, {code: "localStorage.setItem('BlackList" + i + "', '" + temp + "');"});
    }
}
function addUser() {
    addInfo("username");
}
function addKey() {
    addInfo("key");
}
$("#addUser").click(function () {
    addUser();
});
$("#addKey").click(function () {
    addKey();
});
$("#BlackList").on("click", ".deleteInfo", function () {
    deleteInfo(this);
});<|endoftext|>


<commit_before>import _ from 'lodash';
import d3 from 'd3';
import stringify from 'json-stringify-pretty-compact';

import {tileSize, repositionSpeed, DEV_MODE, animationStepDuration, animationStepDurationMin, animationStepDurationMax, margin, stockColumns} from './config';
import * as config from './config';
import * as particles from './particles';
import * as simulation from './simulation';
import {Stock} from './stock';
import * as tile from './tile';
import {TransitionHeatmap} from './transition_heatmap';
import {Level} from './level';
import {WinningStatus} from './winning_status';
import {bindDrag} from './drag_and_drop';

function tileSimpler(name, i, j) {
  const tileClass = tile[name];
  return new tile.Tile(tileClass, 0, false, i, j);
}

export class Board {
  constructor(level, svg, helper, titleManager, storage) {
    this.level = level;
    this.svg = svg;
    this.tileMatrix = [];
    if (DEV_MODE) {
      this.transitionHeatmap = new TransitionHeatmap(helper);
    }
    this.helper = helper;
    this.titleManager = titleManager;
    this.storage = storage;
    this.animationStepDuration = animationStepDuration;
    this.stock = new Stock(svg, this);
  }

  reset() {
    // Reset detection
    // TODO(pathes): make a separate component for detection % and next level button
    d3.select('.top-bar__detection__value').html('0%');
    d3.select('.top-bar__detection__caption').html('detection');
    d3.select('.top-bar__detection').classed('top-bar__detection--success', false);
    d3.select('.top-bar__detection').on('click', _.noop);

    // set tileMatrix according to the recipe
    this.clearTileMatrix();
    this.fillTileMatrix(this.level.tileRecipes);

    // Initial drawing
    this.setHeaderTexts();
    this.resizeSvg();
    this.drawBackground();
    this.drawBoard();
    this.stock.elementCount(this.level);
    this.stock.drawStock();
  }

  clearTileMatrix() {
    // Create matrix filled with Vacuum
    this.tileMatrix = _.range(this.level.width).map((i) =>
        _.range(this.level.height).map((j) =>
            new tile.Tile(tile.Vacuum, 0, false, i, j)
        )
    );
  }

  fillTileMatrix(tileRecipes) {
    _.each(tileRecipes, (tileRecipe) => {
      this.tileMatrix[tileRecipe.i][tileRecipe.j] = new tile.Tile(
        tile[tileRecipe.name],
        tileRecipe.rotation || 0,
        !!tileRecipe.frozen,
        tileRecipe.i,
        tileRecipe.j
      );
    });
  }

  setHeaderTexts() {
    const textBefore = (level) =>
      level.texts && level.texts.before ? `: "${level.texts.before}"` : '';

    this.titleManager.setTitle(
      `[${this.level.group}] ${this.level.i}. ${this.level.name}${textBefore(this.level)}`);

    let description;
    if (this.level.detectorsToFeed === 0) {
      description = 'GOAL: No goals! Freedom to do whatever you like. :)';
    } else if (this.level.detectorsToFeed === 1) {
      description = `GOAL: Make the photon fall into a detector, with ${(100 * this.level.requiredDetectionProbability).toFixed(0)}% chance.`;
    } else {
      description = `GOAL: Make the photon fall into ${this.level.detectorsToFeed} detectors, some probability to each, total of ${(100 * this.level.requiredDetectionProbability).toFixed(0)}%.`;
    }
    this.titleManager.setDescription(description);
  }

  resizeSvg() {
    const width = this.level.width + 2 * margin + stockColumns;
    const height = this.level.height + 2 * margin;
    // top left width height
    this.svg.attr('viewBox', `${-tileSize} ${-tileSize} ${tileSize * width} ${tileSize * height}`);
  }

  /**
   * Draw background - a grid of squares.
   */
  drawBackground() {

    this.svg.select('.background').remove();

    this.svg
      .append('g')
      .attr('class', 'background')
      .selectAll('.background-tile')
      .data(_.chain(this.tileMatrix)  // NOTE I cannot just clone due to d.x and d.y getters
        .flatten()
        .map((d) => new tile.Tile(d.type, d.rotation, d.frozen, d.i, d.j))
        .value()
      )
      .enter()
      .append('rect')
      .attr({
        'class': 'background-tile',
        x: (d) => d.x,
        y: (d) => d.y,
        width: tileSize,
        height: tileSize,
      });
  }

  showTileHelper(d) {

    // temporary hover
    this.titleManager.displayMessage(
      `this is: ${d.type.desc.name}`,
      'hover');

    // things below currently don't work (due to interface changes)
    if (DEV_MODE) {
      this.transitionHeatmap.updateFromTensor(d.transitionAmplitudes.map);
    }
    this.helper.select('#element-name').html(d.type.desc.name);
    this.helper.select('#element-summary').html(d.type.desc.summary);
    this.helper.select('#element-flavour').html(d.type.desc.flavour ? `"${d.type.desc.flavour}"` : '');
  }

  /**
   * Draw board: tiles and their hitboxes.
   * Also, bind click and drag events.
   */
  drawBoard() {

    this.svg.select('.board').remove();
    this.boardGroup = this.svg
      .append('g')
      .attr('class', 'board');

    _.flatten(this.tileMatrix)
        .filter((t) => t.type !== tile.Vacuum)
        .forEach((t) => this.addTile(t));
  }

  addTile(tileObj) {

    this.removeTile(tileObj.i, tileObj.j);
    this.tileMatrix[tileObj.i][tileObj.j] = tileObj;

    const tileSelection = this.boardGroup
      .datum(tileObj)
      .append('g')
        .attr('class', 'tile')
        .attr('transform', (d) => `translate(${d.x + tileSize / 2},${d.y + tileSize / 2})`);

    tileObj.g = tileSelection;
    // DOM element for g
    tileObj.node = tileSelection[0][0];

    // frozen background
    tileSelection
      .append('rect')
        .attr('class', (d) => d.frozen ? 'frost frost-frozen' : 'frost frost-nonfrozen')
        .attr('x', -tileSize / 2)
        .attr('y', -tileSize / 2)
        .attr('width', tileSize)
        .attr('height', tileSize);

    tileObj.draw();

    // hitbox
    tileSelection
      .append('use')
        .attr('xlink:href', '#hitbox')
        .attr('class', 'hitbox');

    this.clickBehavior(tileSelection, this);
    bindDrag(tileSelection, this, this.stock);

  }

  removeTile(i, j) {
    if (this.tileMatrix[i][j].node) {
      this.tileMatrix[i][j].node.remove();
    }
    this.tileMatrix[i][j] = new tile.Tile(tile.Vacuum, 0, false, i, j);
  }

  clickBehavior(tileSelection, board) {
    tileSelection.select('.hitbox').on('click', (d) => {

      // Avoid rotation when dragged
      if (d3.event.defaultPrevented) {
        return;
      }

      // Avoid rotation when frozen
      if (d.frozen) {
        if (d.tileName === 'Source') {
          board.play();
        }
        return;
      }

      if (board.particleAnimation) {
        board.stop();
        board.titleManager.displayMessage(
          'Experiment disturbed! Quantum states are fragile...',
          'failure');
      }

      d.rotate();
      board.showTileHelper(d);

    })
    .on('mouseover', (d) => this.showTileHelper(d));

    // freeze/unfreeze traingular button
    if (this.level.group === 'A Dev' || DEV_MODE) {
      tileSelection
        .append('path')
          .attr('class', 'triangular')
          .attr('d', 'M 0 0 L -1 0 L 0 1 Z')
          .attr('transform', `translate(${tileSize / 2},${-tileSize / 2}) scale(${tileSize / 4})`)
          .on('click', (d) => {
            d.frozen = !d.frozen;
            d.g.select('.frost')
              .attr('class', d.frozen ? 'frost frost-frozen' : 'frost frost-nonfrozen');
          });
    }
  }

  /**
   * Set up animation controls - bind events to buttons
   * @param animationControls d3-wrapped container for control buttons
   */
  setAnimationControls(animationControls) {
    // Don't let d3 bind clicked element as `this` to methods.
    const board = this;
    animationControls.select('.play')
      .on('click', this.play.bind(board));
    animationControls.select('.stop')
      .on('click', this.stop.bind(board));
    animationControls.select('.backward')
      .style('opacity', 0.4)  // as not yet implemented
      .on('click', this.backward.bind(board));
    animationControls.select('.forward')
      .on('click', this.forward.bind(board));
    animationControls.select('.reset')
      .on('click', () => {
        // to reset it to scratch, not only - to the last save
        this.level.initialStock = this.level.initialStock || {};
        this.level.tileRecipes
          .filter((tileRecipe) => !tileRecipe.frozen)
          .forEach((tileRecipe) => {
            this.level.initialStock[tileRecipe.name] = (this.level.initialStock[tileRecipe.name] || 0) + 1;
          });
        this.level.tileRecipes = this.level.tileRecipes
          .filter((tileRecipe) => tileRecipe.frozen);
        this.reset();
      });
    animationControls.select('#download')
      .on('click', function () {
        board.clipBoard(this);
      });

    const durationToSlider = d3.scale.log()
      .domain([animationStepDurationMax, animationStepDurationMin])
      .range([0, 1]);

    animationControls.select('#speed')
      .on('click', function () {
        const sliderWidth = this.getBoundingClientRect().width;
        const mouseX = d3.mouse(this)[0];
        board.animationStepDuration = durationToSlider.invert(mouseX/sliderWidth);
        window.console.log(`New speed: ${(1000/board.animationStepDuration).toFixed(2)} tiles/s`);

        d3.select(this).select('rect')
          .attr('x', 32 * mouseX/sliderWidth - 1);
      });

  }

  /**
   * Generate history.
   */
  generateHistory() {

    // non-deterministic quantum simulation
    // (for animations)
    this.simulationQ = new simulation.Simulation(this.tileMatrix, 'logging');
    this.simulationQ.initialize();
    this.simulationQ.propagateToEnd(true);

    this.winningStatus = new WinningStatus(this.tileMatrix);
    this.winningStatus.run();
    this.winningStatus.compareToObjectives(this.level.requiredDetectionProbability, this.level.detectorsToFeed);
    window.console.log(this.winningStatus);

  }

  /**
   * Generate footer callback.
   * @returns {Function} footer callback
   */
  generateFooterCallback() {

    this.titleManager.displayMessage(
      'Experiment in progress...',
      'progress');

    const footerCallback = () => {
      d3.select('.top-bar__detection__value').html(`${(100 * this.winningStatus.totalProbAtDets).toFixed(0)}%`);

      this.titleManager.displayMessage(
        this.winningStatus.message,
        this.winningStatus.isWon ? 'success' : 'failure'
      );

      if (this.winningStatus.isWon) {
        d3.select('.top-bar__detection').classed('top-bar__detection--success', true);
        if (this.level.group === 'Game') {
          // TODO(pathes): make a separate component for detection % and next level button
          d3.select('.top-bar__detection__caption').html('next level »');
          d3.select('.top-bar__detection').on('click', () => {
            this.loadLevel(this.level.next);
          });
        }
      }

      this.particleAnimation = null;
    };

    return footerCallback;
  }

  /**
   * Play animation. Generate history if necessary.
   */
  play() {
    if (!this.particleAnimation) {
      this.generateHistory();
      this.particleAnimation = new particles.SVGParticleAnimation(
        this,
        this.simulationQ.history,
        this.simulationQ.measurementHistory,
        this.winningStatus.absorptionProbabilities,
        this.generateFooterCallback());
      this.particleAnimation.initialize();
    }
    if (this.particleAnimation.playing) {
      this.particleAnimation.pause();
    } else {
      this.particleAnimation.play();
    }
  }

  stop() {
    if (this.particleAnimation) {
      this.particleAnimation.stop();
      this.particleAnimation = null;
    }
  }

  forward() {
    if (this.particleAnimation) {
      if (this.particleAnimation.playing) {
        this.particleAnimation.pause();
      } else {
        this.particleAnimation.forward();
      }
    }
  }

  backward() {
    if (this.particleAnimation) {
      if (this.particleAnimation.playing) {
        this.particleAnimation.pause();
      } else {
        this.particleAnimation.backward();
      }
    }
  }

  exportBoard() {
    // should match interface from level.js
    return {
      name:   this.level.name,
      group:  this.level.group,
      width:  this.level.width,
      height: this.level.height,
      tiles:  _.chain(this.tileMatrix)
        .flatten()
        .filter((d) => d.tileName !== 'Vacuum')
        .map((d) => ({
          i: d.i,
          j: d.j,
          name: d.tileName,
          rotation: d.rotation,
          frozen: d.frozen,
        })),
      stock: this.stock.stock,
    };
  }

  clipBoard(link) {
    const levelJSON = stringify(this.exportBoard(), {maxLength: 100, indent: 2});
    link.href = `data:text/plain;charset=utf-8,${encodeURIComponent(levelJSON)}`;
    window.console.log(levelJSON);
  }

  loadLevel(levelRecipe, checkStorage = true) {

    let levelToLoad;

    if (!checkStorage) {
      levelToLoad = levelRecipe;
    } else {
      // save progress
      // TODO use hash of sorted elements so to ensure levels are unique?
      this.storage.setItem(
        `${this.level.group} ${this.level.name}`,
         stringify(this.exportBoard())
      );

      if (this.storage.hasOwnProperty(`${levelRecipe.group} ${levelRecipe.name}`)) {
        levelToLoad = JSON.parse(this.storage.getItem(`${levelRecipe.group} ${levelRecipe.name}`));
      } else {
        levelToLoad = levelRecipe;
      }
    }

    this.level = new Level(levelToLoad);
    this.level.i = levelRecipe.i;
    this.level.next = levelRecipe.next;
    this.reset();

  }
}
<commit_msg>fix(board) save preserves tests and winning conditions<commit_after>import _ from 'lodash';
import d3 from 'd3';
import stringify from 'json-stringify-pretty-compact';

import {tileSize, repositionSpeed, DEV_MODE, animationStepDuration, animationStepDurationMin, animationStepDurationMax, margin, stockColumns} from './config';
import * as config from './config';
import * as particles from './particles';
import * as simulation from './simulation';
import {Stock} from './stock';
import * as tile from './tile';
import {TransitionHeatmap} from './transition_heatmap';
import {Level} from './level';
import {WinningStatus} from './winning_status';
import {bindDrag} from './drag_and_drop';

function tileSimpler(name, i, j) {
  const tileClass = tile[name];
  return new tile.Tile(tileClass, 0, false, i, j);
}

export class Board {
  constructor(level, svg, helper, titleManager, storage) {
    this.level = level;
    this.svg = svg;
    this.tileMatrix = [];
    if (DEV_MODE) {
      this.transitionHeatmap = new TransitionHeatmap(helper);
    }
    this.helper = helper;
    this.titleManager = titleManager;
    this.storage = storage;
    this.animationStepDuration = animationStepDuration;
    this.stock = new Stock(svg, this);
  }

  reset() {
    // Reset detection
    // TODO(pathes): make a separate component for detection % and next level button
    d3.select('.top-bar__detection__value').html('0%');
    d3.select('.top-bar__detection__caption').html('detection');
    d3.select('.top-bar__detection').classed('top-bar__detection--success', false);
    d3.select('.top-bar__detection').on('click', _.noop);

    // set tileMatrix according to the recipe
    this.clearTileMatrix();
    this.fillTileMatrix(this.level.tileRecipes);

    // Initial drawing
    this.setHeaderTexts();
    this.resizeSvg();
    this.drawBackground();
    this.drawBoard();
    this.stock.elementCount(this.level);
    this.stock.drawStock();
  }

  clearTileMatrix() {
    // Create matrix filled with Vacuum
    this.tileMatrix = _.range(this.level.width).map((i) =>
        _.range(this.level.height).map((j) =>
            new tile.Tile(tile.Vacuum, 0, false, i, j)
        )
    );
  }

  fillTileMatrix(tileRecipes) {
    _.each(tileRecipes, (tileRecipe) => {
      this.tileMatrix[tileRecipe.i][tileRecipe.j] = new tile.Tile(
        tile[tileRecipe.name],
        tileRecipe.rotation || 0,
        !!tileRecipe.frozen,
        tileRecipe.i,
        tileRecipe.j
      );
    });
  }

  setHeaderTexts() {
    const textBefore = (level) =>
      level.texts && level.texts.before ? `: "${level.texts.before}"` : '';

    this.titleManager.setTitle(
      `[${this.level.group}] ${this.level.i}. ${this.level.name}${textBefore(this.level)}`);

    let description;
    if (this.level.detectorsToFeed === 0) {
      description = 'GOAL: No goals! Freedom to do whatever you like. :)';
    } else if (this.level.detectorsToFeed === 1) {
      description = `GOAL: Make the photon fall into a detector, with ${(100 * this.level.requiredDetectionProbability).toFixed(0)}% chance.`;
    } else {
      description = `GOAL: Make the photon fall into ${this.level.detectorsToFeed} detectors, some probability to each, total of ${(100 * this.level.requiredDetectionProbability).toFixed(0)}%.`;
    }
    this.titleManager.setDescription(description);
  }

  resizeSvg() {
    const width = this.level.width + 2 * margin + stockColumns;
    const height = this.level.height + 2 * margin;
    // top left width height
    this.svg.attr('viewBox', `${-tileSize} ${-tileSize} ${tileSize * width} ${tileSize * height}`);
  }

  /**
   * Draw background - a grid of squares.
   */
  drawBackground() {

    this.svg.select('.background').remove();

    this.svg
      .append('g')
      .attr('class', 'background')
      .selectAll('.background-tile')
      .data(_.chain(this.tileMatrix)  // NOTE I cannot just clone due to d.x and d.y getters
        .flatten()
        .map((d) => new tile.Tile(d.type, d.rotation, d.frozen, d.i, d.j))
        .value()
      )
      .enter()
      .append('rect')
      .attr({
        'class': 'background-tile',
        x: (d) => d.x,
        y: (d) => d.y,
        width: tileSize,
        height: tileSize,
      });
  }

  showTileHelper(d) {

    // temporary hover
    this.titleManager.displayMessage(
      `this is: ${d.type.desc.name}`,
      'hover');

    // things below currently don't work (due to interface changes)
    if (DEV_MODE) {
      this.transitionHeatmap.updateFromTensor(d.transitionAmplitudes.map);
    }
    this.helper.select('#element-name').html(d.type.desc.name);
    this.helper.select('#element-summary').html(d.type.desc.summary);
    this.helper.select('#element-flavour').html(d.type.desc.flavour ? `"${d.type.desc.flavour}"` : '');
  }

  /**
   * Draw board: tiles and their hitboxes.
   * Also, bind click and drag events.
   */
  drawBoard() {

    this.svg.select('.board').remove();
    this.boardGroup = this.svg
      .append('g')
      .attr('class', 'board');

    _.flatten(this.tileMatrix)
        .filter((t) => t.type !== tile.Vacuum)
        .forEach((t) => this.addTile(t));
  }

  addTile(tileObj) {

    this.removeTile(tileObj.i, tileObj.j);
    this.tileMatrix[tileObj.i][tileObj.j] = tileObj;

    const tileSelection = this.boardGroup
      .datum(tileObj)
      .append('g')
        .attr('class', 'tile')
        .attr('transform', (d) => `translate(${d.x + tileSize / 2},${d.y + tileSize / 2})`);

    tileObj.g = tileSelection;
    // DOM element for g
    tileObj.node = tileSelection[0][0];

    // frozen background
    tileSelection
      .append('rect')
        .attr('class', (d) => d.frozen ? 'frost frost-frozen' : 'frost frost-nonfrozen')
        .attr('x', -tileSize / 2)
        .attr('y', -tileSize / 2)
        .attr('width', tileSize)
        .attr('height', tileSize);

    tileObj.draw();

    // hitbox
    tileSelection
      .append('use')
        .attr('xlink:href', '#hitbox')
        .attr('class', 'hitbox');

    this.clickBehavior(tileSelection, this);
    bindDrag(tileSelection, this, this.stock);

  }

  removeTile(i, j) {
    if (this.tileMatrix[i][j].node) {
      this.tileMatrix[i][j].node.remove();
    }
    this.tileMatrix[i][j] = new tile.Tile(tile.Vacuum, 0, false, i, j);
  }

  clickBehavior(tileSelection, board) {
    tileSelection.select('.hitbox').on('click', (d) => {

      // Avoid rotation when dragged
      if (d3.event.defaultPrevented) {
        return;
      }

      // Avoid rotation when frozen
      if (d.frozen) {
        if (d.tileName === 'Source') {
          board.play();
        }
        return;
      }

      if (board.particleAnimation) {
        board.stop();
        board.titleManager.displayMessage(
          'Experiment disturbed! Quantum states are fragile...',
          'failure');
      }

      d.rotate();
      board.showTileHelper(d);

    })
    .on('mouseover', (d) => this.showTileHelper(d));

    // freeze/unfreeze traingular button
    if (this.level.group === 'A Dev' || DEV_MODE) {
      tileSelection
        .append('path')
          .attr('class', 'triangular')
          .attr('d', 'M 0 0 L -1 0 L 0 1 Z')
          .attr('transform', `translate(${tileSize / 2},${-tileSize / 2}) scale(${tileSize / 4})`)
          .on('click', (d) => {
            d.frozen = !d.frozen;
            d.g.select('.frost')
              .attr('class', d.frozen ? 'frost frost-frozen' : 'frost frost-nonfrozen');
          });
    }
  }

  /**
   * Set up animation controls - bind events to buttons
   * @param animationControls d3-wrapped container for control buttons
   */
  setAnimationControls(animationControls) {
    // Don't let d3 bind clicked element as `this` to methods.
    const board = this;
    animationControls.select('.play')
      .on('click', this.play.bind(board));
    animationControls.select('.stop')
      .on('click', this.stop.bind(board));
    animationControls.select('.backward')
      .style('opacity', 0.4)  // as not yet implemented
      .on('click', this.backward.bind(board));
    animationControls.select('.forward')
      .on('click', this.forward.bind(board));
    animationControls.select('.reset')
      .on('click', () => {
        // to reset it to scratch, not only - to the last save
        this.level.initialStock = this.level.initialStock || {};
        this.level.tileRecipes
          .filter((tileRecipe) => !tileRecipe.frozen)
          .forEach((tileRecipe) => {
            this.level.initialStock[tileRecipe.name] = (this.level.initialStock[tileRecipe.name] || 0) + 1;
          });
        this.level.tileRecipes = this.level.tileRecipes
          .filter((tileRecipe) => tileRecipe.frozen);
        this.reset();
      });
    animationControls.select('#download')
      .on('click', function () {
        board.clipBoard(this);
      });

    const durationToSlider = d3.scale.log()
      .domain([animationStepDurationMax, animationStepDurationMin])
      .range([0, 1]);

    animationControls.select('#speed')
      .on('click', function () {
        const sliderWidth = this.getBoundingClientRect().width;
        const mouseX = d3.mouse(this)[0];
        board.animationStepDuration = durationToSlider.invert(mouseX/sliderWidth);
        window.console.log(`New speed: ${(1000/board.animationStepDuration).toFixed(2)} tiles/s`);

        d3.select(this).select('rect')
          .attr('x', 32 * mouseX/sliderWidth - 1);
      });

  }

  /**
   * Generate history.
   */
  generateHistory() {

    // non-deterministic quantum simulation
    // (for animations)
    this.simulationQ = new simulation.Simulation(this.tileMatrix, 'logging');
    this.simulationQ.initialize();
    this.simulationQ.propagateToEnd(true);

    this.winningStatus = new WinningStatus(this.tileMatrix);
    this.winningStatus.run();
    this.winningStatus.compareToObjectives(this.level.requiredDetectionProbability, this.level.detectorsToFeed);
    window.console.log(this.winningStatus);

  }

  /**
   * Generate footer callback.
   * @returns {Function} footer callback
   */
  generateFooterCallback() {

    this.titleManager.displayMessage(
      'Experiment in progress...',
      'progress');

    const footerCallback = () => {
      d3.select('.top-bar__detection__value').html(`${(100 * this.winningStatus.totalProbAtDets).toFixed(0)}%`);

      this.titleManager.displayMessage(
        this.winningStatus.message,
        this.winningStatus.isWon ? 'success' : 'failure'
      );

      if (this.winningStatus.isWon) {
        d3.select('.top-bar__detection').classed('top-bar__detection--success', true);
        if (this.level.group === 'Game') {
          // TODO(pathes): make a separate component for detection % and next level button
          d3.select('.top-bar__detection__caption').html('next level »');
          d3.select('.top-bar__detection').on('click', () => {
            this.loadLevel(this.level.next);
          });
        }
      }

      this.particleAnimation = null;
    };

    return footerCallback;
  }

  /**
   * Play animation. Generate history if necessary.
   */
  play() {
    if (!this.particleAnimation) {
      this.generateHistory();
      this.particleAnimation = new particles.SVGParticleAnimation(
        this,
        this.simulationQ.history,
        this.simulationQ.measurementHistory,
        this.winningStatus.absorptionProbabilities,
        this.generateFooterCallback());
      this.particleAnimation.initialize();
    }
    if (this.particleAnimation.playing) {
      this.particleAnimation.pause();
    } else {
      this.particleAnimation.play();
    }
  }

  stop() {
    if (this.particleAnimation) {
      this.particleAnimation.stop();
      this.particleAnimation = null;
    }
  }

  forward() {
    if (this.particleAnimation) {
      if (this.particleAnimation.playing) {
        this.particleAnimation.pause();
      } else {
        this.particleAnimation.forward();
      }
    }
  }

  backward() {
    if (this.particleAnimation) {
      if (this.particleAnimation.playing) {
        this.particleAnimation.pause();
      } else {
        this.particleAnimation.backward();
      }
    }
  }

  exportBoard() {
    // should match interface from level.js
    return {
      name:   this.level.name,
      group:  this.level.group,
      width:  this.level.width,
      height: this.level.height,
      tiles:  _.chain(this.tileMatrix)
        .flatten()
        .filter((d) => d.tileName !== 'Vacuum')
        .map((d) => ({
          i: d.i,
          j: d.j,
          name: d.tileName,
          rotation: d.rotation,
          frozen: d.frozen,
        })),
      stock:                        this.stock.stock,
      requiredDetectionProbability: this.level.requiredDetectionProbability,
      detectorsToFeed:              this.level.detectorsToFeed,
      texts:                        this.level.texts,
    };
  }

  clipBoard(link) {
    const levelJSON = stringify(this.exportBoard(), {maxLength: 100, indent: 2});
    link.href = `data:text/plain;charset=utf-8,${encodeURIComponent(levelJSON)}`;
    window.console.log(levelJSON);
  }

  loadLevel(levelRecipe, checkStorage = true) {

    let levelToLoad;

    if (!checkStorage) {
      levelToLoad = levelRecipe;
    } else {
      // save progress
      // TODO use hash of sorted elements so to ensure levels are unique?
      this.storage.setItem(
        `${this.level.group} ${this.level.name}`,
         stringify(this.exportBoard())
      );

      if (this.storage.hasOwnProperty(`${levelRecipe.group} ${levelRecipe.name}`)) {
        levelToLoad = JSON.parse(this.storage.getItem(`${levelRecipe.group} ${levelRecipe.name}`));
      } else {
        levelToLoad = levelRecipe;
      }
    }

    this.level = new Level(levelToLoad);
    this.level.i = levelRecipe.i;
    this.level.next = levelRecipe.next;
    this.reset();

  }
}
<|endoftext|>


<commit_before>import React, { useState } from "react";
import classes from "./Marketplace.module.css";
import Block from "../../components/UI/Block/Block";
import TrendingSearches from "../../components/TrendingSearches/TrendingSearches";
import RecentBuys from "../../components/RecentBuys/RecentBuysList";
import Button from "../../components/UI/Button/Button";
import ChartCard from "../../components/ChartCard/ChartCard";

const Marketplace = (props) => {
  const [searchEntry, setSearchEntry] = useState("");
  const [purchaseAmount, setPurchaseAmount] = useState(0);
  const [loadingData, setLoadingData] = useState(false);
  const [chartData, setChartData] = useState();

  const onSearchChange = (e) => {
    setSearchEntry(e.target.value);
  };

  const onSearchEntered = () => {
    if (searchEntry.trim() === "") {
      console.log("empty");
      return;
    }
    setLoadingData(true);
    console.log("setting loadingData TRUE");
    fetchContextData(searchEntry)
      .then((data) => {
        console.log(data);
        setChartData(data);
      })
      .then(() => {
        setLoadingData(false);
        console.log("setting loadingData FALSE");
      });
  };

  const fetchContextData = async (entry) => {
    const formattedData = await fetch(`./contextData?search_term=${entry}`)
      .then((response) => response.json())
      .then((data) => {
        const averagedData = data.map((datapoint) => datapoint / 24);
        return formatChartData(averagedData);
      });

    console.log("fetchContextData: formattedData: ");
    console.log(formattedData);
    return formattedData;
  };

  const formatChartData = (data) => {
    const chartData = [];
    chartData.push(["x", "Popularity"]);
    for (let i = 0; i < data.length; i++) {
      chartData.push([i, data[i]]);
    }
    return chartData;
  };

  let chartSpace =
search something!
;

  if (loadingData === true) {
    chartSpace =
 loooading
;
  }

  if (chartData !== undefined) {
    chartSpace = (
      <ChartCard
        chartInfo={{
          haxis: "Time",
          vaxis: "Net Worth",
          data: formatChartData(chartData),
        }}
      ></ChartCard>
    );
  }

  // if (chartData !== undefined && loadingData === false) {
  //   formatChartData(chartData);
  //   chartSpace = (
  //     <ChartCard
  //       chartInfo={{
  //         haxis: "Time",
  //         vaxis: "Net Worth",
  //         data: formatChartData(),
  //       }}
  //     ></ChartCard>
  //   );
  // }

  // const chartSpace = loadingData ? (
  //
Loading

  // ) : (
  //   <ChartCard
  //     chartInfo={{
  //       haxis: "Time",
  //       vaxis: "Net Worth",
  //       data: formatChartData(),
  //     }}
  //   ></ChartCard>
  // );

  return (

          <input
            className={classes.SearchInput}
            placeholder="Search a trend"
            onChange={(e) => onSearchChange(e)}
          ></input>
          <Button inverted padding="3px 20px" onClick={onSearchEntered}>
            Search
          </Button>

        <Block className={classes.ChartContainer}>{chartSpace}</Block>

"search query"

            Amount to purchase:

              t$ <input></input>

            Currently available:
            t$1234

          <Button>Confirm Purchase</Button>

Trending searches

          <Block className={classes.Block}>
            <TrendingSearches
              searches={props.trendingSearches}
            ></TrendingSearches>
          </Block>

What your team is buying:

          <Block className={classes.Block}>
            <RecentBuys buys={props.recentBuys}></RecentBuys>
          </Block>

  );
};

export default Marketplace;
<commit_msg>DRemove comments<commit_after>import React, { useState } from "react";
import classes from "./Marketplace.module.css";
import Block from "../../components/UI/Block/Block";
import TrendingSearches from "../../components/TrendingSearches/TrendingSearches";
import RecentBuys from "../../components/RecentBuys/RecentBuysList";
import Button from "../../components/UI/Button/Button";
import ChartCard from "../../components/ChartCard/ChartCard";

const Marketplace = (props) => {
  const [searchEntry, setSearchEntry] = useState("");
  const [purchaseAmount, setPurchaseAmount] = useState(0);
  const [loadingData, setLoadingData] = useState(false);
  const [chartData, setChartData] = useState();

  const onSearchChange = (e) => {
    setSearchEntry(e.target.value);
  };

  const onSearchEntered = () => {
    if (searchEntry.trim() === "") {
      console.log("empty");
      return;
    }
    setLoadingData(true);
    console.log("setting loadingData TRUE");
    fetchContextData(searchEntry)
      .then((data) => {
        console.log("onSearchEntered: data: ");

        console.log(data);
        setChartData(data);
      })
      .then(() => {
        setLoadingData(false);
        console.log("setting loadingData FALSE");
      });
  };

  const fetchContextData = async (entry) => {
    const formattedData = await fetch(`./contextData?search_term=${entry}`)
      .then((response) => response.json())
      .then((data) => {
        const averagedData = data.map((datapoint) => datapoint / 24);
        return formatChartData(averagedData);
      });

    console.log("fetchContextData: formattedData: ");
    console.log(formattedData);
    return formattedData;
  };

  const formatChartData = (data) => {
    const chartData = [];
    chartData.push(["x", "Popularity"]);
    for (let i = 0; i < data.length; i++) {
      chartData.push([i, data[i]]);
    }
    return chartData;
  };

  let chartSpace =
search something!
;

  if (loadingData === true) {
    chartSpace =
 loooading
;
  }

  if (chartData !== undefined) {
    chartSpace = (
      <ChartCard
        chartInfo={{
          haxis: "Time",
          vaxis: "Net Worth",
          data: formatChartData(chartData),
        }}
      ></ChartCard>
    );
  }

  return (

          <input
            className={classes.SearchInput}
            placeholder="Search a trend"
            onChange={(e) => onSearchChange(e)}
          ></input>
          <Button inverted padding="3px 20px" onClick={onSearchEntered}>
            Search
          </Button>

        <Block className={classes.ChartContainer}>{chartSpace}</Block>

"search query"

            Amount to purchase:

              t$ <input></input>

            Currently available:
            t$1234

          <Button>Confirm Purchase</Button>

Trending searches

          <Block className={classes.Block}>
            <TrendingSearches
              searches={props.trendingSearches}
            ></TrendingSearches>
          </Block>

What your team is buying:

          <Block className={classes.Block}>
            <RecentBuys buys={props.recentBuys}></RecentBuys>
          </Block>

  );
};

export default Marketplace;
<|endoftext|>


<commit_before>export const handle500 =
  (err, req, res) => {
    log.error(`500 called, err: ${err}`);
    res.send('500 server error');
  };

export default handle500;
<commit_msg>add missing log import<commit_after>import log from 'magic-server-log';

export const handle500 =
  (err, req, res) => {
    log.error(`500 called, err: ${err}`);
    res.send('500 server error');
  };

export default handle500;
<|endoftext|>


<commit_before>export default class TrackedData {
  /**
   * Keeps track of the last change made to any data that is stored
   * @constructor
   * @param {Object} [validProperties=null] - An object containing valid property names as keys and that property's default value as values. If not provided, no validation will occur on property names
   */
  constructor(validProperties = null) {
    this._data = {
      ...validProperties
    };

    // {changedProperty: oldValue, ...}
    this._changes = {};

    this._validPropertiesNames = validProperties ? new Set(Object.keys(validProperties)) : null;
  }

  /**
   * Gets a copy of the value associated with the given name
   * @param {string} name - The name of the property to retrieve
   * @returns {*} a copy of the value of name
   */
  get(name) {
    this._assertValidProperty(name);

    return this._data[name];
  }

  /**
   * Stores the given value and tracks its old value as changed
   * Even if the same value is stored twice, a change will still be registered
   * @param {string} name - The name of the property to set
   * @param {*} value - The value to store
   */
  set(name, value) {
    this._assertValidProperty(name);

    if (value !== this._data[name]) {
      this._changes[name] = this._data[name];
    }

    this._data[name] = value;
  }

  /**
   * @returns {Boolean} Returns whether the given name is a valid name for this store. If no valid names were provided initially, this always returns true since then any name is valid
   * @param {String} name - The name of the property to check
   */
  has(name) {
    return this._validPropertiesNames ? this._validPropertiesNames.has(name) : true;
  }

  /**
   * Iterates through the names of the properties that have changed
   */
  *getChangedPropertyNames() {
    yield* Object.keys(this._changes);
    yield* this._changedTrackedDataProperties();
  }

  /**
   * Retrieves an object containing the name and old value
   * of each property that has been changed
   * @returns {Object} - Object where keys are the names of each changed property and values are the previous value of that property
   */
  getChangedOldValues() {
    const changed = {
      ...this._changes
    };

    for (let propName of this._changedTrackedDataProperties()) {
      if (!changed.hasOwnProperty(propName)) {
        changed[propName] = this.get(propName).getChangedOldValues();
      }
    }

    return changed;
  }

  /**
   * Retrieves an object containing the name and current values
   * of each property that has been changed
   * @returns {Object} - Object where keys are the names of each changed property and the values are the current value of that property
   */
  getChangedCurrentValues() {
    const changed = {};

    for (let propName of this._changedTrackedDataProperties()) {
      changed[propName] = this.get(propName).getChangedCurrentValues();
    }

    for (let propName of Object.keys(this._changes)) {
      changed[propName] = this.get(propName);
    }

    return changed;
  }

  /**
   * Clears out any recorded changes
   */
  clearChanges() {
    this._changes = {};

    for (let propName of this._changedTrackedDataProperties()) {
      this.get(propName).clearChanges();
    }
  }

  /**
   * Iterates through all the data property names currently defined
   */
  *[Symbol.iterator]() {
    for (let name of Object.keys(this._data)) {
      yield name;
    }
  }

  *_changedTrackedDataProperties() {
    for (let propName of Object.keys(this._data)) {
      const value = this.get(propName);
      if (value instanceof TrackedData) {
        if (!value.getChangedPropertyNames().next().done) {
          yield propName;
        }
      }
    }
  }

  _assertValidProperty(name) {
    if (!this.has(name)) {
      throw new Error("Cannot retrieve property '" + name + "'");
    }
  }
}
<commit_msg>Added hasChanged() and pretty()<commit_after>export default class TrackedData {
  /**
   * Keeps track of the last change made to any data that is stored
   * @constructor
   * @param {Object} [validProperties=null] - An object containing valid property names as keys and that property's default value as values. If not provided, no validation will occur on property names
   */
  constructor(validProperties = null) {
    this._data = {
      ...validProperties
    };

    // {changedProperty: oldValue, ...}
    this._changes = {};

    this._validPropertiesNames = validProperties ? new Set(Object.keys(validProperties)) : null;
  }

  /**
   * Gets a copy of the value associated with the given name
   * @param {string} name - The name of the property to retrieve
   * @returns {*} a copy of the value of name
   */
  get(name) {
    this._assertValidProperty(name);

    return this._data[name];
  }

  /**
   * Stores the given value and tracks its old value as changed
   * Even if the same value is stored twice, a change will still be registered
   * @param {string} name - The name of the property to set
   * @param {*} value - The value to store
   */
  set(name, value) {
    this._assertValidProperty(name);

    if (value !== this._data[name]) {
      this._changes[name] = this._data[name];
    }

    this._data[name] = value;
  }

  /**
   * @returns {Boolean} Returns whether the given name is a valid name for this store. If no valid names were provided initially, this always returns true since then any name is valid
   * @param {String} name - The name of the property to check
   */
  has(name) {
    return this._validPropertiesNames ? this._validPropertiesNames.has(name) : true;
  }

  /**
   * @returns {Boolean} Returns true if there is at least one changed property
   */
  hasChanges() {
    const changedNames = this.getChangedPropertyNames();
    return !changedNames.next().done;
  }

  /**
   * Iterates through the names of the properties that have changed
   */
  *getChangedPropertyNames() {
    yield* Object.keys(this._changes);
    yield* this._changedTrackedDataProperties();
  }

  /**
   * Retrieves an object containing the name and old value
   * of each property that has been changed
   * @returns {Object} - Object where keys are the names of each changed property and values are the previous value of that property
   */
  getChangedOldValues() {
    const changed = {
      ...this._changes
    };

    for (let propName of this._changedTrackedDataProperties()) {
      if (!changed.hasOwnProperty(propName)) {
        changed[propName] = this.get(propName).getChangedOldValues();
      }
    }

    return changed;
  }

  /**
   * Retrieves an object containing the name and current values
   * of each property that has been changed
   * @returns {Object} - Object where keys are the names of each changed property and the values are the current value of that property
   */
  getChangedCurrentValues() {
    const changed = {};

    for (let propName of this._changedTrackedDataProperties()) {
      changed[propName] = this.get(propName).getChangedCurrentValues();
    }

    for (let propName of Object.keys(this._changes)) {
      changed[propName] = this.get(propName);
    }

    return changed;
  }

  /**
   * Clears out any recorded changes
   */
  clearChanges() {
    this._changes = {};

    for (let propName of this._changedTrackedDataProperties()) {
      this.get(propName).clearChanges();
    }
  }

  /**
   * Iterates through all the data property names currently defined
   */
  *[Symbol.iterator]() {
    for (let name of Object.keys(this._data)) {
      yield name;
    }
  }

  pretty() {
    const obj = {};
    for (let key of this) {
      const value = this.get(key);
      if (value instanceof TrackedData) {
        obj[key] = value.pretty();
      }
      else {
        obj[key] = value;
      }
    }
    return obj;
  }

  *_changedTrackedDataProperties() {
    for (let propName of Object.keys(this._data)) {
      const value = this.get(propName);
      if (value instanceof TrackedData) {
        if (!value.getChangedPropertyNames().next().done) {
          yield propName;
        }
      }
    }
  }

  _assertValidProperty(name) {
    if (!this.has(name)) {
      throw new Error("Cannot retrieve property '" + name + "'");
    }
  }
}
<|endoftext|>


<commit_before>'use strict';
const webpack = require('webpack');
const glob = require('glob');
const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackInlineSourcePlugin = require('html-webpack-inline-source-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ImageminPlugin = require('imagemin-webpack-plugin').default;
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = function(env, argv) {
    env = env || {};
    const production = !!env.production;
    const optimizeImages = production || !!env.optimizeImages;

    const clean = [];
    if (optimizeImages) {
        console.log('Optimizing images (src/ui/images/settings/*.png)...');
        clean.push('images/settings');
    }

    const plugins = [
        new CleanWebpackPlugin(clean),
        new webpack.optimize.ModuleConcatenationPlugin(),
        new MiniCssExtractPlugin({
            filename: '[name].css'
        }),
        new HtmlWebpackPlugin({
            excludeAssets: [/.*\.main\.js/],
            excludeChunks: ['welcome'],
            template: 'settings/index.html',
            filename: path.resolve(__dirname, 'settings.html'),
            inject: true,
            inlineSource: production ? '.(js|css)$' : undefined,
            // inlineSource: '.(js|css)$',
            minify: production
                ? {
                      removeComments: true,
                      collapseWhitespace: true,
                      removeRedundantAttributes: true,
                      useShortDoctype: true,
                      removeEmptyAttributes: true,
                      removeStyleLinkTypeAttributes: true,
                      keepClosingSlash: true
                  }
                : false
        }),
        new HtmlWebpackPlugin({
            excludeAssets: [/.*\.main\.js/],
            excludeChunks: ['settings'],
            template: 'welcome/index.html',
            filename: path.resolve(__dirname, 'welcome.html'),
            inject: true,
            inlineSource: production ? '.(js|css)$' : undefined,
            // inlineSource: '.(js|css)$',
            minify: production
                ? {
                      removeComments: true,
                      collapseWhitespace: true,
                      removeRedundantAttributes: true,
                      useShortDoctype: true,
                      removeEmptyAttributes: true,
                      removeStyleLinkTypeAttributes: true,
                      keepClosingSlash: true
                  }
                : false
        }),
        new HtmlWebpackInlineSourcePlugin(),
        new ImageminPlugin({
            disable: !optimizeImages,
            externalImages: {
                context: path.resolve(__dirname, 'src/ui/images'),
                sources: glob.sync('src/ui/images/settings/*.png'),
                destination: path.resolve(__dirname, 'images')
            },
            gifsicle: null,
            jpegtran: null,
            optipng: null,
            pngquant: {
                quality: '85-100',
                speed: production ? 1 : 10
            },
            svgo: null
        })
    ];

    return {
        context: path.resolve(__dirname, 'src/ui'),
        // This is ugly having main.scss on both bundles, but if it is added separately it will generate a js bundle :(
        entry: {
            settings: ['./settings/index.ts', './scss/main.scss'],
            welcome: ['./welcome/index.ts', './scss/main.scss']
            // main: ['./scss/main.scss']
        },
        mode: production ? 'production' : 'development',
        devtool: !production ? 'eval-source-map' : undefined,
        output: {
            filename: '[name].js',
            path: path.resolve(__dirname, 'out/ui'),
            publicPath: '{{root}}/out/ui/'
        },
        optimization: {
            splitChunks: {
                cacheGroups: {
                    styles: {
                        name: 'styles',
                        test: /\.css$/,
                        chunks: 'all',
                        enforce: true
                    }
                }
            }
        },
        resolve: {
            extensions: ['.tsx', '.ts', '.js'],
            modules: [path.resolve(__dirname, 'src/ui'), 'node_modules']
        },
        module: {
            rules: [
                {
                    test: /\.tsx?$/,
                    use: {
                        loader: 'ts-loader',
                        options: {
                            configFile: 'ui.tsconfig.json'
                        }
                    },
                    exclude: /node_modules/
                },
                {
                    test: /\.scss$/,
                    use: [
                        {
                            loader: MiniCssExtractPlugin.loader
                        },
                        {
                            loader: 'css-loader',
                            options: {
                                minimize: production,
                                sourceMap: !production,
                                url: false
                            }
                        },
                        {
                            loader: 'sass-loader',
                            options: {
                                sourceMap: !production
                            }
                        }
                    ],
                    exclude: /node_modules/
                }
            ]
        },
        plugins: plugins
    };
};
<commit_msg>Removes unneeded plugin<commit_after>'use strict';
const glob = require('glob');
const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackInlineSourcePlugin = require('html-webpack-inline-source-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ImageminPlugin = require('imagemin-webpack-plugin').default;
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = function(env, argv) {
    env = env || {};
    const production = !!env.production;
    const optimizeImages = production || !!env.optimizeImages;

    const clean = [];
    if (optimizeImages) {
        console.log('Optimizing images (src/ui/images/settings/*.png)...');
        clean.push('images/settings');
    }

    const plugins = [
        new CleanWebpackPlugin(clean),
        new MiniCssExtractPlugin({
            filename: '[name].css'
        }),
        new HtmlWebpackPlugin({
            excludeAssets: [/.*\.main\.js/],
            excludeChunks: ['welcome'],
            template: 'settings/index.html',
            filename: path.resolve(__dirname, 'settings.html'),
            inject: true,
            inlineSource: production ? '.(js|css)$' : undefined,
            // inlineSource: '.(js|css)$',
            minify: production
                ? {
                      removeComments: true,
                      collapseWhitespace: true,
                      removeRedundantAttributes: true,
                      useShortDoctype: true,
                      removeEmptyAttributes: true,
                      removeStyleLinkTypeAttributes: true,
                      keepClosingSlash: true
                  }
                : false
        }),
        new HtmlWebpackPlugin({
            excludeAssets: [/.*\.main\.js/],
            excludeChunks: ['settings'],
            template: 'welcome/index.html',
            filename: path.resolve(__dirname, 'welcome.html'),
            inject: true,
            inlineSource: production ? '.(js|css)$' : undefined,
            // inlineSource: '.(js|css)$',
            minify: production
                ? {
                      removeComments: true,
                      collapseWhitespace: true,
                      removeRedundantAttributes: true,
                      useShortDoctype: true,
                      removeEmptyAttributes: true,
                      removeStyleLinkTypeAttributes: true,
                      keepClosingSlash: true
                  }
                : false
        }),
        new HtmlWebpackInlineSourcePlugin(),
        new ImageminPlugin({
            disable: !optimizeImages,
            externalImages: {
                context: path.resolve(__dirname, 'src/ui/images'),
                sources: glob.sync('src/ui/images/settings/*.png'),
                destination: path.resolve(__dirname, 'images')
            },
            gifsicle: null,
            jpegtran: null,
            optipng: null,
            pngquant: {
                quality: '85-100',
                speed: production ? 1 : 10
            },
            svgo: null
        })
    ];

    return {
        context: path.resolve(__dirname, 'src/ui'),
        // This is ugly having main.scss on both bundles, but if it is added separately it will generate a js bundle :(
        entry: {
            settings: ['./settings/index.ts', './scss/main.scss'],
            welcome: ['./welcome/index.ts', './scss/main.scss']
            // main: ['./scss/main.scss']
        },
        mode: production ? 'production' : 'development',
        devtool: !production ? 'eval-source-map' : undefined,
        output: {
            filename: '[name].js',
            path: path.resolve(__dirname, 'out/ui'),
            publicPath: '{{root}}/out/ui/'
        },
        optimization: {
            splitChunks: {
                cacheGroups: {
                    styles: {
                        name: 'styles',
                        test: /\.css$/,
                        chunks: 'all',
                        enforce: true
                    }
                }
            }
        },
        resolve: {
            extensions: ['.tsx', '.ts', '.js'],
            modules: [path.resolve(__dirname, 'src/ui'), 'node_modules']
        },
        module: {
            rules: [
                {
                    test: /\.tsx?$/,
                    use: {
                        loader: 'ts-loader',
                        options: {
                            configFile: 'ui.tsconfig.json'
                        }
                    },
                    exclude: /node_modules/
                },
                {
                    test: /\.scss$/,
                    use: [
                        {
                            loader: MiniCssExtractPlugin.loader
                        },
                        {
                            loader: 'css-loader',
                            options: {
                                minimize: production,
                                sourceMap: !production,
                                url: false
                            }
                        },
                        {
                            loader: 'sass-loader',
                            options: {
                                sourceMap: !production
                            }
                        }
                    ],
                    exclude: /node_modules/
                }
            ]
        },
        plugins: plugins
    };
};
<|endoftext|>


<commit_before>var dot = require('dot');

dot.templateSettings.strip = false;

module.exports = function (grunt) {
  function renderModulesTemplate(angular){
    var modulesTemplate = dot.template(grunt.file.read('templates/modules.def'));
    return modulesTemplate({
        modules:      angular.modules,
        modulesNames: angular.modulesNames
    });
  }

  function renderModuleTemplate(module){
    var modulesTemplate = dot.template(grunt.file.read('templates/module.def'));
    return modulesTemplate({
        controllers: module.controllers,
        services:    module.services
    });
  }
  return {
    renderModulesTemplate: renderModulesTemplate,
    renderModuleTemplate:  renderModuleTemplate
  }
}<commit_msg>trying to get dot dependency to work.<commit_after>var dot = require('../node_modules/dot/doT.js');

dot.templateSettings.strip = false;

module.exports = function (grunt) {
  function renderModulesTemplate(angular){
    var modulesTemplate = dot.template(grunt.file.read('templates/modules.def'));
    return modulesTemplate({
        modules:      angular.modules,
        modulesNames: angular.modulesNames
    });
  }

  function renderModuleTemplate(module){
    var modulesTemplate = dot.template(grunt.file.read('templates/module.def'));
    return modulesTemplate({
        controllers: module.controllers,
        services:    module.services
    });
  }
  return {
    renderModulesTemplate: renderModulesTemplate,
    renderModuleTemplate:  renderModuleTemplate
  }
}<|endoftext|>


<commit_before>test("Popcorn Webpage Plugin", function () {

  var popped = Popcorn("#video"),
      expects = 11,
      count = 0,
      setupId,
      theiFrame = document.getElementsByTagName('iframe');

  expect(expects);

  function plus() {
    if ( ++count===expects) {
      start();
    }
  }

  stop();

  ok ('webpage' in popped, "webpages is a mehtod of the popped instance");
  plus();

  equals (theiFrame.length, 0, "initially, there is no iframes on the page" );
  plus();

  popped.webpage({
    id: "webpages-a",
    start: 0, // seconds
    end: 1, // seconds
    src: 'http://webmademovies.org',
    target: 'webpagediv'
  })
  .webpage({
    id: "webpages-b",
    start: 1, // seconds
    end: 2, // seconds
    src: 'http://zenit.senecac.on.ca/wiki/index.php/Processing.js',
    target: 'webpagediv'
  })
  .volume(0);

  setupId = popped.getLastTrackEventId();

  popped.exec( 0, function() {
    ok (!!theiFrame[0], "iframe was created" );
    plus();
    equals (theiFrame.length, 2, "there is only two iframes on the page" );
    plus();
    equals (theiFrame[0].id, "webpages-a", "the first iframe has the id 'webpages-a'" );
    plus();
    equals (theiFrame[0].src, "http://webmademovies.org/", "iframe has the src 'http://webmademovies.org/'" );
    plus();
  });

  popped.exec( 1, function() {
    ok (!!theiFrame[1], "iframe was created" );
    plus();
    equals (theiFrame[1].id, "webpages-b", "iframe second has the id 'webpages-b'" );
    plus();
    equals (theiFrame[1].src,"http://zenit.senecac.on.ca/wiki/index.php/Processing.js", "iframe has the src 'http://zenit.senecac.on.ca/wiki/index.php/Processing.js'" );
    plus();
  });

  popped.exec( 2, function() {
    ok (theiFrame[0].style.display === 'none' && theiFrame[1].style.display === 'none', "both iframes are hidden" );
    plus();

    popped.pause().removeTrackEvent( setupId );
    ok( !theiFrame[1], "removed webpage was properly destroyed" );
    plus();
  });

  popped.play();

});
<commit_msg>[#625] Regex match the url to skirt Safari string evaluation issue<commit_after>test("Popcorn Webpage Plugin", function () {

  var popped = Popcorn("#video"),
      expects = 11,
      count = 0,
      setupId,
      theiFrame = document.getElementsByTagName("iframe");

  expect(expects);

  function plus() {
    if ( ++count===expects) {
      start();
    }
  }

  stop();

  ok ("webpage" in popped, "webpages is a mehtod of the popped instance");
  plus();

  equal( theiFrame.length, 0, "initially, there is no iframes on the page" );
  plus();

  popped.webpage({
    id: "webpages-a",
    start: 0, // seconds
    end: 1, // seconds
    src: "http://webmademovies.org",
    target: "webpagediv"
  })
  .webpage({
    id: "webpages-b",
    start: 1, // seconds
    end: 2, // seconds
    src: "http://zenit.senecac.on.ca/wiki/index.php/Processing.js",
    target: "webpagediv"
  })
  .volume(0);

  setupId = popped.getLastTrackEventId();

  popped.exec( 0, function() {
    ok (!!theiFrame[0], "iframe was created" );
    plus();
    equal( theiFrame.length, 2, "there is only two iframes on the page" );
    plus();
    equal( theiFrame[0].id, "webpages-a", "the first iframe has the id 'webpages-a'" );
    plus();
    ok( /webmademovies/.test(theiFrame[0].src), "iframe has the src 'http://webmademovies.org/'" );
    plus();
  });

  popped.exec( 1, function() {
    ok (!!theiFrame[1], "iframe was created" );
    plus();
    equal( theiFrame[1].id, "webpages-b", "iframe second has the id 'webpages-b'" );
    plus();
    equal( theiFrame[1].src,"http://zenit.senecac.on.ca/wiki/index.php/Processing.js", "iframe has the src 'http://zenit.senecac.on.ca/wiki/index.php/Processing.js'" );
    plus();
  });

  popped.exec( 2, function() {
    ok (theiFrame[0].style.display === "none" && theiFrame[1].style.display === "none", "both iframes are hidden" );
    plus();

    popped.pause().removeTrackEvent( setupId );
    ok( !theiFrame[1], "removed webpage was properly destroyed" );
    plus();
  });

  popped.play();

});
<|endoftext|>


<commit_before>// OpenSeadragon canvas Overlay plugin 0.0.1 based on svg overlay plugin

(function() {

    if (!window.OpenSeadragon) {
        console.error('[openseadragon-canvas-overlay] requires OpenSeadragon');
        return;
    }

    // ----------
    OpenSeadragon.Viewer.prototype.canvasOverlay = function(options) {

        if (this._canvasOverlayInfo) {
            return this._canvasOverlayInfo;
        }

        this._canvasOverlayInfo = new Overlay(this,options);
        return this._canvasOverlayInfo;
    };

    // ----------
    var Overlay = function(viewer,options) {
        var self = this;
        console.log(this);
        this._viewer = viewer;

        this._containerWidth = 0;
        this._containerHeight = 0;

        this._canvasdiv = document.createElement( 'div');
        this._canvasdiv.style.position = 'absolute';
        this._canvasdiv.style.left = 0;
        this._canvasdiv.style.top = 0;
        this._canvasdiv.style.width = '100%';
        this._canvasdiv.style.height = '100%';
        this._viewer.canvas.appendChild(this._canvasdiv);

        this._canvas = document.createElement('canvas');
        this._canvasdiv.appendChild(this._canvas);

        this.onRedraw = options.onRedraw || function(){};
        this.clearBeforeRedraw = (typeof (options.clearBeforeRedraw) !== "undefined") ?
                        options.clearBeforeRedraw : true;

        this.resize();

        this._viewer.addHandler('animation', function() {
            self.resize();
            self._updateCanvas();
        });

        this._viewer.addHandler('open', function() {
            self.resize();
            self._updateCanvas();
        });

    };

    // ----------
    Overlay.prototype = {
        // ----------
        canvas: function() {
            return this._canvas;
        },
        // ----------
        context2d: function() {
            return this._canvas.getContext('2d');
        },
        // ----------
        clear: function() {
            this._canvas.getContext('2d').clearRect(0, 0, this._containerWidth, this._containerHeight);
        },
        // ----------
        resize: function() {
            if (this._containerWidth !== this._viewer.container.clientWidth) {
                this._containerWidth = this._viewer.container.clientWidth;
                this._canvasdiv.setAttribute('width', this._containerWidth);
                this._canvas.setAttribute('width', this._containerWidth);
            }

            if (this._containerHeight !== this._viewer.container.clientHeight) {
                this._containerHeight = this._viewer.container.clientHeight;
                this._canvasdiv.setAttribute('height', this._containerHeight);
                this._canvas.setAttribute('height', this._containerHeight);
            }
        },
        _updateCanvas: function() {
            var viewportZoom = this._viewer.viewport.getZoom(true);
            var image1 = this._viewer.world.getItemAt(0);
            var zoom = image1.viewportToImageZoom(viewportZoom);
            var origin = new OpenSeadragon.Point(0, 0);
            var image1WindowPoint = image1.imageToWindowCoordinates(origin);
            var x=Math.round(image1WindowPoint.x);
            var y=Math.round(image1WindowPoint.y);
            if (this.clearBeforeRedraw) this.clear();
            this._canvas.getContext('2d').translate(x,y);
            this._canvas.getContext('2d').scale(zoom,zoom);
            this.onRedraw();
            this._canvas.getContext('2d').setTransform(1, 0, 0, 1, 0, 0);
        }
    };

})();
<commit_msg>using update-viewport instead of animation https://github.com/altert/OpenSeadragonCanvasOverlay/issues/1<commit_after>// OpenSeadragon canvas Overlay plugin 0.0.1 based on svg overlay plugin

(function() {

    if (!window.OpenSeadragon) {
        console.error('[openseadragon-canvas-overlay] requires OpenSeadragon');
        return;
    }

    // ----------
    OpenSeadragon.Viewer.prototype.canvasOverlay = function(options) {

        if (this._canvasOverlayInfo) {
            return this._canvasOverlayInfo;
        }

        this._canvasOverlayInfo = new Overlay(this,options);
        return this._canvasOverlayInfo;
    };

    // ----------
    var Overlay = function(viewer,options) {
        var self = this;
        console.log(this);
        this._viewer = viewer;

        this._containerWidth = 0;
        this._containerHeight = 0;

        this._canvasdiv = document.createElement( 'div');
        this._canvasdiv.style.position = 'absolute';
        this._canvasdiv.style.left = 0;
        this._canvasdiv.style.top = 0;
        this._canvasdiv.style.width = '100%';
        this._canvasdiv.style.height = '100%';
        this._viewer.canvas.appendChild(this._canvasdiv);

        this._canvas = document.createElement('canvas');
        this._canvasdiv.appendChild(this._canvas);

        this.onRedraw = options.onRedraw || function(){};
        this.clearBeforeRedraw = (typeof (options.clearBeforeRedraw) !== "undefined") ?
                        options.clearBeforeRedraw : true;

        this.resize();

        this._viewer.addHandler('update-viewport', function() {
            self.resize();
            self._updateCanvas();
        });

        this._viewer.addHandler('open', function() {
            self.resize();
            self._updateCanvas();
        });

    };

    // ----------
    Overlay.prototype = {
        // ----------
        canvas: function() {
            return this._canvas;
        },
        // ----------
        context2d: function() {
            return this._canvas.getContext('2d');
        },
        // ----------
        clear: function() {
            this._canvas.getContext('2d').clearRect(0, 0, this._containerWidth, this._containerHeight);
        },
        // ----------
        resize: function() {
            if (this._containerWidth !== this._viewer.container.clientWidth) {
                this._containerWidth = this._viewer.container.clientWidth;
                this._canvasdiv.setAttribute('width', this._containerWidth);
                this._canvas.setAttribute('width', this._containerWidth);
            }

            if (this._containerHeight !== this._viewer.container.clientHeight) {
                this._containerHeight = this._viewer.container.clientHeight;
                this._canvasdiv.setAttribute('height', this._containerHeight);
                this._canvas.setAttribute('height', this._containerHeight);
            }
        },
        _updateCanvas: function() {
            var viewportZoom = this._viewer.viewport.getZoom(true);
            var image1 = this._viewer.world.getItemAt(0);
            var zoom = image1.viewportToImageZoom(viewportZoom);
            var origin = new OpenSeadragon.Point(0, 0);
            var image1WindowPoint = image1.imageToWindowCoordinates(origin);
            var x=Math.round(image1WindowPoint.x);
            var y=Math.round(image1WindowPoint.y);
            if (this.clearBeforeRedraw) this.clear();
            this._canvas.getContext('2d').translate(x,y);
            this._canvas.getContext('2d').scale(zoom,zoom);
            this.onRedraw();
            this._canvas.getContext('2d').setTransform(1, 0, 0, 1, 0, 0);
        }
    };

})();
<|endoftext|>