<commit_before>/*
 * Copyright (C) 2012 B3Partners B.V.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/**
 * AttributeList component
 * Creates a AttributeList component
 * @author Roy Braam
 */
Ext.define ("viewer.components.AttributeList",{
    extend: "viewer.components.Component",
    grid: null,
    pager: null,
    config: {
        layers:null,
        title:null,
        iconUrl:null,
        tooltip:null
    },
    appLayer: null,
    featureService: null,
    layerSelector:null,
    constructor: function (conf){
        var minwidth = 600;
        if(conf.details.width < minwidth || !Ext.isDefined(conf.details.width)) conf.details.width = minwidth;
        viewer.components.AttributeList.superclass.constructor.call(this, conf);
        this.initConfig(conf);
        var me = this;
        this.renderButton({
            handler: function(){
                me.layerSelector.initLayers();
                me.showWindow();
            },
            text: me.title,
            icon: me.iconUrl,
            tooltip: me.tooltip
        });
        this.loadWindow();
        this.viewerController.addListener(viewer.viewercontroller.controller.Event.ON_FILTER_ACTIVATED,this.filterChanged,this);
        return this;
    },
    getExtComponents: function() {
        return [
            this.name + 'Container',
            this.name + 'LayerSelectorPanel',
            this.name + 'GridPanel',
            this.name + 'Grid',
            this.name + 'PagerPanel',
            this.name + 'Pager',
            this.name + 'ClosingPanel',
        ];
    },
    loadWindow : function(){
        var me = this;
        Ext.create('Ext.container.Container', {
            id: this.name + 'Container',
            width: '100%',
            height: '100%',
            layout: {
                type: 'vbox',
                align: 'stretch'
            },
            style: {
                backgroundColor: 'White'
            },
            renderTo: this.getContentDiv(),
            items: [{
                id: this.name + 'LayerSelectorPanel',
                xtype: "container",
                padding: "4px",
                width: '100%',
                height: 36
            },{
                id: this.name + 'GridPanel',
                xtype: "container",
                autoScroll: true,
                width: '100%',
                flex: 1
            },{
                id: this.name + 'PagerPanel',
                xtype: "container",
                width: '100%',
                height: 30
            },{
                id: this.name + 'ClosingPanel',
                xtype: "container",
                width: '100%',
                height: MobileManager.isMobile() ? 45 : 25,
                style: {
                    marginTop: '10px'
                },
                layout: {
                    type:'hbox',
                    pack:'end'
                },
                items: [
                    {xtype: 'button', text: 'Sluiten', padding: MobileManager.isMobile() ? '10px' : '2px', handler: function() {
                        me.popup.hide();
                    }}
                ]
            }]
        });

        var config = {
            viewerController : this.viewerController,
            restriction: "attribute",
//            restriction : "hasConfiguredLayers",
//            layers: this.layers,
            div: this.name + 'LayerSelectorPanel'
        };
        this.layerSelector = Ext.create("viewer.components.LayerSelector",config);
        this.layerSelector.addListener(viewer.viewercontroller.controller.Event.ON_LAYERSELECTOR_CHANGE,this.layerChanged,this);

    },
    showWindow : function (){
        this.popup.show();
    },
    clear: function() {
        if(this.grid) {
            this.grid.destroy();
        }
        if(this.pager) {
            this.pager.destroy();
        }
        delete this.appLayer;
        delete this.featureService;
    },
    loadAttributes: function(appLayer) {
        this.clear();

        this.appLayer = appLayer;

        var me = this;

        if(this.appLayer != null) {

            this.featureService = this.viewerController.getAppLayerFeatureService(this.appLayer);

            // check if featuretype was loaded
            if(this.appLayer.attributes == undefined) {
                this.featureService.loadAttributes(me.appLayer, function(attributes) {
                    me.initGrid(me.appLayer);
                });
            } else {
                this.initGrid(me.appLayer);
            }
        }
    },
    // Called when the layerSelector was changed.
    layerChanged : function (appLayer){
        this.loadAttributes(appLayer);
    },
    filterChanged : function (filter,appLayer){
        var selectedLayer = this.layerSelector.getValue();

        if(selectedLayer){
            if(selectedLayer.id == appLayer.id){
                this.loadAttributes(appLayer);
            }
        }
    },
    initGrid: function(appLayer) {
        var me = this;

        var attributes = appLayer.attributes;
        var attributeList = new Array();
        var columns = new Array();
        var index = 0;
        for(var i= 0 ; i < attributes.length ;i++){
            var attribute = attributes[i];
            if(attribute.visible){

                var attIndex = index++;

                var colName = attribute.alias != undefined ? attribute.alias : attribute.name;
                attributeList.push({
                    name: "c" + attIndex,
                    type : 'string'
                });
                columns.push({
                    id: "c" +attIndex,
                    text:colName,
                    dataIndex: "c" + attIndex,
                    flex: 1,
                    filter: {
                        xtype: 'textfield'
                    }
                });
            }
        }
        Ext.define(this.name + 'Model', {
            extend: 'Ext.data.Model',
            fields: attributeList
        });
        var filter = "";
        if(appLayer.filter){
            filter = "&filter="+encodeURIComponent(appLayer.filter.getCQL());
        }
        var store = Ext.create('Ext.data.Store', {
            pageSize: 10,
            model: this.name + 'Model',
            remoteSort: true,
            remoteFilter: true,
            proxy: {
                type: 'ajax',
                timeout: 40000,
                url: appLayer.featureService.getStoreUrl() + "&arrays=1"+filter,
                reader: {
                    type: 'json',
                    root: 'features',
                    totalProperty: 'total'
                },
                simpleSortMode: true,
                listeners: {
                    exception: function(store, response, op) {

                        msg = response.responseText;
                        if(response.status == 200) {
                            try {
                                var j = Ext.JSON.decode(response.responseText);
                                if(j.message) {
                                    msg = j.message;
                                }
                            } catch(e) {
                            }
                        }

                        if(msg == null) {
                            if(response.timedout) {
                                msg = "Request timed out";
                            } else if(response.statusText != null && response.statusText != "") {
                                msg = response.statusText;
                            } else {
                                msg = "Unknown error";
                            }
                        }

                        Ext.getCmp(me.name + "Grid").getStore().removeAll();

                        Ext.MessageBox.alert("Foutmelding", msg);

                    }
                }
            },
            autoLoad: true
        });

        this.grid = Ext.create('Ext.grid.Panel',  {
            id: this.name + 'Grid',
            store: store,
            columns: columns,
            renderTo: this.name + 'GridPanel'
        });

        this.pager = Ext.create('Ext.PagingToolbar', {
            id: this.name + 'Pager',
            store: store,
            displayInfo: true,
            displayMsg: 'Feature {0} - {1} van {2}',
            emptyMsg: "Geen features om weer te geven",
            renderTo: this.name + 'PagerPanel',
            height: 30
        });
    }
});

<commit_msg>fix comma before array end ] <commit_after>/*
 * Copyright (C) 2012 B3Partners B.V.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
/**
 * AttributeList component
 * Creates a AttributeList component
 * @author Roy Braam
 */
Ext.define ("viewer.components.AttributeList",{
    extend: "viewer.components.Component",
    grid: null,
    pager: null,
    config: {
        layers:null,
        title:null,
        iconUrl:null,
        tooltip:null
    },
    appLayer: null,
    featureService: null,
    layerSelector:null,
    constructor: function (conf){
        var minwidth = 600;
        if(conf.details.width < minwidth || !Ext.isDefined(conf.details.width)) conf.details.width = minwidth;
        viewer.components.AttributeList.superclass.constructor.call(this, conf);
        this.initConfig(conf);
        var me = this;
        this.renderButton({
            handler: function(){
                me.layerSelector.initLayers();
                me.showWindow();
            },
            text: me.title,
            icon: me.iconUrl,
            tooltip: me.tooltip
        });
        this.loadWindow();
        this.viewerController.addListener(viewer.viewercontroller.controller.Event.ON_FILTER_ACTIVATED,this.filterChanged,this);
        return this;
    },
    getExtComponents: function() {
        return [
            this.name + 'Container',
            this.name + 'LayerSelectorPanel',
            this.name + 'GridPanel',
            this.name + 'Grid',
            this.name + 'PagerPanel',
            this.name + 'Pager',
            this.name + 'ClosingPanel'
        ];
    },
    loadWindow : function(){
        var me = this;
        Ext.create('Ext.container.Container', {
            id: this.name + 'Container',
            width: '100%',
            height: '100%',
            layout: {
                type: 'vbox',
                align: 'stretch'
            },
            style: {
                backgroundColor: 'White'
            },
            renderTo: this.getContentDiv(),
            items: [{
                id: this.name + 'LayerSelectorPanel',
                xtype: "container",
                padding: "4px",
                width: '100%',
                height: 36
            },{
                id: this.name + 'GridPanel',
                xtype: "container",
                autoScroll: true,
                width: '100%',
                flex: 1
            },{
                id: this.name + 'PagerPanel',
                xtype: "container",
                width: '100%',
                height: 30
            },{
                id: this.name + 'ClosingPanel',
                xtype: "container",
                width: '100%',
                height: MobileManager.isMobile() ? 45 : 25,
                style: {
                    marginTop: '10px'
                },
                layout: {
                    type:'hbox',
                    pack:'end'
                },
                items: [
                    {xtype: 'button', text: 'Sluiten', padding: MobileManager.isMobile() ? '10px' : '2px', handler: function() {
                        me.popup.hide();
                    }}
                ]
            }]
        });

        var config = {
            viewerController : this.viewerController,
            restriction: "attribute",
//            restriction : "hasConfiguredLayers",
//            layers: this.layers,
            div: this.name + 'LayerSelectorPanel'
        };
        this.layerSelector = Ext.create("viewer.components.LayerSelector",config);
        this.layerSelector.addListener(viewer.viewercontroller.controller.Event.ON_LAYERSELECTOR_CHANGE,this.layerChanged,this);

    },
    showWindow : function (){
        this.popup.show();
    },
    clear: function() {
        if(this.grid) {
            this.grid.destroy();
        }
        if(this.pager) {
            this.pager.destroy();
        }
        delete this.appLayer;
        delete this.featureService;
    },
    loadAttributes: function(appLayer) {
        this.clear();

        this.appLayer = appLayer;

        var me = this;

        if(this.appLayer != null) {

            this.featureService = this.viewerController.getAppLayerFeatureService(this.appLayer);

            // check if featuretype was loaded
            if(this.appLayer.attributes == undefined) {
                this.featureService.loadAttributes(me.appLayer, function(attributes) {
                    me.initGrid(me.appLayer);
                });
            } else {
                this.initGrid(me.appLayer);
            }
        }
    },
    // Called when the layerSelector was changed.
    layerChanged : function (appLayer){
        this.loadAttributes(appLayer);
    },
    filterChanged : function (filter,appLayer){
        var selectedLayer = this.layerSelector.getValue();

        if(selectedLayer){
            if(selectedLayer.id == appLayer.id){
                this.loadAttributes(appLayer);
            }
        }
    },
    initGrid: function(appLayer) {
        var me = this;

        var attributes = appLayer.attributes;
        var attributeList = new Array();
        var columns = new Array();
        var index = 0;
        for(var i= 0 ; i < attributes.length ;i++){
            var attribute = attributes[i];
            if(attribute.visible){

                var attIndex = index++;

                var colName = attribute.alias != undefined ? attribute.alias : attribute.name;
                attributeList.push({
                    name: "c" + attIndex,
                    type : 'string'
                });
                columns.push({
                    id: "c" +attIndex,
                    text:colName,
                    dataIndex: "c" + attIndex,
                    flex: 1,
                    filter: {
                        xtype: 'textfield'
                    }
                });
            }
        }
        Ext.define(this.name + 'Model', {
            extend: 'Ext.data.Model',
            fields: attributeList
        });
        var filter = "";
        if(appLayer.filter){
            filter = "&filter="+encodeURIComponent(appLayer.filter.getCQL());
        }
        var store = Ext.create('Ext.data.Store', {
            pageSize: 10,
            model: this.name + 'Model',
            remoteSort: true,
            remoteFilter: true,
            proxy: {
                type: 'ajax',
                timeout: 40000,
                url: appLayer.featureService.getStoreUrl() + "&arrays=1"+filter,
                reader: {
                    type: 'json',
                    root: 'features',
                    totalProperty: 'total'
                },
                simpleSortMode: true,
                listeners: {
                    exception: function(store, response, op) {

                        msg = response.responseText;
                        if(response.status == 200) {
                            try {
                                var j = Ext.JSON.decode(response.responseText);
                                if(j.message) {
                                    msg = j.message;
                                }
                            } catch(e) {
                            }
                        }

                        if(msg == null) {
                            if(response.timedout) {
                                msg = "Request timed out";
                            } else if(response.statusText != null && response.statusText != "") {
                                msg = response.statusText;
                            } else {
                                msg = "Unknown error";
                            }
                        }

                        Ext.getCmp(me.name + "Grid").getStore().removeAll();

                        Ext.MessageBox.alert("Foutmelding", msg);

                    }
                }
            },
            autoLoad: true
        });

        this.grid = Ext.create('Ext.grid.Panel',  {
            id: this.name + 'Grid',
            store: store,
            columns: columns,
            renderTo: this.name + 'GridPanel'
        });

        this.pager = Ext.create('Ext.PagingToolbar', {
            id: this.name + 'Pager',
            store: store,
            displayInfo: true,
            displayMsg: 'Feature {0} - {1} van {2}',
            emptyMsg: "Geen features om weer te geven",
            renderTo: this.name + 'PagerPanel',
            height: 30
        });
    }
});

<|endoftext|>


<commit_before>var requestID;
var	userAntFunction;

window.requestAnimationFrame = function() {
    return window.requestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        window.msRequestAnimationFrame ||
        window.oRequestAnimationFrame ||
        function(f) {
            window.setTimeout(f,1);
        }
}();

var child = document.createElement('div');
child.innerHTML = `

		<input type="button" value="run" id="runTutorial" >
		<input type="button" value="cheat" id="cheat" >

		<canvas width="250" height="200" class="terrarium" id="canvasTutorial"></canvas>
		<input type="checkbox" value="speedUp" id="speedUp">SpeedUp!
		<input type="checkbox" value="debug"   id="debug">debug

`

var insertNode = document.getElementById("tutorialPart");
insertNode.parentNode.insertBefore(child, insertNode);

SettingsGlobal.setFramesPerSecond(15);

requirejs([ 'external/seedrandom/seedrandom',
			'external/setImmediate/setImmediate',
			'tutorial',
			'settingsSimulation',
			'antController'],
function   (seed, setImmediate, Tutorial, SettingsSimulation, AntController) {

	var tutorialPart = document.getElementById("tutorialPart").value;
	var defaultValues = ["return [ActionType.MOVE, DirectionType.FORWARD, rand(-60,60)];",
// MOVE Tutorial
`var nearestFood = this.getNearestObjectType(ObjectType.FOOD);
if (nearestFood !== null){
	var rotationTowardsFood = nearestFood.getRotationToObj();
	return [ActionType.MOVE, DirectionType.FORWARD, rotationTowardsFood];
}
return [ActionType.MOVE, DirectionType.FORWARD, rand(-60,60)];`,
// HARVEST tutorial
`var hive = this.getOwnHive();
var nearestFood = this.getNearestObjectType(ObjectType.FOOD);
if (nearestFood !== null && !this.memory.harvestedFood){
	if(nearestFood.canBeInteractedWith(this)){
		if (this.isFull())
			this.memory.harvestedFood = true;
		return [ActionType.HARVEST, nearestFood];
	}
	else
		return [ActionType.MOVE, DirectionType.FORWARD, nearestFood.getRotationToObj()];
}
if (this.memory.harvestedFood && hive !== null){
	return [ActionType.MOVE, DirectionType.FORWARD, hive.getRotationToObj()];
}
return [ActionType.MOVE, DirectionType.FORWARD, rand(-60,60)];`,
// TRANSFER tutorial
`var hive = this.getOwnHive();
var nearestFood = this.getNearestObjectType(ObjectType.FOOD);
if (nearestFood !== null && !this.memory.harvestedFood){
	if(nearestFood.canBeInteractedWith(this)){
		if (this.isFull())
			this.memory.harvestedFood = true;
		return [ActionType.HARVEST, nearestFood];
	}
	else
		return [ActionType.MOVE, DirectionType.FORWARD, nearestFood.getRotationToObj()];

}
if (this.memory.harvestedFood && hive !== null){
	if(hive.canBeInteractedWith(this)){
		this.memory.harvestedFood = false;
		return [ActionType.TRANSFER, hive, this.getMaxFoodStorage()];
	}
	else
		return [ActionType.MOVE, DirectionType.FORWARD, hive.getRotationToObj()];
}
return [ActionType.MOVE, DirectionType.FORWARD, rand(-60,60)];`,
// PHEROMONE tutorial
`var hive = this.getOwnHive();
var nearestFood = this.getNearestObjectType(ObjectType.FOOD);
var isScout = (this.getGenes().sensitivity > 0.7);
var nextPheromone = this.getNextPheromoneOfType(PheromoneType.FOOD);
// ant has collided with sth -> try to walk around it
if (this.hasCollidedWithID() != -1){
	return [ActionType.MOVE, DirectionType.FORWARD, 45];
}

// return food if ant harvested some but doesn't see food source anymore
if (nearestFood === null && !this.memory.harvestedFood && this.getFoodStorage() > 0)
	this.memory.harvestedFood = true;

// try to find food
if ((nearestFood !== null || (nextPheromone !== null && !isScout)) && !this.memory.harvestedFood){
	if(nearestFood !== null && nearestFood.canBeInteractedWith(this)){
		this.memory.harvestedFood = this.isFull();
		this.memory.lastPheromoneSet = 0;
		return [ActionType.HARVEST, nearestFood];
	}
	else {
		if (nearestFood !== null)
			return [ActionType.MOVE, DirectionType.FORWARD, nearestFood.getRotationToObj()];
		else if (nextPheromone !== null)
			return [ActionType.MOVE, DirectionType.FORWARD, nextPheromone.getRotationToObj()+15];
	}

}

// bring food back home
if (this.memory.harvestedFood && hive !== null){
	if (isScout)
		this.memory.lastPheromoneSet +=1;
	if (this.memory.lastPheromoneSet > 25){
		this.memory.lastPheromoneSet = 0;
		return [ActionType.PHEROMONE, PheromoneType.FOOD];
	}
	if(hive.canBeInteractedWith(this)){
		this.memory.harvestedFood = false;
		return [ActionType.TRANSFER, hive, this.getMaxFoodStorage()];
	}
	else {
		return [ActionType.MOVE, DirectionType.FORWARD, hive.getRotationToObj()];
	}
}

else if (this.memory.harvestedFood && nextPheromone !== null)
	return [ActionType.MOVE, DirectionType.FORWARD, nextPheromone.getRotationToObj()];

if (isScout)
	return [ActionType.MOVE, DirectionType.FORWARD, rand(-60,60)];

return [ActionType.MOVE, DirectionType.NONE, rand(-60,60)];`];

	var editor = createEditor("editor", defaultValues[tutorialPart-1])

	function finishedFunc(){
		document.getElementById('finished').style.display = 'block';
		window.cancelAnimationFrame(requestID);
		requestID = undefined;
	};

	function cheat(part){
		editor.setValue("// CHEATER! :)\n" + defaultValues[part], -1); // -1 set cursor to begin
		startTutorial(part);
	};

	function speedUp(enabled){
		SettingsGlobal.setFramesPerSecond(enabled ? 60 : 15);
	}

	function debug(enabled){
		if (tutorialPart == 1){
			Debug.setVisibility(enabled);
			Debug.setShowSmellingDistance(enabled);
		}
		if (tutorialPart == 4){
			Debug.setShowFoodAmount(enabled);
			Debug.setShowPheromones(enabled);
		}
	}

	function startTutorial(part){
		userAntFunction = new Function(editor.getValue());
		window.cancelAnimationFrame(requestID);
		requestID = undefined;
		SettingsGlobal.setShowUI(true);
		Math.seedrandom();

		var canvas = document.getElementById('canvasTutorial');
		var settings = new SettingsSimulation(SimulationMode.SOLO, AntType.CUSTOM, HiveType.DEFAULT, [userAntFunction]);
		new Tutorial(canvas, settings, finishedFunc, part);
	};

	document.getElementById("cheat").onclick = function(){cheat(tutorialPart)};
	document.getElementById("runTutorial").onclick = function(){startTutorial(tutorialPart)};
	document.getElementById("speedUp").onclick = function(){ speedUp(document.getElementById("speedUp").checked) };
	document.getElementById("debug").onclick = function(){ debug(document.getElementById("debug").checked) };

	// show default behaviour before user has coded
	startTutorial(tutorialPart);
});<commit_msg>fixed tutorial with new playerSettings<commit_after>var requestID;
var	userAntFunction;

window.requestAnimationFrame = function() {
    return window.requestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        window.msRequestAnimationFrame ||
        window.oRequestAnimationFrame ||
        function(f) {
            window.setTimeout(f,1);
        }
}();

var child = document.createElement('div');
child.innerHTML = `

		<input type="button" value="run" id="runTutorial" >
		<input type="button" value="cheat" id="cheat" >

		<canvas width="250" height="200" class="terrarium" id="canvasTutorial"></canvas>
		<input type="checkbox" value="speedUp" id="speedUp">SpeedUp!
		<input type="checkbox" value="debug"   id="debug">debug

`

var insertNode = document.getElementById("tutorialPart");
insertNode.parentNode.insertBefore(child, insertNode);

SettingsGlobal.setFramesPerSecond(15);

requirejs([ 'external/seedrandom/seedrandom',
			'external/setImmediate/setImmediate',
			'tutorial',
			'settingsSimulation',
			'antController'],
function   (seed, setImmediate, Tutorial, SettingsSimulation, AntController) {

	var tutorialPart = document.getElementById("tutorialPart").value;
	var defaultValues = ["return [ActionType.MOVE, DirectionType.FORWARD, rand(-60,60)];",
// MOVE Tutorial
`var nearestFood = this.getNearestObjectType(ObjectType.FOOD);
if (nearestFood !== null){
	var rotationTowardsFood = nearestFood.getRotationToObj();
	return [ActionType.MOVE, DirectionType.FORWARD, rotationTowardsFood];
}
return [ActionType.MOVE, DirectionType.FORWARD, rand(-60,60)];`,
// HARVEST tutorial
`var hive = this.getOwnHive();
var nearestFood = this.getNearestObjectType(ObjectType.FOOD);
if (nearestFood !== null && !this.memory.harvestedFood){
	if(nearestFood.canBeInteractedWith(this)){
		if (this.isFull())
			this.memory.harvestedFood = true;
		return [ActionType.HARVEST, nearestFood];
	}
	else
		return [ActionType.MOVE, DirectionType.FORWARD, nearestFood.getRotationToObj()];
}
if (this.memory.harvestedFood && hive !== null){
	return [ActionType.MOVE, DirectionType.FORWARD, hive.getRotationToObj()];
}
return [ActionType.MOVE, DirectionType.FORWARD, rand(-60,60)];`,
// TRANSFER tutorial
`var hive = this.getOwnHive();
var nearestFood = this.getNearestObjectType(ObjectType.FOOD);
if (nearestFood !== null && !this.memory.harvestedFood){
	if(nearestFood.canBeInteractedWith(this)){
		if (this.isFull())
			this.memory.harvestedFood = true;
		return [ActionType.HARVEST, nearestFood];
	}
	else
		return [ActionType.MOVE, DirectionType.FORWARD, nearestFood.getRotationToObj()];

}
if (this.memory.harvestedFood && hive !== null){
	if(hive.canBeInteractedWith(this)){
		this.memory.harvestedFood = false;
		return [ActionType.TRANSFER, hive, this.getMaxFoodStorage()];
	}
	else
		return [ActionType.MOVE, DirectionType.FORWARD, hive.getRotationToObj()];
}
return [ActionType.MOVE, DirectionType.FORWARD, rand(-60,60)];`,
// PHEROMONE tutorial
`var hive = this.getOwnHive();
var nearestFood = this.getNearestObjectType(ObjectType.FOOD);
var isScout = (this.getGenes().sensitivity > 0.7);
var nextPheromone = this.getNextPheromoneOfType(PheromoneType.FOOD);
// ant has collided with sth -> try to walk around it
if (this.hasCollidedWithID() != -1){
	return [ActionType.MOVE, DirectionType.FORWARD, 45];
}

// return food if ant harvested some but doesn't see food source anymore
if (nearestFood === null && !this.memory.harvestedFood && this.getFoodStorage() > 0)
	this.memory.harvestedFood = true;

// try to find food
if ((nearestFood !== null || (nextPheromone !== null && !isScout)) && !this.memory.harvestedFood){
	if(nearestFood !== null && nearestFood.canBeInteractedWith(this)){
		this.memory.harvestedFood = this.isFull();
		this.memory.lastPheromoneSet = 0;
		return [ActionType.HARVEST, nearestFood];
	}
	else {
		if (nearestFood !== null)
			return [ActionType.MOVE, DirectionType.FORWARD, nearestFood.getRotationToObj()];
		else if (nextPheromone !== null)
			return [ActionType.MOVE, DirectionType.FORWARD, nextPheromone.getRotationToObj()+15];
	}

}

// bring food back home
if (this.memory.harvestedFood && hive !== null){
	if (isScout)
		this.memory.lastPheromoneSet +=1;
	if (this.memory.lastPheromoneSet > 25){
		this.memory.lastPheromoneSet = 0;
		return [ActionType.PHEROMONE, PheromoneType.FOOD];
	}
	if(hive.canBeInteractedWith(this)){
		this.memory.harvestedFood = false;
		return [ActionType.TRANSFER, hive, this.getMaxFoodStorage()];
	}
	else {
		return [ActionType.MOVE, DirectionType.FORWARD, hive.getRotationToObj()];
	}
}

else if (this.memory.harvestedFood && nextPheromone !== null)
	return [ActionType.MOVE, DirectionType.FORWARD, nextPheromone.getRotationToObj()];

if (isScout)
	return [ActionType.MOVE, DirectionType.FORWARD, rand(-60,60)];

return [ActionType.MOVE, DirectionType.NONE, rand(-60,60)];`];

	var editor = createEditor("editor", defaultValues[tutorialPart-1])

	function finishedFunc(){
		document.getElementById('finished').style.display = 'block';
		window.cancelAnimationFrame(requestID);
		requestID = undefined;
	};

	function cheat(part){
		editor.setValue("// CHEATER! :)\n" + defaultValues[part], -1); // -1 set cursor to begin
		startTutorial(part);
	};

	function speedUp(enabled){
		SettingsGlobal.setFramesPerSecond(enabled ? 60 : 15);
	}

	function debug(enabled){
		if (tutorialPart == 1){
			Debug.setVisibility(enabled);
			Debug.setShowSmellingDistance(enabled);
		}
		if (tutorialPart == 4){
			Debug.setShowFoodAmount(enabled);
			Debug.setShowPheromones(enabled);
		}
	}

	function startTutorial(part){
		userAntFunction = new Function(editor.getValue());
		window.cancelAnimationFrame(requestID);
		requestID = undefined;
		SettingsGlobal.setShowUI(true);
		Math.seedrandom();

		var canvas = document.getElementById('canvasTutorial');
		var playerSettings = [{ antType: AntType.CUSTOM, hiveType: HiveType.DEFAULT, antCode: userAntFunction, hiveCode: null}];
		var settings = new SettingsSimulation(SimulationMode.SOLO, playerSettings);
		new Tutorial(canvas, settings, finishedFunc, part);
	};

	document.getElementById("cheat").onclick = function(){cheat(tutorialPart)};
	document.getElementById("runTutorial").onclick = function(){startTutorial(tutorialPart)};
	document.getElementById("speedUp").onclick = function(){ speedUp(document.getElementById("speedUp").checked) };
	document.getElementById("debug").onclick = function(){ debug(document.getElementById("debug").checked) };

	// show default behaviour before user has coded
	startTutorial(tutorialPart);
});<|endoftext|>


<commit_before>var RESOURCES = {
    'erg-uio': 'http://erg.delph-in.net/rest/0.9/parse',
    'erg-uw': 'http://chimpanzee.ling.washington.edu/bottlenose/erg/parse',
    'jacy-uw': 'http://chimpanzee.ling.washington.edu/bottlenose/jacy/parse',
    'indra-uw': 'http://chimpanzee.ling.washington.edu/bottlenose/indra/parse'
};

var SAMPLE_INPUT = {
    erg: 'Abrams knew that it rained.',
    jacy: '犬 が 吠える',
    indra: 'anjing menggonggong.'
};

// Using underscore.js/lodash.js Templates
var Templates = {};

Templates.result = [
    '
',
        '
',
            '
<%= resultNum %>
',
        '
',
    '
'].join("\n");

Templates.viz = [
    '<div class="viz <%= vizType %>" data-viz="<%= vizType %>">',
        '
',
            '

PNG

',
            '

SVG

',
        '
',
    '
'
].join("\n");

Templates.successStatus = [
    '
Showing <%= numResults %> of <%= readings %> analyses.
',
    '
<%= input %>
'
].join("\n");

// Precompile the templates
for (var template in Templates) {
    if (Templates.hasOwnProperty(template)) {
        Templates[template] = _.template(Templates[template]);
    }
}

var RESULTLIST = [];

function Result(result, parent) {
    var resultNum = result['result-id'] + 1;

    // Create and attach the DOM element that will contain the Result
    var $result = $(Templates.result({'resultNum': resultNum})).appendTo(parent);

    // Create this object
    var self = {
        data : result,
        num : resultNum,
        element: $result[0],
        saveViz : function(){},
        saveVizSvg : function(vizType) {
            var svgData = self[vizType].element.outerHTML;
            var svgBlob = new Blob([svgData], {type: 'image/svg+xml;charset=utf-8'});
            var DOMURL = window.URL || window.webkitURL || window;
            var url = DOMURL.createObjectURL(svgBlob);
            triggerDownload(url, 'delphin.svg');
        },
        saveVizPng : function(vizType) {
            // Save SVG to a canvas
            var svg = self[vizType].element;
            var canvas = $('<canvas>')[0];
            var ctx = canvas.getContext('2d');
            var bbox = svg.getBBox();
            ctx.canvas.height = bbox.height;
            ctx.canvas.width = bbox.width;
            ctx.fillStyle = 'white';
            ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);

            // convert SVG to dataUrl
            var data = (new XMLSerializer()).serializeToString(svg);
            var svgBlob = new Blob([data], {type: 'image/svg+xml;charset=utf-8'});
            var DOMURL = window.URL || window.webkitURL || window;
            var url = DOMURL.createObjectURL(svgBlob);

            var img = new Image();
            img.onload = function () {
                ctx.drawImage(img, 0, 0);
                DOMURL.revokeObjectURL(url);

                var imgURI = canvas
                        .toDataURL('image/png')
                        .replace('image/png', 'image/octet-stream');

                // on the image load, actually download it
                triggerDownload(imgURI, 'delphin.png');
            };
            img.src = url;
        }
    };

    var $inner = $result.find('.result-inner');

    // Add data structures as per the available data
    if (self.data.derivation) {
        var $viz = $(Templates.viz({vizType:'tree'})).appendTo($inner);
        self.tree = {element: drawTree($viz[0], self.data.derivation)};
    }

    if (self.data.mrs) {
        var $viz = $(Templates.viz({vizType:'mrs'})).appendTo($inner);
        self.mrs = MRS($viz[0], self.data.mrs);
    }

    if (self.data.dmrs) {
        var $viz = $(Templates.viz({vizType:'dmrs'})).appendTo($inner);
        self.dmrs = DMRS($viz[0], self.data.dmrs);
    }

    //Add various event bindings to things in the visualisations
    $result.find('.viz').hover(
        function(event) {
            $(this).find('.tools').removeClass('hidden');
        },
        function(event) {
            $(this).find('.tools').addClass('hidden');
        }
    ).each(function(index) {
        var vizType = this.dataset.viz;
        $(this).find('.save').click(function(event){
            if (this.dataset.img == 'svg')
                self.saveVizSvg(vizType);
            else if (this.dataset.img == 'png')
                self.saveVizPng(vizType);
        });
    });

    // Return this object
    return self;
}

function triggerDownload (imgURI, filename) {
    var evt = new MouseEvent('click', {
        view: window,
        bubbles: false,
        cancelable: true
    });

    var a = document.createElement('a');
    a.setAttribute('download', filename);
    a.setAttribute('href', imgURI);
    a.setAttribute('target', '_blank');
    a.dispatchEvent(evt);
}

function getQueryVariable(variable) {
    var query = window.location.search.substring(1);
    var vars = query.split("&");

    for (var i=0;i<vars.length;i++) {
        var pair = vars[i].split("=");
        if (pair[0] == variable)
            return pair[1];
    }

    return false;
}

function doResults(data) {
    // Update the status
    $(Templates.successStatus({
        'input': data.input,
        'readings': data.readings,
        'numResults': data.results.length}))
        .appendTo($('#results-info').empty());

    //Create and add the results
    var parent = $('#results-container').empty()[0];

    for (var i=0; i < data.results.length; i++) {
        var result = Result(data.results[i], parent);
        RESULTLIST.push(result);
    }
}

function updateUrl() {
    var makeParam = function(param, value) {return param + '=' + value;};
    var params = [];

    params.push(makeParam('input', $('#input-text').val()));
    params.push(makeParam('count', $('#input-results').val()));
    params.push(makeParam('grammar', $('#input-grammar').val()));

    if ($('#input-tree').prop('checked'));
        params.push(makeParam('tree', 'true'));
    if ($('#input-mrs').prop('checked'));
        params.push(makeParam('mrs', 'true'));
    if ($('#input-dmrs').prop('checked'));
        params.push(makeParam('dmrs', 'true'));

    window.location.hash = encodeURI(params.join('&'));
}

function loadUrlParams() {
    var hash = decodeURI(window.location.hash);
    var params = hash.replace(/^#/, '').split('&');

    if (params.length === 0 || params[0] === "")
        return false;

    for (var i=0; i < params.length; i++) {
        var p = params[i];

        if (p == '')
            continue;

        var fields = p.split('=');
        var param = fields[0];
        var value = fields[1];

        if (param === '' || value === '')
            continue;

        if (param == 'input')
            $('#input-text').val(value);
        else if (param == 'grammar')
            $('#input-grammar').val(value);
        else if (param == 'count')
            $('#input-results').val(value);
        else if (param == 'tree')
            $('#input-tree').prop('checked', true);
        else if (param == 'mrs')
            $('#input-mrs').prop('checked', true);
        else if (param == 'dmrs')
            $('#input-dmrs').prop('checked', true);
    }
    return true;
}

$(document).ready(function(){

    $('#input-submit').click(function(event) {
        $.ajax({
            url: RESOURCES[$('#input-grammar')[0].value],
            dataType: 'json',
            data: {
                'derivation': $('#input-tree').prop('checked') ? 'json' : "null",
                'mrs': $('#input-mrs').prop('checked') ? 'json' : "null",
                'dmrs': $('#input-dmrs').prop('checked') ? 'json' : "null",
                'input': $('#input-text').val(),
                'results': $('#input-results').val()
            },
            dataFilter: function(data) {
                return data.replace(/([^,]) "pedges"/, '$1, "pedges"');
            },
            success: function(data){
                doResults(data);
                updateUrl();
            },
            error: function(data){
                alert("Error");
            }
        });
    });

    $('#input-grammar').change(function(event){
        // Change the sample text to appropriate language
        var grammarPrefix = $(this).val().split('-')[0];
        $('#input-text').val(SAMPLE_INPUT[grammarPrefix]);
    });

    if (loadUrlParams())
        $('#input-submit').trigger('click');

    if (getQueryVariable('dev') == 'true') {
        $.getJSON("elephant.json", function(data) {
            doResults(data);
        });
    }
});
<commit_msg>more respectful default input changing for demo<commit_after>var RESOURCES = {
    'erg-uio': 'http://erg.delph-in.net/rest/0.9/parse',
    'erg-uw': 'http://chimpanzee.ling.washington.edu/bottlenose/erg/parse',
    'jacy-uw': 'http://chimpanzee.ling.washington.edu/bottlenose/jacy/parse',
    'indra-uw': 'http://chimpanzee.ling.washington.edu/bottlenose/indra/parse'
};

var SAMPLE_INPUT = {
    erg: 'Abrams knew that it rained.',
    jacy: '犬 が 吠える',
    indra: 'anjing menggonggong.'
};

// Using underscore.js/lodash.js Templates
var Templates = {};

Templates.result = [
    '
',
        '
',
            '
<%= resultNum %>
',
        '
',
    '
'].join("\n");

Templates.viz = [
    '<div class="viz <%= vizType %>" data-viz="<%= vizType %>">',
        '
',
            '

PNG

',
            '

SVG

',
        '
',
    '
'
].join("\n");

Templates.successStatus = [
    '
Showing <%= numResults %> of <%= readings %> analyses.
',
    '
<%= input %>
'
].join("\n");

// Precompile the templates
for (var template in Templates) {
    if (Templates.hasOwnProperty(template)) {
        Templates[template] = _.template(Templates[template]);
    }
}

var RESULTLIST = [];

function Result(result, parent) {
    var resultNum = result['result-id'] + 1;

    // Create and attach the DOM element that will contain the Result
    var $result = $(Templates.result({'resultNum': resultNum})).appendTo(parent);

    // Create this object
    var self = {
        data : result,
        num : resultNum,
        element: $result[0],
        saveViz : function(){},
        saveVizSvg : function(vizType) {
            var svgData = self[vizType].element.outerHTML;
            var svgBlob = new Blob([svgData], {type: 'image/svg+xml;charset=utf-8'});
            var DOMURL = window.URL || window.webkitURL || window;
            var url = DOMURL.createObjectURL(svgBlob);
            triggerDownload(url, 'delphin.svg');
        },
        saveVizPng : function(vizType) {
            // Save SVG to a canvas
            var svg = self[vizType].element;
            var canvas = $('<canvas>')[0];
            var ctx = canvas.getContext('2d');
            var bbox = svg.getBBox();
            ctx.canvas.height = bbox.height;
            ctx.canvas.width = bbox.width;
            ctx.fillStyle = 'white';
            ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);

            // convert SVG to dataUrl
            var data = (new XMLSerializer()).serializeToString(svg);
            var svgBlob = new Blob([data], {type: 'image/svg+xml;charset=utf-8'});
            var DOMURL = window.URL || window.webkitURL || window;
            var url = DOMURL.createObjectURL(svgBlob);

            var img = new Image();
            img.onload = function () {
                ctx.drawImage(img, 0, 0);
                DOMURL.revokeObjectURL(url);

                var imgURI = canvas
                        .toDataURL('image/png')
                        .replace('image/png', 'image/octet-stream');

                // on the image load, actually download it
                triggerDownload(imgURI, 'delphin.png');
            };
            img.src = url;
        }
    };

    var $inner = $result.find('.result-inner');

    // Add data structures as per the available data
    if (self.data.derivation) {
        var $viz = $(Templates.viz({vizType:'tree'})).appendTo($inner);
        self.tree = {element: drawTree($viz[0], self.data.derivation)};
    }

    if (self.data.mrs) {
        var $viz = $(Templates.viz({vizType:'mrs'})).appendTo($inner);
        self.mrs = MRS($viz[0], self.data.mrs);
    }

    if (self.data.dmrs) {
        var $viz = $(Templates.viz({vizType:'dmrs'})).appendTo($inner);
        self.dmrs = DMRS($viz[0], self.data.dmrs);
    }

    //Add various event bindings to things in the visualisations
    $result.find('.viz').hover(
        function(event) {
            $(this).find('.tools').removeClass('hidden');
        },
        function(event) {
            $(this).find('.tools').addClass('hidden');
        }
    ).each(function(index) {
        var vizType = this.dataset.viz;
        $(this).find('.save').click(function(event){
            if (this.dataset.img == 'svg')
                self.saveVizSvg(vizType);
            else if (this.dataset.img == 'png')
                self.saveVizPng(vizType);
        });
    });

    // Return this object
    return self;
}

function triggerDownload (imgURI, filename) {
    var evt = new MouseEvent('click', {
        view: window,
        bubbles: false,
        cancelable: true
    });

    var a = document.createElement('a');
    a.setAttribute('download', filename);
    a.setAttribute('href', imgURI);
    a.setAttribute('target', '_blank');
    a.dispatchEvent(evt);
}

function getQueryVariable(variable) {
    var query = window.location.search.substring(1);
    var vars = query.split("&");

    for (var i=0;i<vars.length;i++) {
        var pair = vars[i].split("=");
        if (pair[0] == variable)
            return pair[1];
    }

    return false;
}

function doResults(data) {
    // Update the status
    $(Templates.successStatus({
        'input': data.input,
        'readings': data.readings,
        'numResults': data.results.length}))
        .appendTo($('#results-info').empty());

    //Create and add the results
    var parent = $('#results-container').empty()[0];

    for (var i=0; i < data.results.length; i++) {
        var result = Result(data.results[i], parent);
        RESULTLIST.push(result);
    }
}

function updateUrl() {
    var makeParam = function(param, value) {return param + '=' + value;};
    var params = [];

    params.push(makeParam('input', $('#input-text').val()));
    params.push(makeParam('count', $('#input-results').val()));
    params.push(makeParam('grammar', $('#input-grammar').val()));

    if ($('#input-tree').prop('checked'));
        params.push(makeParam('tree', 'true'));
    if ($('#input-mrs').prop('checked'));
        params.push(makeParam('mrs', 'true'));
    if ($('#input-dmrs').prop('checked'));
        params.push(makeParam('dmrs', 'true'));

    window.location.hash = encodeURI(params.join('&'));
}

function loadUrlParams() {
    var hash = decodeURI(window.location.hash);
    var params = hash.replace(/^#/, '').split('&');

    if (params.length === 0 || params[0] === "")
        return false;

    for (var i=0; i < params.length; i++) {
        var p = params[i];

        if (p == '')
            continue;

        var fields = p.split('=');
        var param = fields[0];
        var value = fields[1];

        if (param === '' || value === '')
            continue;

        if (param == 'input')
            $('#input-text').val(value);
        else if (param == 'grammar')
            $('#input-grammar').val(value);
        else if (param == 'count')
            $('#input-results').val(value);
        else if (param == 'tree')
            $('#input-tree').prop('checked', true);
        else if (param == 'mrs')
            $('#input-mrs').prop('checked', true);
        else if (param == 'dmrs')
            $('#input-dmrs').prop('checked', true);
    }
    return true;
}

$(document).ready(function(){

    $('#input-submit').click(function(event) {
        $.ajax({
            url: RESOURCES[$('#input-grammar')[0].value],
            dataType: 'json',
            data: {
                'derivation': $('#input-tree').prop('checked') ? 'json' : "null",
                'mrs': $('#input-mrs').prop('checked') ? 'json' : "null",
                'dmrs': $('#input-dmrs').prop('checked') ? 'json' : "null",
                'input': $('#input-text').val(),
                'results': $('#input-results').val()
            },
            dataFilter: function(data) {
                return data.replace(/([^,]) "pedges"/, '$1, "pedges"');
            },
            success: function(data){
                doResults(data);
                updateUrl();
            },
            error: function(data){
                alert("Error");
            }
        });
    });

    $('#input-grammar').on('focusin', function(){
        $(this).data('prev', $(this).val());
    });

    $('#input-grammar').change(function(event){
        // Change the sample text to appropriate language
        var prevGrammar = $(this).data('prev');
        var thisGrammar = $(this).val();
        var prevGramPrefix = prevGrammar.split('-')[0];
        var thisGramPrefix = thisGrammar.split('-')[0];

        if (prevGramPrefix != thisGramPrefix) {
            $('#input-text').val(SAMPLE_INPUT[thisGramPrefix]);
            $(this).data('prev', thisGrammar);
        }
    });

    if (loadUrlParams())
        $('#input-submit').trigger('click');

    if (getQueryVariable('dev') == 'true') {
        $.getJSON("elephant.json", function(data) {
            doResults(data);
        });
    }
});
<|endoftext|>


<commit_before>/**
 * React Static Boilerplate
 * https://github.com/koistya/react-static-boilerplate
 * Copyright (c) Konstantin Tarkus (@koistya) | MIT license
 */

import React, { Component } from 'react';
import './Footer.scss';
import Link from '../Link';

export default class extends Component {

  render() {
    return (

Community

                  About

                  Forum

                  Chat

                  Events

Social

                  Press

                  Twitter

                  YouTube

Resources

                  Github

                  Wiki

                This is an open sourced site hosted on GitHub. Patches, suggestions and comments are welcome.

              Made with  by the Blockstack community

    );
  }

}
<commit_msg>fix links in the footer<commit_after>/**
 * React Static Boilerplate
 * https://github.com/koistya/react-static-boilerplate
 * Copyright (c) Konstantin Tarkus (@koistya) | MIT license
 */

import React, { Component } from 'react';
import './Footer.scss';
import Link from '../Link';

export default class extends Component {

  render() {
    return (

Community

                  About

                  Forum

                  Chat

                  Events

Social

                  Press

                  Twitter

                  YouTube

Resources

                  Github

                  Wiki

                This is an open sourced site hosted on GitHub. Patches, suggestions and comments are welcome.

              Made with  by the Blockstack community

    );
  }

}
<|endoftext|>


<commit_before>import Cycle from '@cycle/core';
import { makeDOMDriver, div, h1, small } from '@cycle/dom';
import isolate from '@cycle/isolate';
import storageDriver from '@cycle/storage';
import { Observable } from 'rx';
import R from 'ramda';

import { trelloSinkDriver } from './drivers/Trello';
import { makeGraphDriver } from './drivers/Graph';

import LabeledSelect from './components/LabeledSelect/LabeledSelect';
import LabeledCheckbox from './components/LabeledCheckbox/LabeledCheckbox';
import LabeledDatePicker from './components/LabeledDatePicker/LabeledDatePicker';
import SelectDatesButton from './components/SelectDatesButton/SelectDatesButton';
import TrelloCFD from './components/TrelloCFD/TrelloCFD';
import TrelloKanbanMetrics from './components/TrelloKanbanMetrics/TrelloKanbanMetrics';

import {
  lastMonth,
  endOfLastMonth,
  currentMonth,
  today,
  tomorrow,
} from './utils/date';
import { getDisplayedLists } from './utils/trello';

function main({ DOMAboveChart, DOMBelowChart, TrelloFetch, TrelloMissingInfo, Storage }) {
  const publishedTrelloLists$ = TrelloFetch.lists$.publish();
  const publishedTrelloActions$ = TrelloFetch.actions$.publish();
  const publishedTrelloCardsActions$$ = TrelloMissingInfo.cardsActions$$.publish();

  const trelloLists$ = publishedTrelloLists$.startWith([]);
  const trelloActions$ = publishedTrelloActions$.startWith([]);

  // Checkbox to preview tomorrow CFD

  const previewTomorrow = isolate(LabeledCheckbox)({
    DOM: DOMAboveChart,
    props$: Observable.of({
      name: 'preview-tomorrow',
      label: 'Preview tomorrow CFD (include today operations)',
    }),
  });

  // Selects to choose displayed board and lists

  const boardSelectProps$ = Observable.combineLatest(
    TrelloFetch.boards$,
    Storage.local.getItem('selectedBoard').first(),
    (boards, storedBoard) => ({
      name: 'board',
      label: 'Board',
      classNames: ['browser-default'],
      select: (values) => R.defaultTo(R.head(values), storedBoard),

      // Render board names instead of shortLink when possible.
      render: (shortLink) => R.propOr(
        shortLink,
        'name',
        R.find(R.propEq('shortLink', shortLink), boards)
      ),
    })
  );

  const boardSelect = isolate(LabeledSelect)({
    DOM: DOMAboveChart,
    props$: boardSelectProps$,
    values$: TrelloFetch.boards$.map(R.pluck('shortLink')),
  });

  const firstDisplayedListSelect = isolate(LabeledSelect)({
    DOM: DOMAboveChart,
    props$: Storage.local.getItem('firstDisplayedList').first()
      .map((storedList) => ({
        name: 'first-displayed-list',
        label: 'Work begins',
        classNames: ['browser-default'],
        select: (values) => R.defaultTo(R.head(values), storedList),
      })),
    values$: trelloLists$.map(R.pluck('name')),
  });

  const lastDisplayedListSelect = isolate(LabeledSelect)({
    DOM: DOMAboveChart,
    props$: Storage.local.getItem('lastDisplayedList').first()
      .map((storedList) => ({
        name: 'last-displayed-list',
        label: 'Work ends',
        classNames: ['browser-default'],
        select: (values) => R.defaultTo(R.last(values), storedList),
      })),
    values$: trelloLists$.map(R.pluck('name')),
  });

  // Buttons to select period

  const selectLastMonthButton = isolate(SelectDatesButton)({
    DOM: DOMAboveChart,
    props$: Observable.of({
      label: 'Last month',
      classNames: ['btn waves-effect waves-light trello-blue'],
      startDate: lastMonth,
      endDate: endOfLastMonth,
    }),
  });

  const selectCurrentMonthButton = isolate(SelectDatesButton)({
    DOM: DOMAboveChart,
    props$: Observable.of({
      label: 'Current month',
      classNames: ['btn waves-effect waves-light trello-blue'],
      startDate: currentMonth,
      endDate: today,
    }),
  });

  const selectedPeriodDates$ = Observable.merge(
    selectLastMonthButton.dates$,
    selectCurrentMonthButton.dates$
  ).startWith({ startDate: currentMonth, endDate: today });

  // Datepickers to select dates

  const startDatePicker = isolate(LabeledDatePicker)({
    DOM: DOMAboveChart,
    props$: Observable.of({
      name: 'start-date',
      label: 'Start Date',
      max: today,
    }),
    value$: selectedPeriodDates$.map(R.prop('startDate')),
  });

  const endDatePicker = isolate(LabeledDatePicker)({
    DOM: DOMAboveChart,
    props$: Observable.of({
      name: 'end-date',
      label: 'End Date',
      max: today,
    }),
    value$: selectedPeriodDates$.map(R.prop('endDate')),
  });

  // Trello CFD

  const parseTrelloCFDDate = R.cond([
    [R.isEmpty, R.always(null)],
    [R.T, R.identity],
  ]);

  const trelloCFDDates$ = Observable.combineLatest(
    startDatePicker.selected$.map(parseTrelloCFDDate),
    endDatePicker.selected$.map(parseTrelloCFDDate),
    previewTomorrow.checked$,
    (startSelected, endSelected, previewTomorrowChecked) => ({
      startDate: startSelected,
      endDate: previewTomorrowChecked ? tomorrow : endSelected,
    })
  );

  const trelloDisplayedLists$ = Observable.combineLatest(
    trelloLists$,
    firstDisplayedListSelect.selected$,
    lastDisplayedListSelect.selected$,
    getDisplayedLists
  );

  const trelloCFD = TrelloCFD({
    DOM: DOMBelowChart,
    actions$: trelloActions$,
    lists$: trelloLists$,
    displayedLists$: trelloDisplayedLists$,
    dates$: trelloCFDDates$,
    props$: Observable.of({
      label: 'Get actions',
      classNames: ['btn waves-effect waves-light trello-green'],
    }),
    previewTomorrow$: previewTomorrow.checked$,
  });

  // Trello Kanban metrics

  const trelloKanbanMetrics = TrelloKanbanMetrics({
    actions$: trelloActions$,
    dates$: trelloCFDDates$,
    lists$: trelloDisplayedLists$,
    complementaryActions$: publishedTrelloCardsActions$$
      .switch()
      .startWith([])
      .scan(R.concat),
  });

  // Connect
  publishedTrelloLists$.connect();
  publishedTrelloActions$.connect();
  publishedTrelloCardsActions$$.connect();

  return {
    DOMAboveChart: Observable.combineLatest(
      boardSelect.DOM,
      trelloCFD.DOM,
      selectLastMonthButton.DOM,
      selectCurrentMonthButton.DOM,
      startDatePicker.DOM,
      endDatePicker.DOM,
      previewTomorrow.DOM,
      firstDisplayedListSelect.DOM,
      lastDisplayedListSelect.DOM,
      (
        boardVTree,
        trelloCFDVTree,
        selectLastMonthButtonVTree,
        selectCurrentMonthButtonVTree,
        startDatePickerVTree,
        endDatePickerVTree,
        previewTomorrowVTree,
        firstDisplayedListVTree,
        lastDisplayedListVTree
      ) => div([
        h1('.title.center-align.trello-blue.white-text', [
          'TKAT ',
          small('.trello-blue-100-text', '(Trello Kanban Analysis Tool)'),
        ]),
        div('.container', [
          div('.m-top.row', [
            div('.col.s6', [boardVTree]),
            div('.col.s3', [firstDisplayedListVTree]),
            div('.col.s3', [lastDisplayedListVTree]),
          ]),
          div('.m-top.row', [
            div('.col.s6', [startDatePickerVTree]),
            div('.col.s6', [endDatePickerVTree]),
          ]),
          div('.center-align-around', [
            trelloCFDVTree,
            selectLastMonthButtonVTree,
            selectCurrentMonthButtonVTree,
          ]),
          div('.m-top.row', [
            div('.col.s12', [previewTomorrowVTree]),
          ]),
        ]),
      ])
    ),
    DOMBelowChart: trelloKanbanMetrics.DOM.map(
      (trelloKanbanMetricsVTree) =>
        div('.container.m-top', [trelloKanbanMetricsVTree])
    ),
    TrelloFetch: Observable.combineLatest(
      boardSelect.selected$,
      trelloCFD.Trello,
      R.compose(R.head, R.unapply(R.identity))
    ),
    TrelloMissingInfo: trelloKanbanMetrics.Trello,
    Graph: trelloCFD.Graph,
    Storage: Observable.merge(
      boardSelect.selected$
        .map(selected => ({ key: 'selectedBoard', value: selected })),
      firstDisplayedListSelect.selected$
        .map(selected => ({ key: 'firstDisplayedList', value: selected })),
      lastDisplayedListSelect.selected$
        .map(selected => ({ key: 'lastDisplayedList', value: selected }))
    ),
  };
}

const drivers = {
  DOMAboveChart: makeDOMDriver('#above-chart'),
  DOMBelowChart: makeDOMDriver('#below-chart'),
  TrelloFetch: trelloSinkDriver,
  TrelloMissingInfo: trelloSinkDriver,
  Graph: makeGraphDriver('#chart svg'),
  Storage: storageDriver,
};

Trello.authorize({
  type: 'popup',
  name: 'Trello Kanban Analysis Tool',
  scope: { read: true },
  persist: true,
  expiration: 'never',
  success: () => {
    Cycle.run(main, drivers);
  },
  error: () => console.log("Can't connect to Trello"),
});
<commit_msg>Persist selected period<commit_after>import Cycle from '@cycle/core';
import { makeDOMDriver, div, h1, small } from '@cycle/dom';
import isolate from '@cycle/isolate';
import storageDriver from '@cycle/storage';
import { Observable } from 'rx';
import R from 'ramda';

import { trelloSinkDriver } from './drivers/Trello';
import { makeGraphDriver } from './drivers/Graph';

import LabeledSelect from './components/LabeledSelect/LabeledSelect';
import LabeledCheckbox from './components/LabeledCheckbox/LabeledCheckbox';
import LabeledDatePicker from './components/LabeledDatePicker/LabeledDatePicker';
import SelectDatesButton from './components/SelectDatesButton/SelectDatesButton';
import TrelloCFD from './components/TrelloCFD/TrelloCFD';
import TrelloKanbanMetrics from './components/TrelloKanbanMetrics/TrelloKanbanMetrics';

import {
  lastMonth,
  endOfLastMonth,
  currentMonth,
  today,
  tomorrow,
} from './utils/date';
import { getDisplayedLists } from './utils/trello';

function main({ DOMAboveChart, DOMBelowChart, TrelloFetch, TrelloMissingInfo, Storage }) {
  const publishedTrelloLists$ = TrelloFetch.lists$.publish();
  const publishedTrelloActions$ = TrelloFetch.actions$.publish();
  const publishedTrelloCardsActions$$ = TrelloMissingInfo.cardsActions$$.publish();

  const trelloLists$ = publishedTrelloLists$.startWith([]);
  const trelloActions$ = publishedTrelloActions$.startWith([]);

  // Checkbox to preview tomorrow CFD

  const previewTomorrow = isolate(LabeledCheckbox)({
    DOM: DOMAboveChart,
    props$: Observable.of({
      name: 'preview-tomorrow',
      label: 'Preview tomorrow CFD (include today operations)',
    }),
  });

  // Selects to choose displayed board and lists

  const boardSelectProps$ = Observable.combineLatest(
    TrelloFetch.boards$,
    Storage.local.getItem('selectedBoard').first(),
    (boards, storedBoard) => ({
      name: 'board',
      label: 'Board',
      classNames: ['browser-default'],
      select: (values) => R.defaultTo(R.head(values), storedBoard),

      // Render board names instead of shortLink when possible.
      render: (shortLink) => R.propOr(
        shortLink,
        'name',
        R.find(R.propEq('shortLink', shortLink), boards)
      ),
    })
  );

  const boardSelect = isolate(LabeledSelect)({
    DOM: DOMAboveChart,
    props$: boardSelectProps$,
    values$: TrelloFetch.boards$.map(R.pluck('shortLink')),
  });

  const firstDisplayedListSelect = isolate(LabeledSelect)({
    DOM: DOMAboveChart,
    props$: Storage.local.getItem('firstDisplayedList').first()
      .map((storedList) => ({
        name: 'first-displayed-list',
        label: 'Work begins',
        classNames: ['browser-default'],
        select: (values) => R.defaultTo(R.head(values), storedList),
      })),
    values$: trelloLists$.map(R.pluck('name')),
  });

  const lastDisplayedListSelect = isolate(LabeledSelect)({
    DOM: DOMAboveChart,
    props$: Storage.local.getItem('lastDisplayedList').first()
      .map((storedList) => ({
        name: 'last-displayed-list',
        label: 'Work ends',
        classNames: ['browser-default'],
        select: (values) => R.defaultTo(R.last(values), storedList),
      })),
    values$: trelloLists$.map(R.pluck('name')),
  });

  // Buttons to select period

  const selectLastMonthButton = isolate(SelectDatesButton)({
    DOM: DOMAboveChart,
    props$: Observable.of({
      label: 'Last month',
      classNames: ['btn waves-effect waves-light trello-blue'],
      startDate: lastMonth,
      endDate: endOfLastMonth,
    }),
  });

  const selectCurrentMonthButton = isolate(SelectDatesButton)({
    DOM: DOMAboveChart,
    props$: Observable.of({
      label: 'Current month',
      classNames: ['btn waves-effect waves-light trello-blue'],
      startDate: currentMonth,
      endDate: today,
    }),
  });

  const selectPeriod$ = Observable.concat(
    Observable.combineLatest(
      Storage.local.getItem('selectedStartDate').first()
        .map(R.defaultTo(currentMonth)),
      Storage.local.getItem('selectedEndDate').first()
        .map(R.defaultTo(today)),
      (startDate, endDate) => ({ startDate, endDate })
    ),
    Observable.merge(
      selectLastMonthButton.dates$,
      selectCurrentMonthButton.dates$
    )
  );

  // Datepickers to select dates

  const startDatePicker = isolate(LabeledDatePicker)({
    DOM: DOMAboveChart,
    props$: Observable.of({
      name: 'start-date',
      label: 'Start Date',
      max: today,
    }),
    value$: selectPeriod$.map(R.prop('startDate')),
  });

  const endDatePicker = isolate(LabeledDatePicker)({
    DOM: DOMAboveChart,
    props$: Observable.of({
      name: 'end-date',
      label: 'End Date',
      max: today,
    }),
    value$: selectPeriod$.map(R.prop('endDate')),
  });

  // Trello CFD

  const parseSelectedDate = R.cond([
    [R.isEmpty, R.always(null)],
    [R.T, R.identity],
  ]);

  const selectedDates$ = Observable.combineLatest(
    startDatePicker.selected$.map(parseSelectedDate),
    endDatePicker.selected$.map(parseSelectedDate),
    previewTomorrow.checked$,
    (startSelected, endSelected, previewTomorrowChecked) => ({
      startDate: startSelected,
      endDate: previewTomorrowChecked ? tomorrow : endSelected,
    })
  );

  const trelloDisplayedLists$ = Observable.combineLatest(
    trelloLists$,
    firstDisplayedListSelect.selected$,
    lastDisplayedListSelect.selected$,
    getDisplayedLists
  );

  const trelloCFD = TrelloCFD({
    DOM: DOMBelowChart,
    actions$: trelloActions$,
    lists$: trelloLists$,
    displayedLists$: trelloDisplayedLists$,
    dates$: selectedDates$,
    props$: Observable.of({
      label: 'Get actions',
      classNames: ['btn waves-effect waves-light trello-green'],
    }),
    previewTomorrow$: previewTomorrow.checked$,
  });

  // Trello Kanban metrics

  const trelloKanbanMetrics = TrelloKanbanMetrics({
    actions$: trelloActions$,
    dates$: selectedDates$,
    lists$: trelloDisplayedLists$,
    complementaryActions$: publishedTrelloCardsActions$$
      .switch()
      .startWith([])
      .scan(R.concat),
  });

  // Connect
  publishedTrelloLists$.connect();
  publishedTrelloActions$.connect();
  publishedTrelloCardsActions$$.connect();

  return {
    DOMAboveChart: Observable.combineLatest(
      boardSelect.DOM,
      trelloCFD.DOM,
      selectLastMonthButton.DOM,
      selectCurrentMonthButton.DOM,
      startDatePicker.DOM,
      endDatePicker.DOM,
      previewTomorrow.DOM,
      firstDisplayedListSelect.DOM,
      lastDisplayedListSelect.DOM,
      (
        boardVTree,
        trelloCFDVTree,
        selectLastMonthButtonVTree,
        selectCurrentMonthButtonVTree,
        startDatePickerVTree,
        endDatePickerVTree,
        previewTomorrowVTree,
        firstDisplayedListVTree,
        lastDisplayedListVTree
      ) => div([
        h1('.title.center-align.trello-blue.white-text', [
          'TKAT ',
          small('.trello-blue-100-text', '(Trello Kanban Analysis Tool)'),
        ]),
        div('.container', [
          div('.m-top.row', [
            div('.col.s6', [boardVTree]),
            div('.col.s3', [firstDisplayedListVTree]),
            div('.col.s3', [lastDisplayedListVTree]),
          ]),
          div('.m-top.row', [
            div('.col.s6', [startDatePickerVTree]),
            div('.col.s6', [endDatePickerVTree]),
          ]),
          div('.center-align-around', [
            trelloCFDVTree,
            selectLastMonthButtonVTree,
            selectCurrentMonthButtonVTree,
          ]),
          div('.m-top.row', [
            div('.col.s12', [previewTomorrowVTree]),
          ]),
        ]),
      ])
    ),
    DOMBelowChart: trelloKanbanMetrics.DOM.map(
      (trelloKanbanMetricsVTree) =>
        div('.container.m-top', [trelloKanbanMetricsVTree])
    ),
    TrelloFetch: Observable.combineLatest(
      boardSelect.selected$,
      trelloCFD.Trello,
      R.compose(R.head, R.unapply(R.identity))
    ),
    TrelloMissingInfo: trelloKanbanMetrics.Trello,
    Graph: trelloCFD.Graph,
    Storage: Observable.merge(
      boardSelect.selected$
        .map(selected => ({ key: 'selectedBoard', value: selected })),
      firstDisplayedListSelect.selected$
        .map(selected => ({ key: 'firstDisplayedList', value: selected })),
      lastDisplayedListSelect.selected$
        .map(selected => ({ key: 'lastDisplayedList', value: selected })),
      selectedDates$
        .map(period => ({ key: 'selectedStartDate', value: period.startDate })),
      selectedDates$
        .map(period => ({ key: 'selectedEndDate', value: period.endDate }))
    ),
  };
}

const drivers = {
  DOMAboveChart: makeDOMDriver('#above-chart'),
  DOMBelowChart: makeDOMDriver('#below-chart'),
  TrelloFetch: trelloSinkDriver,
  TrelloMissingInfo: trelloSinkDriver,
  Graph: makeGraphDriver('#chart svg'),
  Storage: storageDriver,
};

Trello.authorize({
  type: 'popup',
  name: 'Trello Kanban Analysis Tool',
  scope: { read: true },
  persist: true,
  expiration: 'never',
  success: () => {
    Cycle.run(main, drivers);
  },
  error: () => console.log("Can't connect to Trello"),
});
<|endoftext|>


<commit_before>/* MIT (c) Juho Vepsalainen */
(function($) {
    $.fn.qdemo = function(title, pluginName, parentElement, inputCb) {
        // http://javascript.crockford.com/remedial.html
        function typeOf(value) {
            var s = typeof value;

            if (s === 'object') {
                if (value) {
                    if (value instanceof Array) {
                        s = 'array';
                    }
                } else {
                    s = 'null';
                }
            }

            return s;
        }

        function trim(str) {
            // http://blog.stevenlevithan.com/archives/faster-trim-javascript
            var str = str.replace(/^\s\s*/, '');
            var ws = /\s/;
            var i = str.length;

            while (ws.test(str.charAt(--i)));

            return str.slice(0, i + 1);
        }

        function camelcase(str) {
            var s = trim(str);

            return ( /\S[A-Z]/.test( s ) ) ?
                s.replace( /(.)([A-Z])/g, function(t,a,b) { return a + ' ' + b.toLowerCase(); } ) :
                s.replace( /( )([a-z])/g, function(t,a,b) { return b.toUpperCase(); } );
        };

        function capitalize(str) {
            return str.charAt(0).toUpperCase() + str.slice(1);
        };

        function isInt(value) {
            return !isNaN(parseInt(value));
        }

        function constructUI(options) {
            function textInput(name, id, value) {
                return input(name, id, value, 'text');
            }

            function checkboxInput(name, id, value) {
                return input(name, id, value, 'checkbox');
            }

            function input(name, id, value, type) {
                if (id == undefined) {
                    return '<input type="' + type + '" name="' + name +
                        '" value="' + value + '"></input>';
                }

                return '' + name + ': ' +
                    '<input type="' + type + '" id="' + id +
                    '" name="' + name + '"' +
                    '" value="' + value + '"></input>';
            }

            function legend(title) {
                return '<legend>' + title + '</legend>';
            }

            function format(str) {
                return capitalize(camelcase(str));
            }

            function _recursion(options, title) {
                var $ret = $('<fieldset id="' + title + '">');

                $ret.append(legend(format(title)));

                for (var optionName in options) {
                    var optionValue = options[optionName];

                    var types = {
                        "string": function() {
                            $ret.append(textInput(format(optionName),
                                optionName, optionValue));
                        },
                        "number": function() {this.string()},
                        "boolean": function() {
                            $ret.append(checkboxInput(format(optionName),
                                optionName, optionValue));

                            $ret.find('#' + optionName).attr('checked',
                                optionValue);
                        },
                        "array": function() {
                            var $fieldset = $('<fieldset id="' +
                                optionName + '">');

                            $fieldset.append(legend(format(optionName) +
                                textInput('arrayAmount', null,
                                optionValue.length)));

                            for (var i = 0; i < optionValue.length; i++) {
                                var optionItem = optionValue[i];
                                var itemName = optionName + '[]';

                                $fieldset.append(textInput(
                                    format(itemName), null, optionItem));
                            }

                            $ret.append($fieldset);
                        },
                        "object": function() {
                            var uiStructure = _recursion(optionValue,
                                optionName);

                            $ret.append(uiStructure);
                        },
                        "null": function() {}
                    }[typeOf(optionValue)]();
                }

                return $ret;
            }

            var $ret = _recursion(options, 'pluginOptions');
            $ret.prepend(textInput(format('parentElement'), 'parentElement',
                parentElement || '

'));

            return $ret;
        }

        function getSize(ob) {
            var size = 0;

            for (var e in ob) { size++; }

            return size;
        }

        function getPluginOptions() {
            var ret = {};

            function _recursion(parent, target) {
                $('#' + parent).children().each(function() {
                    if ($(this).is(':visible')) {
                        if ($(this).is('fieldset')) {
                            var newTarget;

                            if (target == undefined) {
                                if (!(this.id in ret)) {
                                    var foundArray = $(this).
                                        find('input[name=arrayAmount]').length;

                                    ret[this.id] = foundArray? []: {};
                                }

                                newTarget = ret[this.id];
                            }
                            else {
                                if (!(this.id in target)) {
                                    var foundArray = $(this).
                                        find('input[name=arrayAmount]').length;

                                    target[this.id] = foundArray? []: {};
                                }

                                newTarget = target[this.id];
                            }

                            _recursion(this.id, newTarget);
                        }

                        if ($(this).is('input')) {
                            var type = $(this).attr('type');
                            var value;

                            if (type == 'text') {
                                value = $(this).val();

                                if (isInt(value)) {
                                    value = parseInt(value);
                                }
                            }
                            else if (type == 'checkbox') {
                                value = $(this).attr('checked')? true: false;
                            }

                            if (this.id) {
                                if (target == undefined) {
                                    ret[this.id] = value;
                                }
                                else {
                                    target[this.id] = value;
                                }
                            }
                            else {
                                ret[parent].push(value);
                            }
                        }
                    }
                });
            }

            _recursion('pluginOptions');

            // parentElement is a special case, no need to pass that
            delete ret['parentElement'];

            return ret;
        }

        function constructCode(options) {
            var ret = '$(parent).colorPicker(';

            function stringify(a) {
                if(typeOf(a) == 'string') {
                    return "'" + a + "'";
                }

                return a;
            }

            function _recursion(values) {
                var i = 0;
                var size = getSize(values);

                ret += '{';

                for (var name in values) {
                    var value = values[name];

                    if(name == 'parentElement') {
                        continue;
                    }

                    ret += name + ': ';
                    if (typeOf(value) == 'object') {
                        _recursion(value);
                    }
                    else if (typeOf(value) == 'array') {
                        ret += '[';

                        for (var j = 0; j < value.length; j++) {
                            var item = value[j];

                            ret += stringify(item);

                            // skip last ,
                            if (j < value.length - 1) {
                                ret += ', ';
                            }
                        }

                        ret += ']';
                    }
                    else {
                        ret += stringify(value);
                    }

                    // skip last ,
                    i++;
                    if (i < size) {
                        ret += ', ';
                    }
                }

                ret += '}';
            }

            _recursion(options);

            ret += ')';

            return ret;
        }

        $(this[0]).append('<form>' +
            '<fieldset><legend>' + title + '</legend>' +
            '

</fieldset>' +
            '</form>' +
            '<form>' +
            '<fieldset><legend>Code</legend>' +
            '

' +
            '</fieldset>' +
            '</form>' +
            '<form>' +
            '<fieldset><legend>Plugin</legend>' +
            '

' +
            '</fieldset>' +
            '</form>'
        );

        var options = $.fn[pluginName].options;
        var $uiStructure = constructUI(options);
        $('#options').append($uiStructure);

        $("input[name=arrayAmount]").change(function() {
            var amount = $(this).val();

            if (isInt(amount)) {
                var $fieldset = $(this).parent().parent('fieldset');
                var $inputs = $fieldset.children('input');
                var inputAmount = $inputs.length;

                $inputs.show();

                if (amount <= inputAmount) {
                    $fieldset.children('input:gt(' +
                        (amount - 1) + ')').hide();
                }
                else {
                    var amountOfMissingInputs = amount - inputAmount;

                    for (var i = 0; i < amountOfMissingInputs; i++) {
                        var input = $inputs[0].cloneNode();
                        input.value = '';

                        $fieldset.append(input);
                    }
                }
            }
        });

        $("input").live('change', function() {
            var pluginOptions = getPluginOptions();
            var code = constructCode(pluginOptions);

            $("#code").text(code);

            var parent = $('#parentElement').val();
            var $parentElement = $(parent).attr('id', 'plugin');
            $('#pluginContainer').children().remove();
            $('#pluginContainer').append($parentElement);
            $('#plugin')[pluginName](pluginOptions);

            if (typeOf(inputCb) == 'function') {
                inputCb(parent);
            }
        }).change();
    };
})(jQuery);
<commit_msg>Mark code as pre<commit_after>/* MIT (c) Juho Vepsalainen */
(function($) {
    $.fn.qdemo = function(title, pluginName, parentElement, inputCb) {
        // http://javascript.crockford.com/remedial.html
        function typeOf(value) {
            var s = typeof value;

            if (s === 'object') {
                if (value) {
                    if (value instanceof Array) {
                        s = 'array';
                    }
                } else {
                    s = 'null';
                }
            }

            return s;
        }

        function trim(str) {
            // http://blog.stevenlevithan.com/archives/faster-trim-javascript
            var str = str.replace(/^\s\s*/, '');
            var ws = /\s/;
            var i = str.length;

            while (ws.test(str.charAt(--i)));

            return str.slice(0, i + 1);
        }

        function camelcase(str) {
            var s = trim(str);

            return ( /\S[A-Z]/.test( s ) ) ?
                s.replace( /(.)([A-Z])/g, function(t,a,b) { return a + ' ' + b.toLowerCase(); } ) :
                s.replace( /( )([a-z])/g, function(t,a,b) { return b.toUpperCase(); } );
        };

        function capitalize(str) {
            return str.charAt(0).toUpperCase() + str.slice(1);
        };

        function isInt(value) {
            return !isNaN(parseInt(value));
        }

        function constructUI(options) {
            function textInput(name, id, value) {
                return input(name, id, value, 'text');
            }

            function checkboxInput(name, id, value) {
                return input(name, id, value, 'checkbox');
            }

            function input(name, id, value, type) {
                if (id == undefined) {
                    return '<input type="' + type + '" name="' + name +
                        '" value="' + value + '"></input>';
                }

                return '' + name + ': ' +
                    '<input type="' + type + '" id="' + id +
                    '" name="' + name + '"' +
                    '" value="' + value + '"></input>';
            }

            function legend(title) {
                return '<legend>' + title + '</legend>';
            }

            function format(str) {
                return capitalize(camelcase(str));
            }

            function _recursion(options, title) {
                var $ret = $('<fieldset id="' + title + '">');

                $ret.append(legend(format(title)));

                for (var optionName in options) {
                    var optionValue = options[optionName];

                    var types = {
                        "string": function() {
                            $ret.append(textInput(format(optionName),
                                optionName, optionValue));
                        },
                        "number": function() {this.string()},
                        "boolean": function() {
                            $ret.append(checkboxInput(format(optionName),
                                optionName, optionValue));

                            $ret.find('#' + optionName).attr('checked',
                                optionValue);
                        },
                        "array": function() {
                            var $fieldset = $('<fieldset id="' +
                                optionName + '">');

                            $fieldset.append(legend(format(optionName) +
                                textInput('arrayAmount', null,
                                optionValue.length)));

                            for (var i = 0; i < optionValue.length; i++) {
                                var optionItem = optionValue[i];
                                var itemName = optionName + '[]';

                                $fieldset.append(textInput(
                                    format(itemName), null, optionItem));
                            }

                            $ret.append($fieldset);
                        },
                        "object": function() {
                            var uiStructure = _recursion(optionValue,
                                optionName);

                            $ret.append(uiStructure);
                        },
                        "null": function() {}
                    }[typeOf(optionValue)]();
                }

                return $ret;
            }

            var $ret = _recursion(options, 'pluginOptions');
            $ret.prepend(textInput(format('parentElement'), 'parentElement',
                parentElement || '

'));

            return $ret;
        }

        function getSize(ob) {
            var size = 0;

            for (var e in ob) { size++; }

            return size;
        }

        function getPluginOptions() {
            var ret = {};

            function _recursion(parent, target) {
                $('#' + parent).children().each(function() {
                    if ($(this).is(':visible')) {
                        if ($(this).is('fieldset')) {
                            var newTarget;

                            if (target == undefined) {
                                if (!(this.id in ret)) {
                                    var foundArray = $(this).
                                        find('input[name=arrayAmount]').length;

                                    ret[this.id] = foundArray? []: {};
                                }

                                newTarget = ret[this.id];
                            }
                            else {
                                if (!(this.id in target)) {
                                    var foundArray = $(this).
                                        find('input[name=arrayAmount]').length;

                                    target[this.id] = foundArray? []: {};
                                }

                                newTarget = target[this.id];
                            }

                            _recursion(this.id, newTarget);
                        }

                        if ($(this).is('input')) {
                            var type = $(this).attr('type');
                            var value;

                            if (type == 'text') {
                                value = $(this).val();

                                if (isInt(value)) {
                                    value = parseInt(value);
                                }
                            }
                            else if (type == 'checkbox') {
                                value = $(this).attr('checked')? true: false;
                            }

                            if (this.id) {
                                if (target == undefined) {
                                    ret[this.id] = value;
                                }
                                else {
                                    target[this.id] = value;
                                }
                            }
                            else {
                                ret[parent].push(value);
                            }
                        }
                    }
                });
            }

            _recursion('pluginOptions');

            // parentElement is a special case, no need to pass that
            delete ret['parentElement'];

            return ret;
        }

        function constructCode(options) {
            var ret = '$(parent).colorPicker(';

            function stringify(a) {
                if(typeOf(a) == 'string') {
                    return "'" + a + "'";
                }

                return a;
            }

            function _recursion(values) {
                var i = 0;
                var size = getSize(values);

                ret += '{';

                for (var name in values) {
                    var value = values[name];

                    if(name == 'parentElement') {
                        continue;
                    }

                    ret += name + ': ';
                    if (typeOf(value) == 'object') {
                        _recursion(value);
                    }
                    else if (typeOf(value) == 'array') {
                        ret += '[';

                        for (var j = 0; j < value.length; j++) {
                            var item = value[j];

                            ret += stringify(item);

                            // skip last ,
                            if (j < value.length - 1) {
                                ret += ', ';
                            }
                        }

                        ret += ']';
                    }
                    else {
                        ret += stringify(value);
                    }

                    // skip last ,
                    i++;
                    if (i < size) {
                        ret += ', ';
                    }
                }

                ret += '}';
            }

            _recursion(options);

            ret += ')';

            return ret;
        }

        $(this[0]).append('<form>' +
            '<fieldset><legend>' + title + '</legend>' +
            '

</fieldset>' +
            '</form>' +
            '<form>' +
            '<fieldset><legend>Code</legend>' +
            '

' +
            '</fieldset>' +
            '</form>' +
            '<form>' +
            '<fieldset><legend>Plugin</legend>' +
            '

' +
            '</fieldset>' +
            '</form>'
        );

        var options = $.fn[pluginName].options;
        var $uiStructure = constructUI(options);
        $('#options').append($uiStructure);

        $("input[name=arrayAmount]").change(function() {
            var amount = $(this).val();

            if (isInt(amount)) {
                var $fieldset = $(this).parent().parent('fieldset');
                var $inputs = $fieldset.children('input');
                var inputAmount = $inputs.length;

                $inputs.show();

                if (amount <= inputAmount) {
                    $fieldset.children('input:gt(' +
                        (amount - 1) + ')').hide();
                }
                else {
                    var amountOfMissingInputs = amount - inputAmount;

                    for (var i = 0; i < amountOfMissingInputs; i++) {
                        var input = $inputs[0].cloneNode();
                        input.value = '';

                        $fieldset.append(input);
                    }
                }
            }
        });

        $("input").live('change', function() {
            var pluginOptions = getPluginOptions();
            var code = constructCode(pluginOptions);

            $("#code").text(code);

            var parent = $('#parentElement').val();
            var $parentElement = $(parent).attr('id', 'plugin');
            $('#pluginContainer').children().remove();
            $('#pluginContainer').append($parentElement);
            $('#plugin')[pluginName](pluginOptions);

            if (typeOf(inputCb) == 'function') {
                inputCb(parent);
            }
        }).change();
    };
})(jQuery);
<|endoftext|>


<commit_before>"use strict";
var logger = process.require("api/logger.js").get("logger");
var bnetAPI = process.require("api/bnet.js");
var async = require("async");
var guildUpdateModel = process.require("models/guildUpdateModel.js");
var guildService = process.require("services/guildService.js");

//Configuration
var env = process.env.NODE_ENV || 'dev';
var config = process.require('config/config.'+env+'.json');

module.exports.importAuctions = function(){

    async.eachSeries(config.bnet_regions,function(region,callback) {
        //Get Realms
        bnetAPI.getRealms(region, function (error, realms) {
            if (error) {
                logger.error(error.message)
                return;
            }
            async.eachSeries(realms.realms,function(realm,callback){
                bnetAPI.getAuctions(region, realm.name, function (error, auctions) {
                    async.eachSeries(auctions.auctions, function (auction, callback) {
                        bnetAPI.getCharacter(region, realm.name, auction.owner, function (error, character) {
                            if (error || !character.guild) {
                                callback();
                                return;
                            }
                            guildService.get(region, character.realm, character.guild.name,function(error,guild){
                                if (error || !character.guild) {
                                    callback();
                                    return;
                                }
                                var timestampWeekAgo = new Date().getTime() - (7 * 24 * 3600 * 1000);
                                if(guild == null || guild.bnet.updated < timestampWeekAgo ) {
                                    guildUpdateModel.insertOrUpdate(region, character.realm, character.guild.name, 0, function (error) {
                                        logger.info("Insert guild  to update " + region + "-" + character.realm + "-" + character.guild.name);
                                        callback();
                                    });
                                }
                            });
                        });
                    },function(){
                        callback();
                    });
                });
            },function(){
                callback();
            });

        });
    });

};<commit_msg>Correcting  blocking issue on auction import<commit_after>"use strict";
var logger = process.require("api/logger.js").get("logger");
var bnetAPI = process.require("api/bnet.js");
var async = require("async");
var guildUpdateModel = process.require("models/guildUpdateModel.js");
var guildService = process.require("services/guildService.js");

//Configuration
var env = process.env.NODE_ENV || 'dev';
var config = process.require('config/config.'+env+'.json');

module.exports.importAuctions = function(){

    async.eachSeries(config.bnet_regions,function(region,callback) {
        //Get Realms
        bnetAPI.getRealms(region, function (error, realms) {
            if (error) {
                logger.error(error.message)
                return;
            }
            async.eachSeries(realms.realms,function(realm,callback){
                bnetAPI.getAuctions(region, realm.name, function (error, auctions) {
                    async.eachSeries(auctions.auctions, function (auction, callback) {
                        bnetAPI.getCharacter(region, realm.name, auction.owner, function (error, character) {
                            if (error || !character.guild) {
                                callback();
                                return;
                            }
                            guildService.get(region, character.realm, character.guild.name,function(error,guild){
                                if (error || !character.guild) {
                                    callback();
                                    return;
                                }
                                var timestampWeekAgo = new Date().getTime() - (7 * 24 * 3600 * 1000);
                                if(guild == null || guild.bnet.updated < timestampWeekAgo ) {
                                    guildUpdateModel.insertOrUpdate(region, character.realm, character.guild.name, 0, function (error) {
                                        logger.info("Insert guild  to update " + region + "-" + character.realm + "-" + character.guild.name);
                                        callback();
                                    });
                                }
                                else{
                                    callback();
                                }
                            });
                        });
                    },function(){
                        callback();
                    });
                });
            },function(){
                callback();
            });

        });
    });

};<|endoftext|>