<commit_before>var tower_Operate = {
    run: function(tower, thisRoom) {
        var thisTower = Game.getObjectById(tower);

        var UnderAttackPos = Memory.roomsUnderAttack.indexOf(thisRoom.name);
        if (UnderAttackPos >= 0 && thisTower.energy > 0) {
            var closestHostile = thisTower.pos.findInRange(FIND_HOSTILE_CREEPS, 15, {
                filter: (creep) => (creep.getActiveBodyparts(WORK) > 0 || creep.getActiveBodyparts(CARRY) > 0 || creep.getActiveBodyparts(ATTACK) > 0 || creep.getActiveBodyparts(RANGED_ATTACK) > 0 || creep.getActiveBodyparts(HEAL) > 0) || (creep.hits <= 500)
            });
            if (closestHostile.length > 0) {
                //Target healing creeps first
                closestHostile.sort(towerPartsCompare);
                thisTower.attack(closestHostile[0]);
            }
        } else if (thisTower.energy > (thisTower.energyCapacity * 0.5)) {
            //Save 50% of the tower's energy to use on repelling attackers
            var closestDamagedCreep = thisTower.pos.findClosestByRange(FIND_MY_CREEPS, {
                filter: (creep) => creep.hits < creep.hitsMax
            });
            if (closestDamagedCreep) {
                thisTower.heal(closestDamagedCreep);
            }
        }

        thisRoom.visual.rect(tower.pos.x - 15, tower.pos.y - 15, 30, 30, {fill: '#ff0019', opacity: 0.2});
    }
};

module.exports = tower_Operate;

function towerPartsCompare(a, b) {
    if (a.getActiveBodyparts(HEAL) < b.getActiveBodyparts(HEAL))
        return 1;
    if (a.getActiveBodyparts(HEAL) > b.getActiveBodyparts(HEAL))
        return -1;
    return 0;
}<commit_msg>hang on here<commit_after>var tower_Operate = {
    run: function(tower, thisRoom) {
        var thisTower = Game.getObjectById(tower);

        var UnderAttackPos = Memory.roomsUnderAttack.indexOf(thisRoom.name);
        if (UnderAttackPos >= 0 && thisTower.energy > 0) {
            var closestHostile = thisTower.pos.findInRange(FIND_HOSTILE_CREEPS, 15, {
                filter: (creep) => (creep.getActiveBodyparts(WORK) > 0 || creep.getActiveBodyparts(CARRY) > 0 || creep.getActiveBodyparts(ATTACK) > 0 || creep.getActiveBodyparts(RANGED_ATTACK) > 0 || creep.getActiveBodyparts(HEAL) > 0) || (creep.hits <= 500)
            });
            if (closestHostile.length > 0) {
                //Target healing creeps first
                closestHostile.sort(towerPartsCompare);
                thisTower.attack(closestHostile[0]);
            }
        } else if (thisTower.energy > (thisTower.energyCapacity * 0.5)) {
            //Save 50% of the tower's energy to use on repelling attackers
            var closestDamagedCreep = thisTower.pos.findClosestByRange(FIND_MY_CREEPS, {
                filter: (creep) => creep.hits < creep.hitsMax
            });
            if (closestDamagedCreep) {
                thisTower.heal(closestDamagedCreep);
            }
        }

        //thisRoom.visual.rect(tower.pos.x - 15, tower.pos.y - 15, 30, 30, {fill: '#ff0019', opacity: 0.2});
    }
};

module.exports = tower_Operate;

function towerPartsCompare(a, b) {
    if (a.getActiveBodyparts(HEAL) < b.getActiveBodyparts(HEAL))
        return 1;
    if (a.getActiveBodyparts(HEAL) > b.getActiveBodyparts(HEAL))
        return -1;
    return 0;
}<|endoftext|>


<commit_before>const ee = require('sepal/ee')
const {map, of, zip} = require('rxjs')
const imageFactory = require('sepal/ee/imageFactory')
const _ = require('lodash')

const createClassChange =
    ({
        model: {
            fromImage,
            toImage,
            options: {
                minConfidence = 0
            }
        }
    },
    {selection: selectedBands} = {selection: []}
    ) => {
        return {
            getImage$() {
                return zip(
                    imageFactory(fromImage).getImage$(),
                    imageFactory(toImage).getImage$(),
                ).pipe(
                    map(([fromEEImage, toEEImage]) => {
                        const image = calculateClassChange({
                            fromEEImage,
                            fromValues: fromImage.legendEntries.map(({value}) => value).sort(),
                            fromBand: fromImage.band,
                            toEEImage,
                            toValues: toImage.legendEntries.map(({value}) => value).sort(),
                            toBand: toImage.band,
                            minConfidence
                        })

                        return selectedBands.length
                            ? image.select(_.uniq(selectedBands))
                            : image
                    })
                )
            },
            getBands$() {
                const hasConfidence = () => {
                    const fromEntries = fromImage.legendEntries
                        .map(({value, label}) => ({value, label}))
                    const toEntries = toImage.legendEntries
                        .map(({value, label}) => ({value, label}))
                    if (!_.isEqual(new Set(fromEntries), new Set(toEntries))) {
                        return false
                    } else {
                        const fromBands = Object.keys(fromImage.bands)
                        const toBands = Object.keys(toImage.bands)
                        const probabilityBands = fromEntries.map(({value}) => `probability_${value}`)
                        return probabilityBands.every(band => fromBands.includes(band))
                            && probabilityBands.every(band => toBands.includes(band))
                    }
                }

                return of([
                    ['transition'],
                    hasConfidence() ? ['confidence'] : []
                ].flat())
            },
            getGeometry$() {
                return imageFactory(fromImage).getGeometry$()
            }
        }
    }

const calculateClassChange = ({
    fromEEImage,
    fromValues,
    fromBand,
    toEEImage,
    toValues,
    toBand,
    minConfidence
}) => {
    const fromValue = fromEEImage.select(fromBand)
    const toValue = toEEImage.select(fromBand)

    const fromValuesWithProbabilities = findValuesWithProbabilities(fromEEImage)
    const toValuesWithProbabilities = findValuesWithProbabilities(toEEImage)

    const fromProbabilityArray = createProbabilityArray(fromEEImage, fromValuesWithProbabilities)
    const toProbabilityArray = createProbabilityArray(toEEImage, toValuesWithProbabilities)

    const maxNumberOfValues = fromValuesWithProbabilities.size().max(toValuesWithProbabilities.size())

    const fromProbability = getProbability(fromValue, fromProbabilityArray, fromValuesWithProbabilities, maxNumberOfValues)
    const toProbability = getProbability(toValue, toProbabilityArray, toValuesWithProbabilities, maxNumberOfValues)

    const fromInToProbability = getProbability(fromValue, toProbabilityArray, toValuesWithProbabilities, maxNumberOfValues)
    const toInFromProbability = getProbability(toValue, fromProbabilityArray, fromValuesWithProbabilities, maxNumberOfValues)

    const toCertainty = toProbability.subtract(fromInToProbability)
    const fromCertainty = fromProbability.subtract(toInFromProbability)
    const confidence = ee.ImageCollection([toCertainty, fromCertainty])
        .mean()
        .updateMask(fromValue.neq(toValue))
        .rename('confidence')

    const mostProbableValue = toValue
        .where(toProbability.gt(fromProbability), toValue)
        .where(toProbability.lte(fromProbability), fromValue)

    const fromValueAdjusted = fromValue
        .where(confidence.lt(minConfidence), mostProbableValue)
    const toValueAdjusted = toValue
        .where(confidence.lt(minConfidence), mostProbableValue)

    const fromIndex = valueIndex(fromValueAdjusted, fromValues, fromBand)
    const toIndex = valueIndex(toValueAdjusted, toValues, toBand)

    const transition = fromIndex.multiply(toValues.length).add(toIndex).add(1)
        .rename('transition')

    return transition
        .addBands(confidence)
        .clip(fromEEImage.geometry())

}

const getProbability = (value, probabilityArray, valuesWithProbabilities, maxNumberOfValues) => {
    const probability = probabilityArray
        .arrayPad([maxNumberOfValues], -1)
        .arrayMask(
            ee.Image(ee.Array(valuesWithProbabilities))
                .arrayPad([maxNumberOfValues], -1)
                .eq(value)
        )
    return probability
        .updateMask(probability.arrayLength(0))
        .arrayGet([0])
}

const valueIndex = (value, values, band) => {
    const arrayMask = createArrayMask(value, values, band)
    const indexes = ee.Image(ee.Array(ee.List.sequence(0, ee.List(values).size().subtract(1))))
    const index = indexes
        .arrayMask(arrayMask)
    return index
        .updateMask(index.arrayLength(0))
        .arrayGet([0])
}

const createArrayMask = (image, values, band) => ee.Image(
    values.map(function (value) {
        return image.select(band).eq(value)
    })
).toArray()

const createProbabilityArray = (image, values) => ee.ImageCollection(
    values.map(function (value) {
        return image
            .select(
                ee.String('probability_').cat(ee.Number(value).format())
            )
            .rename('probability')
    })
).toBands().toArray()

const findValuesWithProbabilities = image => image
    .bandNames()
    .map(function (bandName) {
        return ee.String(bandName)
            .match('^probability_\\d*$')
            .slice(0, 1)
    })
    .flatten()
    .map(function (bandName) {
        const valueString = ee.String(bandName)
            .replace('probability_(\\d*)', '$1')
        return ee.Number.parse(valueString)
    })
    .sort()

module.exports = createClassChange
<commit_msg>Stopped masking class change confidence band, when there wasn't a transition.<commit_after>const ee = require('sepal/ee')
const {map, of, zip} = require('rxjs')
const imageFactory = require('sepal/ee/imageFactory')
const _ = require('lodash')

const createClassChange =
    ({
        model: {
            fromImage,
            toImage,
            options: {
                minConfidence = 0
            }
        }
    },
    {selection: selectedBands} = {selection: []}
    ) => {
        return {
            getImage$() {
                return zip(
                    imageFactory(fromImage).getImage$(),
                    imageFactory(toImage).getImage$(),
                ).pipe(
                    map(([fromEEImage, toEEImage]) => {
                        const image = calculateClassChange({
                            fromEEImage,
                            fromValues: fromImage.legendEntries.map(({value}) => value).sort(),
                            fromBand: fromImage.band,
                            toEEImage,
                            toValues: toImage.legendEntries.map(({value}) => value).sort(),
                            toBand: toImage.band,
                            minConfidence
                        })

                        return selectedBands.length
                            ? image.select(_.uniq(selectedBands))
                            : image
                    })
                )
            },
            getBands$() {
                const hasConfidence = () => {
                    const fromEntries = fromImage.legendEntries
                        .map(({value, label}) => ({value, label}))
                    const toEntries = toImage.legendEntries
                        .map(({value, label}) => ({value, label}))
                    if (!_.isEqual(new Set(fromEntries), new Set(toEntries))) {
                        return false
                    } else {
                        const fromBands = Object.keys(fromImage.bands)
                        const toBands = Object.keys(toImage.bands)
                        const probabilityBands = fromEntries.map(({value}) => `probability_${value}`)
                        return probabilityBands.every(band => fromBands.includes(band))
                            && probabilityBands.every(band => toBands.includes(band))
                    }
                }

                return of([
                    ['transition'],
                    hasConfidence() ? ['confidence'] : []
                ].flat())
            },
            getGeometry$() {
                return imageFactory(fromImage).getGeometry$()
            }
        }
    }

const calculateClassChange = ({
    fromEEImage,
    fromValues,
    fromBand,
    toEEImage,
    toValues,
    toBand,
    minConfidence
}) => {
    const fromValue = fromEEImage.select(fromBand)
    const toValue = toEEImage.select(fromBand)

    const fromValuesWithProbabilities = findValuesWithProbabilities(fromEEImage)
    const toValuesWithProbabilities = findValuesWithProbabilities(toEEImage)

    const fromProbabilityArray = createProbabilityArray(fromEEImage, fromValuesWithProbabilities)
    const toProbabilityArray = createProbabilityArray(toEEImage, toValuesWithProbabilities)

    const maxNumberOfValues = fromValuesWithProbabilities.size().max(toValuesWithProbabilities.size())

    const fromProbability = getProbability(fromValue, fromProbabilityArray, fromValuesWithProbabilities, maxNumberOfValues)
    const toProbability = getProbability(toValue, toProbabilityArray, toValuesWithProbabilities, maxNumberOfValues)

    const fromInToProbability = getProbability(fromValue, toProbabilityArray, toValuesWithProbabilities, maxNumberOfValues)
    const toInFromProbability = getProbability(toValue, fromProbabilityArray, fromValuesWithProbabilities, maxNumberOfValues)

    const toCertainty = toProbability.subtract(fromInToProbability)
    const fromCertainty = fromProbability.subtract(toInFromProbability)
    const confidence = ee.ImageCollection([toCertainty, fromCertainty])
        .mean()
        .rename('confidence')

    const mostProbableValue = toValue
        .where(toProbability.gt(fromProbability), toValue)
        .where(toProbability.lte(fromProbability), fromValue)

    const fromValueAdjusted = fromValue
        .where(confidence.lt(minConfidence), mostProbableValue)
    const toValueAdjusted = toValue
        .where(confidence.lt(minConfidence), mostProbableValue)

    const fromIndex = valueIndex(fromValueAdjusted, fromValues, fromBand)
    const toIndex = valueIndex(toValueAdjusted, toValues, toBand)

    const transition = fromIndex.multiply(toValues.length).add(toIndex).add(1)
        .rename('transition')

    return transition
        .addBands(confidence)
        .clip(fromEEImage.geometry())

}

const getProbability = (value, probabilityArray, valuesWithProbabilities, maxNumberOfValues) => {
    const probability = probabilityArray
        .arrayPad([maxNumberOfValues], -1)
        .arrayMask(
            ee.Image(ee.Array(valuesWithProbabilities))
                .arrayPad([maxNumberOfValues], -1)
                .eq(value)
        )
    return probability
        .updateMask(probability.arrayLength(0))
        .arrayGet([0])
}

const valueIndex = (value, values, band) => {
    const arrayMask = createArrayMask(value, values, band)
    const indexes = ee.Image(ee.Array(ee.List.sequence(0, ee.List(values).size().subtract(1))))
    const index = indexes
        .arrayMask(arrayMask)
    return index
        .updateMask(index.arrayLength(0))
        .arrayGet([0])
}

const createArrayMask = (image, values, band) => ee.Image(
    values.map(function (value) {
        return image.select(band).eq(value)
    })
).toArray()

const createProbabilityArray = (image, values) => ee.ImageCollection(
    values.map(function (value) {
        return image
            .select(
                ee.String('probability_').cat(ee.Number(value).format())
            )
            .rename('probability')
    })
).toBands().toArray()

const findValuesWithProbabilities = image => image
    .bandNames()
    .map(function (bandName) {
        return ee.String(bandName)
            .match('^probability_\\d*$')
            .slice(0, 1)
    })
    .flatten()
    .map(function (bandName) {
        const valueString = ee.String(bandName)
            .replace('probability_(\\d*)', '$1')
        return ee.Number.parse(valueString)
    })
    .sort()

module.exports = createClassChange
<|endoftext|>


<commit_before>/* editorview Plugin
 * Depends:
 *	ui.core.js
 * 	ui.view.js
 *

 Author
 Sacha Zyto (sacha@csail.mit.edu)

 License
 Copyright (c) 2010 Massachusetts Institute of Technology.
 MIT License (cf. MIT-LICENSE.txt or http://www.opensource.org/licenses/mit-license.php)
*/

(function($) {
    var V_OBJ = $.extend({},$.ui.view.prototype,{
	    _create: function() {
		$.ui.view.prototype._create.call(this);
		var self = this;
		var O		= self.options;
		self._allowStaffOnly = O.allowStaffOnly;
		self._allowAnonymous = O.allowAnonymous;
		$.mods.declare({
			editorview1: {js: [], css: ["/content/modules/dev/ui.editorview1.css"]},
			    });
		$.mods.ready("editorview1", function(){});
	    },
	    _defaultHandler: function(evt){
		var self		= this;
		var model		= self._model;
		var me			= $.concierge.get_component("get_userinfo")();
		var guest_msg	= "You need to register  or  login in order to post a reply...";
		switch (evt.type){
		case "new_thread":
		    if (me.guest == 1){
			$.I("You need to register  or  login in order to write annotations...", true, 10000);
			return;
		    }
		    //TMP FIX: only allow one current editor
		    if (self.element.children().length){
			$.I("Only one editor at a time is allowed for now...");
			return;
		    }
		    //TODO: delete previous draft if empty
		    //TODO: if existting draft, sync its content w/ its model
		    //now create new draft:
		    var id_item		= (new Date()).getTime();
		    var draft		= {};
		    draft[id_item]		= id_item;
		    var drafts	        = {};
		    drafts[id_item]		= draft;
		    self._doEdit		= false;
		    self._inReplyTo		= 0 ;
		    self._selection		= evt.value.selection;
		    self._sel		= null;
		    self._note		= null;
		    model.add("draft", drafts);
		    self._render(id_item);
		    break;
		case "reply_thread":
		    if (me.guest == 1){
			$.I("You need to register  or  login in order to write annotations...", true, 10000);
			return;
		    }
		    //TMP FIX: only allow one current editor
		    if (self.element.children().length){
			$.I("Only one editor at a time is allowed for now...");
			return;
		    }
		    var id_item		= (new Date()).getTime();
		    var draft		= {};
		    draft[id_item]		= id_item;
		    var drafts	        = {};
		    drafts[id_item]		= draft;
		    self._doEdit		= false;
		    self._inReplyTo		= evt.value;
		    self._selection		= null;
		    self._sel		= null;
		    self._note		= model.o.comment[evt.value];
		    model.add("draft", drafts);
		    self._render(id_item);
		    break;
		case "edit_thread":
		    //TMP FIX: only allow one current editor
		    if (self.element.children().length){
			$.I("Only one editor at a time is allowed for now...");
			return;
		    }
		    var id_item		= (new Date()).getTime();
		    var draft		= {};
		    draft[id_item]		= id_item;
		    var drafts	        = {};
		    drafts[id_item]		= draft;
		    self._doEdit		= true;
		    self._inReplyTo		= 0 ;
		    self._selection		= null;
		    self._sel		= null;
		    self._note		= model.o.comment[evt.value];
		    model.add("draft", drafts);
		    self._render(id_item);
		    break;
		}
	    },
	    _render: function(id_item){
		var self		= this;
		var model		= self._model;
		self.element.trigger("restore");
		//Various ways to create a selection
		if (self._selection){ //editor connected to a location
		    self._sel = self._selection.clone();
		}
		else if (self._inReplyTo){ //

		}

		//TODO: maybe other case to see if we should create selection from draft

		//Now construct the editor.
		var answerplease_opt = " ";
		if(self._doEdit && self._note.ID in model.o.mark){
		    var mark = model.o.mark[self._note.ID];
		    if (mark.answerplease == 1){
			answerplease_opt = " checked='checked' ";
		    }
		}
		var f_cleanup = function(){
		    self.element.trigger("before_cleanup", true);
		    self.element.trigger("minimize");
		    self.element.empty();
		    model.remove("draft", id_item);
		    if (self._sel){
			self._sel.remove();
		    }
		}
		var staffoption	= self._allowStaffOnly ? "
<input type='radio' name='vis_"+id_item+"' value='2'/>	Instructors and TAs
" : " ";

		var signoption	= self._allowAnonymous ? "<input type='checkbox' id='checkbox_sign' value='anonymous'/>Anonymous": " ";
		var questionoption = self._doEdit ? " " : "<input type='checkbox' value='question'/>Reply Requested ";
		var checkbox_options = "
"+questionoption+signoption+"
";
		var header	= self._inReplyTo ? "Re: "+$.E($.ellipsis(self._note.body, 20)) : "New note...";
		//		var body	= self._doEdit ? self._note.body : "";
		var contents = $([
				  "

",
				  header,
				  "
<textarea/>

 <input type='radio' checked='checked' name='vis_",
				  id_item,
				  "' value='3' />	The entire class
", staffoption,
				  "
<input type='radio' name='vis_"+id_item+"' value='1'/>	Myself only

	"+checkbox_options+"<button action='save' >Save</button><button action='discard' >Cancel</button>

"].join(""));
		self.element.append(contents);
		$("a[role='button']", self.element).click(f_cleanup).hover(function(e){$(this).addClass('ui-state-hover').removeClass('ui-view-semiopaque');},function(e){$(this).removeClass('ui-state-hover').addClass('ui-view-semiopaque');} );
		var $textarea = $("textarea", self.element).keypress(function(e){
			if(e.keyCode == 27 && this.value.length==0){
			    f_cleanup();
			}
		    }).width(self.element.width()-15);
		$textarea.height($textarea.height() + self.element.height() - $("div.notebox", self.element).height()-30);
		var f_sel = function(evt, ui){
		    $.D("sel has moved to", self._sel.width(), "x",  self._sel.height(), "+" ,  self._sel.css("left"), "+", self._sel.css("top"));
		}

		var f_discard = function(evt){
		    f_cleanup();
		};
		var f_on_save = function(payload){
		    model.add("comment", payload["comments"]);
		    model.add("threadmark", payload["threadmarks"]);
		    //important to add location even when edit or reply since it can change styling (if adding private comment etc...)
		    if ("locations" in payload){
			model.add("location", payload["locations"]);
		    }
		    else{
			var id_comment; for (id_comment in payload["comments"]){break;}
			id_loc = model.o.comment[id_comment]["ID_location"];
			if (id_loc in model.o.location){
			    var locs = {};
			    locs[id_loc] = model.o.location[id_loc];
			    model.add("location", locs);
			}
		    }
		    f_cleanup();
		};
		var f_save = function(evt){
		    var msg = {
			type: $("input[name=vis_"+id_item+"]:checked", self.element)[0].value,
			body:  $("textarea", self.element)[0].value,
			signed: self._allowAnonymous ? $("input[value=anonymous]:not(:checked)", self.element).length : 1,
			marks: {}
		    };
		    if ($("input[value=question]:checked", self.element).length){
			msg.marks.question =true;
		    }
		    var component_name;
		    if (!(self._note)){ //new note, local or global
			var s_inv = 	   100*$.concierge.get_constant("RESOLUTION_COORDINATES") / ($.concierge.get_constant("res")*$.concierge.get_state("scale")+0.0);
			var file = model.o.file[self._file];
			var fudge = (file.rotation==90 || file.rotation==270 ? file.h : file.w)/612.0;
			s_inv = s_inv/fudge;
			msg.id_ensemble = model.o.file[self._file].ID_ensemble;
			msg.top = self._sel ? s_inv*parseInt(self._sel.css("top")):0;
			msg.left= self._sel ? s_inv*parseInt(self._sel.css("left")):0;
			msg.w =  self._sel ? s_inv*self._sel.width():0;
			msg.h =  self._sel ? s_inv*self._sel.height():0;
			msg.x0= 0;
			msg.y0= 0;
			msg.page= self._sel ? self._sel.parent().attr("page"):0;
			msg.id_source=self._file;
			component_name =  "note_creator";
		    }
		    else{ //reply or edit
			msg.id_location = self._note.ID_location;
			msg.id_ensemble = model.o.location[msg.id_location].id_ensemble;
			if  (self._doEdit){
			    msg.id_comment = self._note.ID;
			    component_name =  "note_editor";
			}
			else{
			    msg.id_parent = self._note.ID;
			    component_name =  "note_creator";
			}
		    }
		    $.concierge.get_component(component_name)(msg, f_on_save);
		};
		$("button[action=save]",self.element).click(f_save);
		$("button[action=discard]",self.element).click(f_discard);
		if (self._sel){
		    var p = self._selection.parent();
		    self._sel.addClass("ui-drawable-selection").removeClass("ui-drawable-helper").appendTo(p).draggable({drag: f_sel, containment: 'parent' });
		    //animate transition so user understands that the editor is connected to the selection
		    self._sel.effect("transfer",{to: self.element} , 500);

		    //var y0 = parseInt(self._sel.css("top"))+self._sel.height();
		    //		    self.element.addClass("floating-editor").mousedown(function(evt){evt.stopPropagation()}).css({"top":y0+"px", "left": self._sel.css("left")});
		}
		self.element.addClass("editor");

		//if editing: fill in w/ exising values.
		if (self._doEdit){
		    $("textarea", self.element)[0].value = self._note.body;
		    $("input[name=vis_"+id_item+"]:checked", self.element).removeAttr("checked");
		    $("input[name=vis_"+id_item+"][value="+self._note.type+"]", self.element).attr("checked", "checked");
		    if (self._note.signed){
			$("input[value=anonymous]", self.element).removeAttr("checked");
		    }
		    else{
			$("input[value=anonymous]", self.element).attr("checked", "checked");
		    }
		}
		$("textarea", self.element).focus();
	    },
	    set_model: function(model){
		var self=this;
		self._model =  model;
		var id_source = $.concierge.get_state("file");
		self._file =  id_source ;
		// add this to be notified of model events:
		//model.register($.ui.view.prototype.get_adapter.call(this),  {YOUR_EVENT1: null});
	    },
	    update: function(action, payload, items_fieldname){
	    }
	});

    $.widget("ui.editorview",V_OBJ );
    $.ui.editorview.prototype.options = {
	listens: {
	    new_thread: null,
	    reply_thread: null,
	    edit_thread: null,
	},
	id_source: null,
	note: null,
	doEdit: false,
	selection: null,
	model: null,
	allowAnonymous: false,
	allowStaffOnly: false
    };
})(jQuery);
<commit_msg>added id for label to be clickable<commit_after>/* editorview Plugin
 * Depends:
 *	ui.core.js
 * 	ui.view.js
 *

 Author
 Sacha Zyto (sacha@csail.mit.edu)

 License
 Copyright (c) 2010 Massachusetts Institute of Technology.
 MIT License (cf. MIT-LICENSE.txt or http://www.opensource.org/licenses/mit-license.php)
*/

(function($) {
    var V_OBJ = $.extend({},$.ui.view.prototype,{
	    _create: function() {
		$.ui.view.prototype._create.call(this);
		var self = this;
		var O		= self.options;
		self._allowStaffOnly = O.allowStaffOnly;
		self._allowAnonymous = O.allowAnonymous;
		$.mods.declare({
			editorview1: {js: [], css: ["/content/modules/dev/ui.editorview1.css"]},
			    });
		$.mods.ready("editorview1", function(){});
	    },
	    _defaultHandler: function(evt){
		var self		= this;
		var model		= self._model;
		var me			= $.concierge.get_component("get_userinfo")();
		var guest_msg	= "You need to register  or  login in order to post a reply...";
		switch (evt.type){
		case "new_thread":
		    if (me.guest == 1){
			$.I("You need to register  or  login in order to write annotations...", true, 10000);
			return;
		    }
		    //TMP FIX: only allow one current editor
		    if (self.element.children().length){
			$.I("Only one editor at a time is allowed for now...");
			return;
		    }
		    //TODO: delete previous draft if empty
		    //TODO: if existting draft, sync its content w/ its model
		    //now create new draft:
		    var id_item		= (new Date()).getTime();
		    var draft		= {};
		    draft[id_item]		= id_item;
		    var drafts	        = {};
		    drafts[id_item]		= draft;
		    self._doEdit		= false;
		    self._inReplyTo		= 0 ;
		    self._selection		= evt.value.selection;
		    self._sel		= null;
		    self._note		= null;
		    model.add("draft", drafts);
		    self._render(id_item);
		    break;
		case "reply_thread":
		    if (me.guest == 1){
			$.I("You need to register  or  login in order to write annotations...", true, 10000);
			return;
		    }
		    //TMP FIX: only allow one current editor
		    if (self.element.children().length){
			$.I("Only one editor at a time is allowed for now...");
			return;
		    }
		    var id_item		= (new Date()).getTime();
		    var draft		= {};
		    draft[id_item]		= id_item;
		    var drafts	        = {};
		    drafts[id_item]		= draft;
		    self._doEdit		= false;
		    self._inReplyTo		= evt.value;
		    self._selection		= null;
		    self._sel		= null;
		    self._note		= model.o.comment[evt.value];
		    model.add("draft", drafts);
		    self._render(id_item);
		    break;
		case "edit_thread":
		    //TMP FIX: only allow one current editor
		    if (self.element.children().length){
			$.I("Only one editor at a time is allowed for now...");
			return;
		    }
		    var id_item		= (new Date()).getTime();
		    var draft		= {};
		    draft[id_item]		= id_item;
		    var drafts	        = {};
		    drafts[id_item]		= draft;
		    self._doEdit		= true;
		    self._inReplyTo		= 0 ;
		    self._selection		= null;
		    self._sel		= null;
		    self._note		= model.o.comment[evt.value];
		    model.add("draft", drafts);
		    self._render(id_item);
		    break;
		}
	    },
	    _render: function(id_item){
		var self		= this;
		var model		= self._model;
		self.element.trigger("restore");
		//Various ways to create a selection
		if (self._selection){ //editor connected to a location
		    self._sel = self._selection.clone();
		}
		else if (self._inReplyTo){ //

		}

		//TODO: maybe other case to see if we should create selection from draft

		//Now construct the editor.
		var answerplease_opt = " ";
		if(self._doEdit && self._note.ID in model.o.mark){
		    var mark = model.o.mark[self._note.ID];
		    if (mark.answerplease == 1){
			answerplease_opt = " checked='checked' ";
		    }
		}
		var f_cleanup = function(){
		    self.element.trigger("before_cleanup", true);
		    self.element.trigger("minimize");
		    self.element.empty();
		    model.remove("draft", id_item);
		    if (self._sel){
			self._sel.remove();
		    }
		}
		var staffoption	= self._allowStaffOnly ? "
<input type='radio' name='vis_"+id_item+"' value='2'/>	Instructors and TAs
" : " ";

		var signoption	= self._allowAnonymous ? "<input type='checkbox' id='checkbox_sign' value='anonymous'/>Anonymous": " ";
		var questionoption = self._doEdit ? " " : "<input type='checkbox' id='checkbox_question' value='question'/>Reply Requested ";
		var checkbox_options = "
"+questionoption+signoption+"
";
		var header	= self._inReplyTo ? "Re: "+$.E($.ellipsis(self._note.body, 20)) : "New note...";
		//		var body	= self._doEdit ? self._note.body : "";
		var contents = $([
				  "

",
				  header,
				  "
<textarea/>

 <input type='radio' checked='checked' name='vis_",
				  id_item,
				  "' value='3' />	The entire class
", staffoption,
				  "
<input type='radio' name='vis_"+id_item+"' value='1'/>	Myself only

	"+checkbox_options+"<button action='save' >Save</button><button action='discard' >Cancel</button>

"].join(""));
		self.element.append(contents);
		$("a[role='button']", self.element).click(f_cleanup).hover(function(e){$(this).addClass('ui-state-hover').removeClass('ui-view-semiopaque');},function(e){$(this).removeClass('ui-state-hover').addClass('ui-view-semiopaque');} );
		var $textarea = $("textarea", self.element).keypress(function(e){
			if(e.keyCode == 27 && this.value.length==0){
			    f_cleanup();
			}
		    }).width(self.element.width()-15);
		$textarea.height($textarea.height() + self.element.height() - $("div.notebox", self.element).height()-30);
		var f_sel = function(evt, ui){
		    $.D("sel has moved to", self._sel.width(), "x",  self._sel.height(), "+" ,  self._sel.css("left"), "+", self._sel.css("top"));
		}

		var f_discard = function(evt){
		    f_cleanup();
		};
		var f_on_save = function(payload){
		    model.add("comment", payload["comments"]);
		    model.add("threadmark", payload["threadmarks"]);
		    //important to add location even when edit or reply since it can change styling (if adding private comment etc...)
		    if ("locations" in payload){
			model.add("location", payload["locations"]);
		    }
		    else{
			var id_comment; for (id_comment in payload["comments"]){break;}
			id_loc = model.o.comment[id_comment]["ID_location"];
			if (id_loc in model.o.location){
			    var locs = {};
			    locs[id_loc] = model.o.location[id_loc];
			    model.add("location", locs);
			}
		    }
		    f_cleanup();
		};
		var f_save = function(evt){
		    var msg = {
			type: $("input[name=vis_"+id_item+"]:checked", self.element)[0].value,
			body:  $("textarea", self.element)[0].value,
			signed: self._allowAnonymous ? $("input[value=anonymous]:not(:checked)", self.element).length : 1,
			marks: {}
		    };
		    if ($("input[value=question]:checked", self.element).length){
			msg.marks.question =true;
		    }
		    var component_name;
		    if (!(self._note)){ //new note, local or global
			var s_inv = 	   100*$.concierge.get_constant("RESOLUTION_COORDINATES") / ($.concierge.get_constant("res")*$.concierge.get_state("scale")+0.0);
			var file = model.o.file[self._file];
			var fudge = (file.rotation==90 || file.rotation==270 ? file.h : file.w)/612.0;
			s_inv = s_inv/fudge;
			msg.id_ensemble = model.o.file[self._file].ID_ensemble;
			msg.top = self._sel ? s_inv*parseInt(self._sel.css("top")):0;
			msg.left= self._sel ? s_inv*parseInt(self._sel.css("left")):0;
			msg.w =  self._sel ? s_inv*self._sel.width():0;
			msg.h =  self._sel ? s_inv*self._sel.height():0;
			msg.x0= 0;
			msg.y0= 0;
			msg.page= self._sel ? self._sel.parent().attr("page"):0;
			msg.id_source=self._file;
			component_name =  "note_creator";
		    }
		    else{ //reply or edit
			msg.id_location = self._note.ID_location;
			msg.id_ensemble = model.o.location[msg.id_location].id_ensemble;
			if  (self._doEdit){
			    msg.id_comment = self._note.ID;
			    component_name =  "note_editor";
			}
			else{
			    msg.id_parent = self._note.ID;
			    component_name =  "note_creator";
			}
		    }
		    $.concierge.get_component(component_name)(msg, f_on_save);
		};
		$("button[action=save]",self.element).click(f_save);
		$("button[action=discard]",self.element).click(f_discard);
		if (self._sel){
		    var p = self._selection.parent();
		    self._sel.addClass("ui-drawable-selection").removeClass("ui-drawable-helper").appendTo(p).draggable({drag: f_sel, containment: 'parent' });
		    //animate transition so user understands that the editor is connected to the selection
		    self._sel.effect("transfer",{to: self.element} , 500);

		    //var y0 = parseInt(self._sel.css("top"))+self._sel.height();
		    //		    self.element.addClass("floating-editor").mousedown(function(evt){evt.stopPropagation()}).css({"top":y0+"px", "left": self._sel.css("left")});
		}
		self.element.addClass("editor");

		//if editing: fill in w/ exising values.
		if (self._doEdit){
		    $("textarea", self.element)[0].value = self._note.body;
		    $("input[name=vis_"+id_item+"]:checked", self.element).removeAttr("checked");
		    $("input[name=vis_"+id_item+"][value="+self._note.type+"]", self.element).attr("checked", "checked");
		    if (self._note.signed){
			$("input[value=anonymous]", self.element).removeAttr("checked");
		    }
		    else{
			$("input[value=anonymous]", self.element).attr("checked", "checked");
		    }
		}
		$("textarea", self.element).focus();
	    },
	    set_model: function(model){
		var self=this;
		self._model =  model;
		var id_source = $.concierge.get_state("file");
		self._file =  id_source ;
		// add this to be notified of model events:
		//model.register($.ui.view.prototype.get_adapter.call(this),  {YOUR_EVENT1: null});
	    },
	    update: function(action, payload, items_fieldname){
	    }
	});

    $.widget("ui.editorview",V_OBJ );
    $.ui.editorview.prototype.options = {
	listens: {
	    new_thread: null,
	    reply_thread: null,
	    edit_thread: null,
	},
	id_source: null,
	note: null,
	doEdit: false,
	selection: null,
	model: null,
	allowAnonymous: false,
	allowStaffOnly: false
    };
})(jQuery);
<|endoftext|>


<commit_before>(function(){
"use strict";

glow.data = {
    count: {},
    map: {},
    sector: {}
};

var ROOT = "data/json/";
var adjustOffset = 248;
var targetHeight = 1650;

// Load the next file of json data before timeout seconds have elapsed.
glow.fetchCount = function(timeout) {
    // We don't request data.sector until the page flips, but
    // but we want to be ready with the right url.
    var sector = glow.data.count.next.next.replace('count', 'arc');
    getData(glow.data.count.next.next, timeout, function(r) {
        glow.data.count.next = r;
        glow.data.sector.next = sector;
    });
};

// Load the next file of json data before timeout seconds have elapsed.
glow.fetchMap = function(timeout) {
    getData(glow.data.map.next.next, timeout, function(r) {
        glow.data.map.next = r;
    });
};

// $.getJSON with an error parameter.
var getJSON = function(url, success, error) {
    $.ajax({url: ROOT + url, dataType: 'json',
            success: success, error: error});
};

// Reload the page if we couldn't fetch any data after a few retries. This
// drops us back into the loading screen with error messaging.
var fetchFailure = function() {
    window.location.reload();
};

// We have timeout seconds to pull the next chunk of data.
// Start by waiting timeout/2 seconds before the first attempt.
// If that fails, retry every 5 seconds until we run out of time.
var getData = function(url, timeout, success) {
    var error = setTimeout(fetchFailure, timeout * 1000),
        remaining = timeout / 2;

    var success_ = function(data, textStatus, xhr) {
        dbg('Success', url);
        clearTimeout(error);
        success(data, textStatus, xhr);
    };

    var fetch = function(timeout) {
        setTimeout(function() {
            getJSON(url, success_, function() {
                dbg('Error, retrying', url);
                if (!glow.stop) {
                    remaining -= 5;
                    fetch(5);
                }
            });
        }, timeout * 1000);
    };
    fetch(remaining);
};

glow.toggleView = function() {
    if (glow.view == "map") {
        window.location.hash = "arc";
        glow.view = "chart";
        $("#sunburst").show();
        if (!glow.sector) initSunburst();
    } else {
        window.location.hash = "";
        glow.view = "map";
        $("#sunburst").hide();
    }
    sizePageElements();
    $("body").toggleClass("view-sector", glow.view == "chart");
}

function sizePageElements() {
    var $geo = $("#geo");
    $("#sunburst, #geo").css("height", $("body").height() - adjustOffset);
    $("#chart")[0].width = $("#sunburst").width() - 300;
    $("#chart")[0].height = $("#sunburst").height();
    if (glow.sector) glow.sector.redraw();
    if ($geo.width() / $geo.height() > 2) {
        glow.map.scale = $geo.height() / targetHeight;
    } else {
        glow.map.scale = $geo.width() / 3600;
    }
    $("#mapdata, #pings").css({
        "top": $geo.height() - targetHeight * glow.map.scale,
        "left": ($geo.width() - 3600 * glow.map.scale) / 2
    });
    $("#mapdata").css({
        "-moz-transform": "scale(" + glow.map.scale + ")",
        "-webkit-transform": "scale(" + glow.map.scale + ")",
        "-ms-transform": "scale(" + glow.map.scale + ")",
        "-o-transform": "scale(" + glow.map.scale + ")"
    });
    if ($("#geo").height)
    $("#pings").css({
        width: $mc.width() + "px",
        height: $mc.height() + "px"
    });
    $("#pings")[0].width=$mc.width();
    $("#pings")[0].height=$mc.height();
}
$(window).resize(vast.debounce(sizePageElements, 500, this));

function initSunburst() {
  var loader = loading();
  $.getJSON(ROOT + glow.data.sector.next, function(r) {
      dbg('sector data loaded');
      processGeo(r.data, function(decodedData) {
          dbg('processing done');
          clearInterval(loader);
          glow.sector = $("#chart").arcChart({data: decodedData});
          $("#crumb").click(glow.sector.zoomOut);
      });
  });
}

function loading() {
    var c = $('#chart'),
        ctx = c[0].getContext('2d'),
        wedges = 8,
        cnt = 0;
    return setInterval(function(){
        ctx.save();
        ctx.fillStyle = 'rgba(227, 159, 28, .1)';
        ctx.translate(c[0].width / 2, c[0].height / 2);
        ctx.rotate(-Math.PI/16);
        ctx.clearRect(-70, -70, 140, 140);
        for (var i = 0; i < 8; i++) {
            ctx.rotate(Math.PI / 4);
            if (i == cnt) {
                ctx.save();
                ctx.shadowColor = 'rgba(227, 159, 28, .8)';
                ctx.shadowBlur = 5;
                ctx.fillStyle = 'rgb(227, 159, 28)';
                wedge();
                ctx.restore();
            } else {
                wedge();
            }
        }
        function wedge() {
            ctx.beginPath();
            ctx.arc(0, 0, 60, 0, Math.PI / 8, 0);
            ctx.arc(0, 0, 20, Math.PI / 8, 0, 1);
            ctx.lineTo(60, 0);
            ctx.stroke();
            ctx.fill();
        }
        cnt = ++cnt % 8;
        ctx.restore();
    }, 90);
}

function processGeo(_data, cb) {
    $.getScript("locale/" + glow.locale + "/countries.js", function() {
        dbg('loaded countries');
        $.getScript("media/regions.js", function() {
            dbg('loaded regions');
            cb.call(null, [null, _data[1], decodeGeo(_data[2], 1)]);
        });
    });
}

var _continents = {
    "EU": "Europe",
    "NA": "North America",
    "AS": "Asia",
    "SA": "South America",
    "AF": "Africa",
    "OC": "Oceania"
};
function decodeGeo(data, depth, parent) {
    if (!data) return;
    var i, name, row,
        ret = [], o;
    for (i=0; i < data.length; i++) {
        row = data[i];
        name = row[0] || "Other";
        switch (depth) {
            case 1:
                name = gettext(_continents[row[0]]) || name;
                break;
            case 2:
                name = _countries[row[0]] || name;
                break;
            case 3:
                if (_regions[parent]) {
                    name = _regions[parent][row[0]] || name
                }
                name = _countries[name] || name;
                break;
            case 4:
                name = _countries[name] || name;
        }
        ret.push([name, row[1], decodeGeo(row[2], depth+1, row[0]), row[0]]);
    }
    return ret;
}

$("#chart").bind("update", function(e, list, current) {
    var $ul = $("#rankedlist").empty(),
        $crumb = $("#crumb").empty(),
        i;

    if (current) {
        $crumb.append(current[2][0]);
    }

    $ul.undelegate().delegate("li a", "click", function(e) {
        e.preventDefault();
        var $li = $(this).closest("li");
        glow.sector.zoomIn($li.index());
    })
    for (i=0; i<list.length; i++) {
        $ul.append("
" + list[i][2][0] + " " + numberfmt(list[i][2][1]) + "
");
    }

});

glow.toggleFullscreen = function() {
    var $body = $("body");
    $body.toggleClass("fullscreen");
    if ($body.hasClass("fullscreen")) {
        adjustOffset = 0;
        targetHeight = 1800;
    } else {
        adjustOffset = 248;
        targetHeight = 1650;
    }
    setTimeout(sizePageElements, 0);
}

glow.init = function() {
    glow.data.sector.next = glow.time + "/arc.json";
    $.getJSON(ROOT + glow.time + "/count.json", function(r) {
        glow.data.count.next = r;
        glow.count.playNext();
        glow.bar.playNext();

        loadMap(function() {
            $.getJSON(ROOT + glow.time + "/map.json", function(r) {
                glow.data.map.next = r;
                glow.map.playNext();
            });
        });
    });

    initCounter();
    initBars();
    initMap();
    sizePageElements();

    $(".menu").click(glow.toggleView);
    $("#logo").click(glow.toggleFullscreen);

    if (location.hash.slice(1, 4) == "arc") {
        glow.toggleView();
    } else if (location.hash.slice(1, 5) == "full") {
        glow.toggleFullscreen();
    }
};

var lastKey = null;
var toggled = false;
$(window).bind('keydown', function(e) {
    var num = null;
    if (e.keyCode >= 48 && e.keyCode <= 57) {
        num = e.keyCode - 48;
    } else if (e.keyCode >= 96 && e.keyCode <= 105) {
        num = e.keyCode - 96;
    } else {
        return;
    }

    if (lastKey === 0 && num === 0) {
        window.location.reload();
    } else if (lastKey == 1 && num == 1) {
        glow.toggleFullscreen();
    } else if (lastKey == 9 && num == 9) {
        if (toggled) {
            $("#logo")[0].src = "media/logo-large.png";
        } else {
            $("#logo")[0].src = "media/theeye.png";
        }
        toggled = !toggled;
    }

    console.log(num, lastKey);
    lastKey = num;
});

$(".show-about").click(function(e) {
    e.preventDefault();
    $("body").addClass("about");
    setTimeout(function() {
        $("body").one('click', function() {
            $("body").removeClass("about");
        });
    },100);
});

})();
<commit_msg>going to /#arc/NA/US/CA now loads properly. Need to add in-page push/popstate.<commit_after>(function(){
"use strict";

glow.data = {
    count: {},
    map: {},
    sector: {}
};

var ROOT = "data/json/";
var adjustOffset = 248;
var targetHeight = 1650;

// Load the next file of json data before timeout seconds have elapsed.
glow.fetchCount = function(timeout) {
    // We don't request data.sector until the page flips, but
    // but we want to be ready with the right url.
    var sector = glow.data.count.next.next.replace('count', 'arc');
    getData(glow.data.count.next.next, timeout, function(r) {
        glow.data.count.next = r;
        glow.data.sector.next = sector;
    });
};

// Load the next file of json data before timeout seconds have elapsed.
glow.fetchMap = function(timeout) {
    getData(glow.data.map.next.next, timeout, function(r) {
        glow.data.map.next = r;
    });
};

// $.getJSON with an error parameter.
var getJSON = function(url, success, error) {
    $.ajax({url: ROOT + url, dataType: 'json',
            success: success, error: error});
};

// Reload the page if we couldn't fetch any data after a few retries. This
// drops us back into the loading screen with error messaging.
var fetchFailure = function() {
    window.location.reload();
};

// We have timeout seconds to pull the next chunk of data.
// Start by waiting timeout/2 seconds before the first attempt.
// If that fails, retry every 5 seconds until we run out of time.
var getData = function(url, timeout, success) {
    var error = setTimeout(fetchFailure, timeout * 1000),
        remaining = timeout / 2;

    var success_ = function(data, textStatus, xhr) {
        dbg('Success', url);
        clearTimeout(error);
        success(data, textStatus, xhr);
    };

    var fetch = function(timeout) {
        setTimeout(function() {
            getJSON(url, success_, function() {
                dbg('Error, retrying', url);
                if (!glow.stop) {
                    remaining -= 5;
                    fetch(5);
                }
            });
        }, timeout * 1000);
    };
    fetch(remaining);
};

glow.toggleView = function() {
    if (glow.view == "map") {
        if (window.location.hash.slice(1,4) != "arc") {
            window.location.hash = "arc";
        }
        glow.view = "chart";
        $("#sunburst").show();
        if (!glow.sector) initSunburst();
    } else {
        window.location.hash = "";
        glow.view = "map";
        $("#sunburst").hide();
    }
    sizePageElements();
    $("body").toggleClass("view-sector", glow.view == "chart");
}

function sizePageElements() {
    var $geo = $("#geo");
    $("#sunburst, #geo").css("height", $("body").height() - adjustOffset);
    $("#chart")[0].width = $("#sunburst").width() - 300;
    $("#chart")[0].height = $("#sunburst").height();
    if (glow.sector) glow.sector.redraw();
    if ($geo.width() / $geo.height() > 2) {
        glow.map.scale = $geo.height() / targetHeight;
    } else {
        glow.map.scale = $geo.width() / 3600;
    }
    $("#mapdata, #pings").css({
        "top": $geo.height() - targetHeight * glow.map.scale,
        "left": ($geo.width() - 3600 * glow.map.scale) / 2
    });
    $("#mapdata").css({
        "-moz-transform": "scale(" + glow.map.scale + ")",
        "-webkit-transform": "scale(" + glow.map.scale + ")",
        "-ms-transform": "scale(" + glow.map.scale + ")",
        "-o-transform": "scale(" + glow.map.scale + ")"
    });
    if ($("#geo").height)
    $("#pings").css({
        width: $mc.width() + "px",
        height: $mc.height() + "px"
    });
    $("#pings")[0].width=$mc.width();
    $("#pings")[0].height=$mc.height();
}
$(window).resize(vast.debounce(sizePageElements, 500, this));

function initSunburst() {
  var loader = loading();
  $.getJSON(ROOT + glow.data.sector.next, function(r) {
      dbg('sector data loaded');
      processGeo(r.data, function(decodedData) {
          dbg('processing done');
          clearInterval(loader);
          glow.sector = $("#chart").arcChart({data: decodedData});
          $("#crumb").click(glow.sector.zoomOut);
          if (window.location.hash.slice(1, 4) == "arc") {
              glow.sector.zoomTo(window.location.hash.split("/").slice(1));
          }
      });
  });
}

function loading() {
    var c = $('#chart'),
        ctx = c[0].getContext('2d'),
        wedges = 8,
        cnt = 0;
    return setInterval(function(){
        ctx.save();
        ctx.fillStyle = 'rgba(227, 159, 28, .1)';
        ctx.translate(c[0].width / 2, c[0].height / 2);
        ctx.rotate(-Math.PI/16);
        ctx.clearRect(-70, -70, 140, 140);
        for (var i = 0; i < 8; i++) {
            ctx.rotate(Math.PI / 4);
            if (i == cnt) {
                ctx.save();
                ctx.shadowColor = 'rgba(227, 159, 28, .8)';
                ctx.shadowBlur = 5;
                ctx.fillStyle = 'rgb(227, 159, 28)';
                wedge();
                ctx.restore();
            } else {
                wedge();
            }
        }
        function wedge() {
            ctx.beginPath();
            ctx.arc(0, 0, 60, 0, Math.PI / 8, 0);
            ctx.arc(0, 0, 20, Math.PI / 8, 0, 1);
            ctx.lineTo(60, 0);
            ctx.stroke();
            ctx.fill();
        }
        cnt = ++cnt % 8;
        ctx.restore();
    }, 90);
}

function processGeo(_data, cb) {
    $.getScript("locale/" + glow.locale + "/countries.js", function() {
        dbg('loaded countries');
        $.getScript("media/regions.js", function() {
            dbg('loaded regions');
            cb.call(null, [null, _data[1], decodeGeo(_data[2], 1)]);
        });
    });
}

var _continents = {
    "EU": "Europe",
    "NA": "North America",
    "AS": "Asia",
    "SA": "South America",
    "AF": "Africa",
    "OC": "Oceania"
};
function decodeGeo(data, depth, parent) {
    if (!data) return;
    var i, name, row,
        ret = [], o;
    for (i=0; i < data.length; i++) {
        row = data[i];
        name = row[0] || "Other";
        switch (depth) {
            case 1:
                name = gettext(_continents[row[0]]) || name;
                break;
            case 2:
                name = _countries[row[0]] || name;
                break;
            case 3:
                if (_regions[parent]) {
                    name = _regions[parent][row[0]] || name
                }
                name = _countries[name] || name;
                break;
            case 4:
                name = _countries[name] || name;
        }
        ret.push([name, row[1], decodeGeo(row[2], depth+1, row[0]), row[0]]);
    }
    return ret;
}

$("#chart").bind("update", function(e, list, current) {
    var $ul = $("#rankedlist").empty(),
        $crumb = $("#crumb").empty(),
        i;

    if (current) {
        $crumb.append(current[2][0]);
    }

    $ul.undelegate().delegate("li a", "click", function(e) {
        e.preventDefault();
        var $li = $(this).closest("li");
        glow.sector.zoomIn($li.index());
    })
    for (i=0; i<list.length; i++) {
        $ul.append("
" + list[i][2][0] + " " + numberfmt(list[i][2][1]) + "
");
    }

});

glow.toggleFullscreen = function() {
    var $body = $("body");
    $body.toggleClass("fullscreen");
    if ($body.hasClass("fullscreen")) {
        adjustOffset = 0;
        targetHeight = 1800;
    } else {
        adjustOffset = 248;
        targetHeight = 1650;
    }
    setTimeout(sizePageElements, 0);
}

glow.init = function() {
    glow.data.sector.next = glow.time + "/arc.json";
    $.getJSON(ROOT + glow.time + "/count.json", function(r) {
        glow.data.count.next = r;
        glow.count.playNext();
        glow.bar.playNext();

        loadMap(function() {
            $.getJSON(ROOT + glow.time + "/map.json", function(r) {
                glow.data.map.next = r;
                glow.map.playNext();
            });
        });
    });

    initCounter();
    initBars();
    initMap();
    sizePageElements();

    $(".menu").click(glow.toggleView);
    $("#logo").click(glow.toggleFullscreen);

    if (location.hash.slice(1, 4) == "arc") {
        glow.toggleView();
    } else if (location.hash.slice(1, 5) == "full") {
        glow.toggleFullscreen();
    }
};

var lastKey = null;
var toggled = false;
$(window).bind('keydown', function(e) {
    var num = null;
    if (e.keyCode >= 48 && e.keyCode <= 57) {
        num = e.keyCode - 48;
    } else if (e.keyCode >= 96 && e.keyCode <= 105) {
        num = e.keyCode - 96;
    } else {
        return;
    }

    if (lastKey === 0 && num === 0) {
        window.location.reload();
    } else if (lastKey == 1 && num == 1) {
        glow.toggleFullscreen();
    } else if (lastKey == 9 && num == 9) {
        if (toggled) {
            $("#logo")[0].src = "media/logo-large.png";
        } else {
            $("#logo")[0].src = "media/theeye.png";
        }
        toggled = !toggled;
    }

    lastKey = num;
});

$(".show-about").click(function(e) {
    e.preventDefault();
    $("body").addClass("about");
    setTimeout(function() {
        $("body").one('click', function() {
            $("body").removeClass("about");
        });
    },100);
});

})();
<|endoftext|>


<commit_before>var WebSocketServer = require('websocket').server;
var fs = require('fs');
var url = require('url');
var qs = require('querystring');
var express = require('express');
var iniparser = require('iniparser');
var crypto = require('crypto');

var EventEmitter = require('events').EventEmitter;

console.log('Loading config');
var config = iniparser.parseSync('./config.ini');

// HTTP Server
var http = require(config.http.protocol);
var app = express();
var httpServer = http.createServer(app);
app.use(express.static(__dirname + config.filesystem.public_files));
app.set('views', __dirname + config.filesystem.view_files);
app.engine('html', require('ejs').renderFile);

// App Variables
var currentUsers = {};
var carddisplay = {
    cards: {},
    show: false
};
var currentUserstory = '';

// WebSocket Server
console.log('Creating WebSocket Server');
wsServer = new WebSocketServer({
    httpServer: httpServer,
    // You should not use autoAcceptConnections for production
    // applications, as it defeats all standard cross-origin protection
    // facilities built into the protocol and the browser.  You should
    // *always* verify the connection's origin and decide whether or not
    // to accept it.
    autoAcceptConnections: false
});

var pokerLoginListener = function(messageData) {
    var user,
        sha1sum,
        sendData;

    // For callbacks
    connection = this.connection;

    user = messageData.user;
    if (typeof user.id !== 'undefined') {
        currentUsers[user.id] = user;
        sendData = {
            type: 'login',
            user: user
        };
        connection.sendUTF(JSON.stringify(sendData));
        broadcastUsers();
    } else {
        // Create random id for user
        sha1sum = crypto.createHash('sha1');
        crypto.randomBytes(256, function(ex, buf) {
            if (ex) throw ex;
            sha1sum.update(buf);
            user.id = sha1sum.digest('hex');
            currentUsers[user.id] = user;
            sendData = {
                type: 'login',
                user: user
            };
            connection.sendUTF(JSON.stringify(sendData));
            broadcastUsers();
        });
    }
    this.user = user;
};

var getInitialDataListener = function(messageData) {
    this.connection.sendUTF(JSON.stringify(getUserUpdateList()));
    this.connection.sendUTF(JSON.stringify(getCardUpdateList()));
    this.connection.sendUTF(JSON.stringify(getUserstoryUpdate()));
};

var playCardListener = function(messageData) {
    // Allow only if cards are not already shown
    if (!carddisplay.show) {
        carddisplay.cards[messageData.userId] = messageData.cardValue
        broadcastCards();
    }
};

var PokerConnectionHandler = function() {};
PokerConnectionHandler.prototype = new EventEmitter();

PokerConnectionHandler.prototype.connection = null;

PokerConnectionHandler.prototype.setConnection = function(connection) {
    var me;
    me = this;
    this.connection = connection;
    this.connection.on('message', function(message) {
        me.onmessage.call(me, message);
    });

    connection.on('close', function(reasonCode, description) {
        me.onclose.call(me, reasonCode, description);
    });
};

PokerConnectionHandler.prototype.onclose = function(reasonCode, description) {
    console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.');
    if (typeof this.user != 'undefined') {
        currentUsers[this.user.id] = null;
        delete currentUsers[this.user.id];

        carddisplay[this.user.id] = null;
        delete carddisplay.cards[this.user.id];

        broadcastUsers();
        broadcastCards();
    }
};

PokerConnectionHandler.prototype.onmessage = function(message) {
    if (message.type === 'utf8') {
        //console.log('Received Message: ' + message.utf8Data);
        var messageData = JSON.parse(message.utf8Data);
        this.emit(messageData.type, messageData, this);
        switch(messageData.type) {
            case 'show-cards':
                var pushData = {
                    type: 'show-cards'
                };
                carddisplay.show = true;
                wsServer.broadcastUTF(JSON.stringify(pushData));
                break;

            case 'reset-cards':
                carddisplay = {
                    cards: {},
                    show: false
                };
                broadcastCards();
                break;

            case 'post-userstory':
                currentUserstory  = messageData.userstory;
                broadcastUserstory();
                break;

            case 'post-chat-message':
                chatMessage = {
                    type: 'new-chat-message',
                    text: messageData.text,
                    user: this.user
                };
                wsServer.broadcastUTF(JSON.stringify(chatMessage));
                break;

            case 'reset-room':
                currentUserstory = '';
                carddisplay = {
                    cards: {},
                    show: false
                };
                broadcastCards();
                broadcastUserstory();

                var pushData = {
                    type: 'reset-room'
                };
                wsServer.broadcastUTF(JSON.stringify(pushData));
                break;
        }
    }
    else if (message.type === 'binary') {
        console.log('Received Binary Message of ' + message.binaryData.length + ' bytes');
    }
};

wsServer.on('request', function(request) {
    var connectionHandler = new PokerConnectionHandler();
    connectionHandler.on('login', pokerLoginListener);
    connectionHandler.on('get-initial-data', getInitialDataListener);
    connectionHandler.on('play-card', playCardListener);

	connectionHandler.setConnection(request.accept());

    console.log((new Date()) + ' Connection accepted.');

});

app.get('/', function(req, res) {
    console.log(config.http);
	res.render(
        'index.html',
        {
            web: config.http,
            cards: config.cards
        }
    );
	res.end();
});

getUserUpdateList = function () {
	return {
    	type: 'userlist',
    	data: currentUsers
    };
};

broadcastUsers = function() {
	var pushData = getUserUpdateList();
    wsServer.broadcastUTF(JSON.stringify(pushData));
}

getCardUpdateList = function () {
	return {
    	type: 'carddisplay',
    	data: carddisplay
    };
};

broadcastCards = function() {
	var pushData = getCardUpdateList();
    wsServer.broadcastUTF(JSON.stringify(pushData));
};

getUserstoryUpdate = function() {
	return {
		type: 'userstory',
		userstory: currentUserstory
	};
}

broadcastUserstory = function() {
	var pushData = getUserstoryUpdate();
	wsServer.broadcastUTF(JSON.stringify(pushData));
};

httpServer.listen(config.http.port, function() {
	console.log('HTTP Server running with config:');
    console.log(config.http);
});<commit_msg>show-cards as listener<commit_after>var WebSocketServer = require('websocket').server;
var fs = require('fs');
var url = require('url');
var qs = require('querystring');
var express = require('express');
var iniparser = require('iniparser');
var crypto = require('crypto');

var EventEmitter = require('events').EventEmitter;

console.log('Loading config');
var config = iniparser.parseSync('./config.ini');

// HTTP Server
var http = require(config.http.protocol);
var app = express();
var httpServer = http.createServer(app);
app.use(express.static(__dirname + config.filesystem.public_files));
app.set('views', __dirname + config.filesystem.view_files);
app.engine('html', require('ejs').renderFile);

// App Variables
var currentUsers = {};
var carddisplay = {
    cards: {},
    show: false
};
var currentUserstory = '';

// WebSocket Server
console.log('Creating WebSocket Server');
wsServer = new WebSocketServer({
    httpServer: httpServer,
    // You should not use autoAcceptConnections for production
    // applications, as it defeats all standard cross-origin protection
    // facilities built into the protocol and the browser.  You should
    // *always* verify the connection's origin and decide whether or not
    // to accept it.
    autoAcceptConnections: false
});

var pokerLoginListener = function(messageData) {
    var user,
        sha1sum,
        sendData;

    // For callbacks
    connection = this.connection;

    user = messageData.user;
    if (typeof user.id !== 'undefined') {
        currentUsers[user.id] = user;
        sendData = {
            type: 'login',
            user: user
        };
        connection.sendUTF(JSON.stringify(sendData));
        broadcastUsers();
    } else {
        // Create random id for user
        sha1sum = crypto.createHash('sha1');
        crypto.randomBytes(256, function(ex, buf) {
            if (ex) throw ex;
            sha1sum.update(buf);
            user.id = sha1sum.digest('hex');
            currentUsers[user.id] = user;
            sendData = {
                type: 'login',
                user: user
            };
            connection.sendUTF(JSON.stringify(sendData));
            broadcastUsers();
        });
    }
    this.user = user;
};

var getInitialDataListener = function(messageData) {
    this.connection.sendUTF(JSON.stringify(getUserUpdateList()));
    this.connection.sendUTF(JSON.stringify(getCardUpdateList()));
    this.connection.sendUTF(JSON.stringify(getUserstoryUpdate()));
};

var playCardListener = function(messageData) {
    // Allow only if cards are not already shown
    if (!carddisplay.show) {
        carddisplay.cards[messageData.userId] = messageData.cardValue
        broadcastCards();
    }
};

var showCardsListener = function(messageData) {
    var pushData = {
        type: 'show-cards'
    };
    carddisplay.show = true;
    wsServer.broadcastUTF(JSON.stringify(pushData));
};

var PokerConnectionHandler = function() {};
PokerConnectionHandler.prototype = new EventEmitter();

PokerConnectionHandler.prototype.connection = null;

PokerConnectionHandler.prototype.setConnection = function(connection) {
    var me;
    me = this;
    this.connection = connection;
    this.connection.on('message', function(message) {
        me.onmessage.call(me, message);
    });

    connection.on('close', function(reasonCode, description) {
        me.onclose.call(me, reasonCode, description);
    });
};

PokerConnectionHandler.prototype.onclose = function(reasonCode, description) {
    console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.');
    if (typeof this.user != 'undefined') {
        currentUsers[this.user.id] = null;
        delete currentUsers[this.user.id];

        carddisplay[this.user.id] = null;
        delete carddisplay.cards[this.user.id];

        broadcastUsers();
        broadcastCards();
    }
};

PokerConnectionHandler.prototype.onmessage = function(message) {
    if (message.type === 'utf8') {
        //console.log('Received Message: ' + message.utf8Data);
        var messageData = JSON.parse(message.utf8Data);
        this.emit(messageData.type, messageData, this);
        switch(messageData.type) {
            case 'reset-cards':
                carddisplay = {
                    cards: {},
                    show: false
                };
                broadcastCards();
                break;

            case 'post-userstory':
                currentUserstory  = messageData.userstory;
                broadcastUserstory();
                break;

            case 'post-chat-message':
                chatMessage = {
                    type: 'new-chat-message',
                    text: messageData.text,
                    user: this.user
                };
                wsServer.broadcastUTF(JSON.stringify(chatMessage));
                break;

            case 'reset-room':
                currentUserstory = '';
                carddisplay = {
                    cards: {},
                    show: false
                };
                broadcastCards();
                broadcastUserstory();

                var pushData = {
                    type: 'reset-room'
                };
                wsServer.broadcastUTF(JSON.stringify(pushData));
                break;
        }
    }
    else if (message.type === 'binary') {
        console.log('Received Binary Message of ' + message.binaryData.length + ' bytes');
    }
};

wsServer.on('request', function(request) {
    var connectionHandler = new PokerConnectionHandler();
    connectionHandler.on('login', pokerLoginListener);
    connectionHandler.on('get-initial-data', getInitialDataListener);
    connectionHandler.on('play-card', playCardListener);
    connectionHandler.on('show-cards', showCardsListener);

	connectionHandler.setConnection(request.accept());

    console.log((new Date()) + ' Connection accepted.');

});

app.get('/', function(req, res) {
    console.log(config.http);
	res.render(
        'index.html',
        {
            web: config.http,
            cards: config.cards
        }
    );
	res.end();
});

getUserUpdateList = function () {
	return {
    	type: 'userlist',
    	data: currentUsers
    };
};

broadcastUsers = function() {
	var pushData = getUserUpdateList();
    wsServer.broadcastUTF(JSON.stringify(pushData));
}

getCardUpdateList = function () {
	return {
    	type: 'carddisplay',
    	data: carddisplay
    };
};

broadcastCards = function() {
	var pushData = getCardUpdateList();
    wsServer.broadcastUTF(JSON.stringify(pushData));
};

getUserstoryUpdate = function() {
	return {
		type: 'userstory',
		userstory: currentUserstory
	};
}

broadcastUserstory = function() {
	var pushData = getUserstoryUpdate();
	wsServer.broadcastUTF(JSON.stringify(pushData));
};

httpServer.listen(config.http.port, function() {
	console.log('HTTP Server running with config:');
    console.log(config.http);
});<|endoftext|>


<commit_before>db.failed_logins.createIndex({timestamp : 1})
db.logs.createIndex({timestamp : 1})
db.logs.createIndex({realm : 1})
db.logs.createIndex({visinst : 1})
db.logs.createIndex({pn : 1})
db.realms.createIndex({realm : 1})
db.mac_count.createIndex({timestamp : 1})
db.roaming.createIndex({timestamp : 1})
db.users_mac.createIndex({username : 1})
db.shared_mac.createIndex({mac_address : 1})
db.heat_map.createIndex({timestamp : 1})
db.heat_map.createIndex({realm : 1})
db.succ_logins.createIndex({timestamp : 1})
db.succ_logins.createIndex({username : 1})
<commit_msg>update indexes<commit_after>db.failed_logins.createIndex({timestamp : 1})
db.logs.createIndex({timestamp : 1})
db.logs.createIndex({realm : 1})
db.logs.createIndex({visinst : 1})
db.logs.createIndex({pn : 1})
db.logs.createIndex({csi : 1})
db.realms.createIndex({realm : 1})
db.mac_count.createIndex({timestamp : 1})
db.roaming.createIndex({timestamp : 1})
db.users_mac.createIndex({username : 1})
db.shared_mac.createIndex({mac_address : 1})
db.heat_map.createIndex({timestamp : 1})
db.heat_map.createIndex({realm : 1})
db.succ_logins.createIndex({timestamp : 1})
db.succ_logins.createIndex({username : 1})
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';

class Counter extends Component {
  constructor() {
    super();
    this.state = { counter: 0 };

    this.increment = this.increment.bind(this);
    this.decrement = this.decrement.bind(this);
  }

  increment() {
    const state = { counter: this.state.counter + 1 };
    this.setState(state);
  }

  decrement() {
    const state = { counter: this.state.counter - 1 };
    this.setState(state);
  }

  render() {
    const { counter } = this.state;
    return (

        Clicked: {counter} times
        {' '}
        <button onClick={this.increment}>+</button>
        {' '}
        <button onClick={this.decrement}>-</button>

    );
  }
}

export default Counter;
<commit_msg>Send changes in react-counter-messaging<commit_after>import React, { Component, PropTypes } from 'react';

class Counter extends Component {
  constructor() {
    super();
    this.state = { counter: 0 };

    this.increment = this.increment.bind(this);
    this.decrement = this.decrement.bind(this);
  }

  increment() {
    const state = { counter: this.state.counter + 1 };
    window.devToolsExtension && window.devToolsExtension.send('increment', state);
    this.setState(state);
  }

  decrement() {
    const state = { counter: this.state.counter - 1 };
    window.devToolsExtension && window.devToolsExtension.send('decrement', state);
    this.setState(state);
  }

  render() {
    const { counter } = this.state;
    return (

        Clicked: {counter} times
        {' '}
        <button onClick={this.increment}>+</button>
        {' '}
        <button onClick={this.decrement}>-</button>

    );
  }
}

export default Counter;
<|endoftext|>


<commit_before>//<script src="https://rawgit.com/mshoote/BTJSC/master/Markup/AutoTestingMRK2.js"></script>
//The following code is from https://github.com/bgrins/devtools-snippets
(function(console){
    console.save = function(data, filename){

        if(!data) {
            console.error('Console.save: No data')
            return;
        }

        if(!filename) filename = 'dataTime.json'

        if(typeof data === "object"){
            data = JSON.stringify(data, undefined, 4)
        }

        var blob = new Blob([data], {type: 'text/json'}),
            e    = document.createEvent('MouseEvents'),
            a    = document.createElement('a')

        a.download = filename
        a.href = window.URL.createObjectURL(blob)
        a.dataset.downloadurl =  ['text/json', a.download, a.href].join(':')
        e.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null)
        a.dispatchEvent(e)
    }
})(console)
window.onload = function() {
    //Following function fixes the loadEventEnd time to give us a better timing.
    window.setTimeout(function(){
  // Check for browser support
  if(!(window.performance && window.performance.timing)) {
    return;
  }
  //This function will send the performance timing to a JSON file to be downloaded.
 //console.log(console.save(performance.timing));

 //This allows us to get the excate times we are wanting.
 console.log(console.save([performance.timing.connectEnd - performance.timing.navigationStart,
 performance.timing.responseEnd - performance.timing.requestStart,
 performance.timing.domComplete - performance.timing.domLoading,
 performance.timing.loadEventEnd - performance.timing.navigationStart,
 performance.timing.responseEnd - performance.timing.fetchStart,
 performance.timing.loadEventEnd - performance.timing.responseEnd]));
    }, 0);
};
//Allows you to set a time(in seconds) for refreshing the page.
setTimeout(function(){window.location=window.location;},50000);
<commit_msg>Update AutoTestingMRK2.js<commit_after>//<script src="https://rawgit.com/mshoote/BTJSC/master/Markup/AutoTestingMRK2.js"></script>
//The following code is from https://github.com/bgrins/devtools-snippets
(function(console){
    console.save = function(data, filename){

        if(!data) {
            console.error('Console.save: No data')
            return;
        }

        if(!filename) filename = 'dataTime.txt'

        if(typeof data === "object"){
            data = JSON.stringify(data, undefined, 4)
        }

        var blob = new Blob([data], {type: 'text/json'}),
            e    = document.createEvent('MouseEvents'),
            a    = document.createElement('a')

        a.download = filename
        a.href = window.URL.createObjectURL(blob)
        a.dataset.downloadurl =  ['text/json', a.download, a.href].join(':')
        e.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null)
        a.dispatchEvent(e)
    }
})(console)
window.onload = function() {
    //Following function fixes the loadEventEnd time to give us a better timing.
    window.setTimeout(function(){
  // Check for browser support
  if(!(window.performance && window.performance.timing)) {
    return;
  }
  //This function will send the performance timing to a JSON file to be downloaded.
 //console.log(console.save(performance.timing));

 //This allows us to get the excate times we are wanting.
 console.log(console.save([performance.timing.connectEnd - performance.timing.navigationStart,
 performance.timing.responseEnd - performance.timing.requestStart,
 performance.timing.domComplete - performance.timing.domLoading,
 performance.timing.loadEventEnd - performance.timing.navigationStart,
 performance.timing.responseEnd - performance.timing.fetchStart,
 performance.timing.loadEventEnd - performance.timing.responseEnd]));
    }, 0);
};
//Allows you to set a time(in seconds) for refreshing the page.
setTimeout(function(){window.location=window.location;},50000);
<|endoftext|>


<commit_before>angular.module('anol.savemanager')

/**
 * @ngdoc object
 * @name anol.savemanager.SaveManagerServiceProvider
 */
.provider('SaveManagerService', [function() {
    // handles layer source change events and store listener keys for removing
    // listeners nicely
    var LayerListener = function(layer, saveManager) {
        this.layer = layer;
        this.saveManager = saveManager;
        this.source = layer.olLayer.getSource();

        this.addListenerKey = undefined;
        this.changeListenerKey = undefined;
        this.removeListenerKey = undefined;
    };
    LayerListener.prototype.register = function(addHandler, changeHandler, removeHandler) {
        var self = this;

        var _register = function(type, handler, key) {
            if(handler === undefined) {
                return;
            }
            if(key !== undefined) {
                self.source.unByKey(key);
            }
            return self.source.on(
                type,
                function(evt) {
                    handler.apply(self.saveManager, [evt, self.layer]);
                }
            );
        };

        self.addListenerKey = _register(
            ol.source.VectorEventType.ADDFEATURE,
            addHandler,
            self.addListenerKey
        );
        self.changeListenerKey = _register(
            ol.source.VectorEventType.CHANGEFEATURE,
            changeHandler,
            self.changeListenerKey
        );
        self.removeListenerKey = _register(
            ol.source.VectorEventType.REMOVEFEATURE,
            removeHandler,
            self.removeListenerKey
        );
    };
    LayerListener.prototype.unregister = function() {
        var self = this;
        if(self.addListenerKey !== undefined) {
            self.source.unByKey(self.addListenerKey);
            self.addListenerKey = undefined;
        }
        if(self.changeListenerKey !== undefined) {
            self.source.unByKey(self.changeListenerKey);
            self.changeListenerKey = undefined;
        }
        if(self.removeListenerKey !== undefined) {
            self.source.unByKey(self.removeListenerKey);
            self.removeListenerKey = undefined;
        }
    };

    // stores features depending on their edit state
    // and converts stored features to geojson objects
    var FeatureStore = function(format) {
        this.format = format || new ol.format.GeoJSON();
        this.added = [];
        this.changed = [];
        this.removed = [];
    };
    FeatureStore.prototype.pushInto = function(list, feature) {
        if(list.indexOf(feature) === -1) {
            list.push(feature);
        }
    };
    FeatureStore.prototype.pushAdded = function(feature) {
        this.pushInto(this.added, feature);
    };
    FeatureStore.prototype.pushChanged = function(feature) {
        if(this.added.indexOf(feature) !== -1) {
            return;
        }
        this.pushInto(this.changed, feature);
    };
    FeatureStore.prototype.pushRemoved = function(feature) {
        var addIdx = this.added.indexOf(feature);
        if(addIdx !== -1) {
            this.added.splice(addIdx, 1);
            return;
        }
        var changedIdx = this.changed.indexOf(feature);
        if(changedIdx !== -1) {
            this.changed.splice(changedIdx, 1);
        }
        this.pushInto(this.removed, feature);
    };
    FeatureStore.prototype.clearAdded = function() {
        this.added.length = 0;
    };
    FeatureStore.prototype.clearChanged = function() {
        this.changed.length = 0;
    };
    FeatureStore.prototype.clearRemoved = function() {
        this.removed.length = 0;
    };
    FeatureStore.prototype.hasAddedFeatures = function() {
        return this.added.length > 0;
    };
    FeatureStore.prototype.hasChangedFeatures = function() {
        return this.changed.length > 0;
    };
    FeatureStore.prototype.hasRemovedFeatures = function() {
        return this.removed.length > 0;
    };
    FeatureStore.prototype.addedFeatures = function() {
        return this.format.writeFeaturesObject(this.added);
    };
    FeatureStore.prototype.changedFeatures = function() {
        return this.format.writeFeaturesObject(this.changed);
    };
    FeatureStore.prototype.removedFeatures = function() {
        var ids = [];
        angular.forEach(this.removed, function(feature) {
            ids.push(feature.get('_id'));
        });
        return ids;
    };

    var _saveUrl;
    /**
     * @ngdoc method
     * @name setSaveUrl
     * @methodOf anol.savemanager.SaveManagerServiceProvider
     * @param {String} saveUrl url to save changes to. Might be overwritten by layer.saveUrl
     */
    this.setSaveUrl = function(saveUrl) {
        _saveUrl = saveUrl;
    };

    this.$get = ['$rootScope', '$q', '$http', '$timeout', function($rootScope, $q, $http, $timeout) {
        /**
         * @ngdoc service
         * @name anol.savemanager.SaveManagerService
         *
         * @description
         * Collects changes in saveable layers and send them to given saveUrl
         */
        var SaveManager = function(saveUrl) {
            this.saveUrl = saveUrl;
            this.changedLayers = {};
            this.changedFeatures = {};
        };
        /**
         * @ngdoc method
         * @name addLayer
         * @methodOd anol.savemanager.SaveManagerService
         * @param {anol.layer.Feature} layer layer to watch for changes
         */
        SaveManager.prototype.addLayer = function(layer) {
            var self = this;
            var layerListener = new LayerListener(layer, self);
            $rootScope.$watch(function() {
                return layer.loaded;
            }, function(loaded) {
                if(loaded === true) {
                    layerListener.register(
                        self.featureAddedHandler,
                        self.featureChangedHandler,
                        self.featureRemovedHandler
                    );
                } else {
                    layerListener.unregister();
                }
            });
        };
        /**
         * private function
         *
         * handler for ol3 feature added event
         */
        SaveManager.prototype.featureAddedHandler = function(evt, layer) {
            var self = this;
            var feature = evt.feature;
            var featureStore = self.featureStoreByLayer(layer);
            featureStore.pushAdded(feature);
            self.addChangedLayer(layer);
        };
        /**
         * private function
         *
         * handler for ol3 feature changed event
         */
        SaveManager.prototype.featureChangedHandler = function(evt, layer) {
            var self = this;
            var feature = evt.feature;
            var featureStore = self.featureStoreByLayer(layer);
            featureStore.pushChanged(feature);
            self.addChangedLayer(layer);
        };
        /**
         * private function
         *
         * handler for ol3 feature removed event
         */
        SaveManager.prototype.featureRemovedHandler = function(evt, layer) {
            var self = this;
            var feature = evt.feature;
            var featureStore = self.featureStoreByLayer(layer);
            featureStore.pushRemoved(feature);
            self.addChangedLayer(layer);
        };
        /**
         * private function
         *
         * returns corresponding feature store for given layer
         */
        SaveManager.prototype.featureStoreByLayer = function(layer) {
            var self = this;
            if(self.changedFeatures[layer.name] === undefined) {
                self.changedFeatures[layer.name] = new FeatureStore();
            }
            return self.changedFeatures[layer.name];
        };
        /**
         * private function
         *
         * adds a layer to list of layers with changes
         */
        SaveManager.prototype.addChangedLayer = function(layer) {
            var self = this;
            if(!(layer.name in self.changedLayers)) {
                // TODO find out why $apply already in progress
                $timeout(function() {
                    $rootScope.$apply(function() {
                        self.changedLayers[layer.name] = layer;
                    });
                });
            }
        };
        /**
         * private function
         *
         * cleans up after changes done
         */
        SaveManager.prototype.changesDone = function(layerName) {
            delete this.changedLayers[layerName];
            delete this.changedFeatures[layerName];
        };
        /**
         * private function
         *
         * sends changes to saveUrl or layer.saveUrl
         */
        SaveManager.prototype.commitFeatures = function(featureStore, layerName, targetUrl) {
            var promises = [];
            if(featureStore.hasAddedFeatures()) {
                var addDeferred = $q.defer();
                promises.push(addDeferred.promise);

                var data = featureStore.addedFeatures();
                data.layername = layerName;

                $http.put(targetUrl, data).then(function() {
                    featureStore.clearAdded();
                    addDeferred.resolve();
                }, function(reason) {
                    addDeferred.reject(reason);
                });
            }
            if(featureStore.hasChangedFeatures()) {
                var changeDeferred = $q.defer();
                promises.push(changeDeferred.promise);

                $http.post(targetUrl, featureStore.changedFeatures()).then(function() {
                    featureStore.clearChanged();
                    changeDeferred.resolve();
                }, function(reason) {
                    changeDeferred.reject(reason);
                });
            }
            if(featureStore.hasRemovedFeatures()) {
                var removeDeferred = $q.defer();
                promises.push(removeDeferred.promise);
                $http.delete(targetUrl, {
                    params: {
                        'ids': featureStore.removedFeatures().join(',')
                    }
                }).then(function() {
                    featureStore.clearRemoved();
                    removeDeferred.resolve();
                }, function(reason) {
                    removeDeferred.reject(reason);
                });
            }
            return $q.all(promises);
        };
        /**
         * @ngdoc method
         * @name commit
         * @methodOd anol.savemanager.SaveManagerService
         * @param {anol.layer.Feature} layer
         * @description
         * Commits changes for given layer
         */
        SaveManager.prototype.commit = function(layer) {
            var self = this;
            var deferred = $q.defer();

            if(layer.name in self.changedLayers) {
                var featureStore = self.featureStoreByLayer(layer);
                var promise = self.commitFeatures(featureStore, layer.name, layer.saveUrl || self.saveUrl);
                promise.then(function() {
                    self.changesDone(layer.name);
                    deferred.resolve();
                }, function(reason) {
                    deferred.reject(reason);
                });
            } else {
                deferred.reject('No changes for layer ' + layer.name + ' present');
            }

            return deferred.promise;
        };

        return new SaveManager(_saveUrl);
    }];
}]);<commit_msg>Renamed data variable<commit_after>angular.module('anol.savemanager')

/**
 * @ngdoc object
 * @name anol.savemanager.SaveManagerServiceProvider
 */
.provider('SaveManagerService', [function() {
    // handles layer source change events and store listener keys for removing
    // listeners nicely
    var LayerListener = function(layer, saveManager) {
        this.layer = layer;
        this.saveManager = saveManager;
        this.source = layer.olLayer.getSource();

        this.addListenerKey = undefined;
        this.changeListenerKey = undefined;
        this.removeListenerKey = undefined;
    };
    LayerListener.prototype.register = function(addHandler, changeHandler, removeHandler) {
        var self = this;

        var _register = function(type, handler, key) {
            if(handler === undefined) {
                return;
            }
            if(key !== undefined) {
                self.source.unByKey(key);
            }
            return self.source.on(
                type,
                function(evt) {
                    handler.apply(self.saveManager, [evt, self.layer]);
                }
            );
        };

        self.addListenerKey = _register(
            ol.source.VectorEventType.ADDFEATURE,
            addHandler,
            self.addListenerKey
        );
        self.changeListenerKey = _register(
            ol.source.VectorEventType.CHANGEFEATURE,
            changeHandler,
            self.changeListenerKey
        );
        self.removeListenerKey = _register(
            ol.source.VectorEventType.REMOVEFEATURE,
            removeHandler,
            self.removeListenerKey
        );
    };
    LayerListener.prototype.unregister = function() {
        var self = this;
        if(self.addListenerKey !== undefined) {
            self.source.unByKey(self.addListenerKey);
            self.addListenerKey = undefined;
        }
        if(self.changeListenerKey !== undefined) {
            self.source.unByKey(self.changeListenerKey);
            self.changeListenerKey = undefined;
        }
        if(self.removeListenerKey !== undefined) {
            self.source.unByKey(self.removeListenerKey);
            self.removeListenerKey = undefined;
        }
    };

    // stores features depending on their edit state
    // and converts stored features to geojson objects
    var FeatureStore = function(format) {
        this.format = format || new ol.format.GeoJSON();
        this.added = [];
        this.changed = [];
        this.removed = [];
    };
    FeatureStore.prototype.pushInto = function(list, feature) {
        if(list.indexOf(feature) === -1) {
            list.push(feature);
        }
    };
    FeatureStore.prototype.pushAdded = function(feature) {
        this.pushInto(this.added, feature);
    };
    FeatureStore.prototype.pushChanged = function(feature) {
        if(this.added.indexOf(feature) !== -1) {
            return;
        }
        this.pushInto(this.changed, feature);
    };
    FeatureStore.prototype.pushRemoved = function(feature) {
        var addIdx = this.added.indexOf(feature);
        if(addIdx !== -1) {
            this.added.splice(addIdx, 1);
            return;
        }
        var changedIdx = this.changed.indexOf(feature);
        if(changedIdx !== -1) {
            this.changed.splice(changedIdx, 1);
        }
        this.pushInto(this.removed, feature);
    };
    FeatureStore.prototype.clearAdded = function() {
        this.added.length = 0;
    };
    FeatureStore.prototype.clearChanged = function() {
        this.changed.length = 0;
    };
    FeatureStore.prototype.clearRemoved = function() {
        this.removed.length = 0;
    };
    FeatureStore.prototype.hasAddedFeatures = function() {
        return this.added.length > 0;
    };
    FeatureStore.prototype.hasChangedFeatures = function() {
        return this.changed.length > 0;
    };
    FeatureStore.prototype.hasRemovedFeatures = function() {
        return this.removed.length > 0;
    };
    FeatureStore.prototype.addedFeatures = function() {
        return this.format.writeFeaturesObject(this.added);
    };
    FeatureStore.prototype.changedFeatures = function() {
        return this.format.writeFeaturesObject(this.changed);
    };
    FeatureStore.prototype.removedFeatures = function() {
        var ids = [];
        angular.forEach(this.removed, function(feature) {
            ids.push(feature.get('_id'));
        });
        return ids;
    };

    var _saveUrl;
    /**
     * @ngdoc method
     * @name setSaveUrl
     * @methodOf anol.savemanager.SaveManagerServiceProvider
     * @param {String} saveUrl url to save changes to. Might be overwritten by layer.saveUrl
     */
    this.setSaveUrl = function(saveUrl) {
        _saveUrl = saveUrl;
    };

    this.$get = ['$rootScope', '$q', '$http', '$timeout', function($rootScope, $q, $http, $timeout) {
        /**
         * @ngdoc service
         * @name anol.savemanager.SaveManagerService
         *
         * @description
         * Collects changes in saveable layers and send them to given saveUrl
         */
        var SaveManager = function(saveUrl) {
            this.saveUrl = saveUrl;
            this.changedLayers = {};
            this.changedFeatures = {};
        };
        /**
         * @ngdoc method
         * @name addLayer
         * @methodOd anol.savemanager.SaveManagerService
         * @param {anol.layer.Feature} layer layer to watch for changes
         */
        SaveManager.prototype.addLayer = function(layer) {
            var self = this;
            var layerListener = new LayerListener(layer, self);
            $rootScope.$watch(function() {
                return layer.loaded;
            }, function(loaded) {
                if(loaded === true) {
                    layerListener.register(
                        self.featureAddedHandler,
                        self.featureChangedHandler,
                        self.featureRemovedHandler
                    );
                } else {
                    layerListener.unregister();
                }
            });
        };
        /**
         * private function
         *
         * handler for ol3 feature added event
         */
        SaveManager.prototype.featureAddedHandler = function(evt, layer) {
            var self = this;
            var feature = evt.feature;
            var featureStore = self.featureStoreByLayer(layer);
            featureStore.pushAdded(feature);
            self.addChangedLayer(layer);
        };
        /**
         * private function
         *
         * handler for ol3 feature changed event
         */
        SaveManager.prototype.featureChangedHandler = function(evt, layer) {
            var self = this;
            var feature = evt.feature;
            var featureStore = self.featureStoreByLayer(layer);
            featureStore.pushChanged(feature);
            self.addChangedLayer(layer);
        };
        /**
         * private function
         *
         * handler for ol3 feature removed event
         */
        SaveManager.prototype.featureRemovedHandler = function(evt, layer) {
            var self = this;
            var feature = evt.feature;
            var featureStore = self.featureStoreByLayer(layer);
            featureStore.pushRemoved(feature);
            self.addChangedLayer(layer);
        };
        /**
         * private function
         *
         * returns corresponding feature store for given layer
         */
        SaveManager.prototype.featureStoreByLayer = function(layer) {
            var self = this;
            if(self.changedFeatures[layer.name] === undefined) {
                self.changedFeatures[layer.name] = new FeatureStore();
            }
            return self.changedFeatures[layer.name];
        };
        /**
         * private function
         *
         * adds a layer to list of layers with changes
         */
        SaveManager.prototype.addChangedLayer = function(layer) {
            var self = this;
            if(!(layer.name in self.changedLayers)) {
                // TODO find out why $apply already in progress
                $timeout(function() {
                    $rootScope.$apply(function() {
                        self.changedLayers[layer.name] = layer;
                    });
                });
            }
        };
        /**
         * private function
         *
         * cleans up after changes done
         */
        SaveManager.prototype.changesDone = function(layerName) {
            delete this.changedLayers[layerName];
            delete this.changedFeatures[layerName];
        };
        /**
         * private function
         *
         * sends changes to saveUrl or layer.saveUrl
         */
        SaveManager.prototype.commitFeatures = function(featureStore, layerName, targetUrl) {
            var promises = [];
            if(featureStore.hasAddedFeatures()) {
                var addDeferred = $q.defer();
                promises.push(addDeferred.promise);

                var addData = featureStore.addedFeatures();
                addData.name = layerName;

                $http.put(targetUrl, addData).then(function() {
                    featureStore.clearAdded();
                    addDeferred.resolve();
                }, function(reason) {
                    addDeferred.reject(reason);
                });
            }
            if(featureStore.hasChangedFeatures()) {
                var changeDeferred = $q.defer();
                promises.push(changeDeferred.promise);

                var changeData = featureStore.addedFeatures();
                changeData.name = layerName;

                $http.post(targetUrl, changeData).then(function() {
                    featureStore.clearChanged();
                    changeDeferred.resolve();
                }, function(reason) {
                    changeDeferred.reject(reason);
                });
            }
            if(featureStore.hasRemovedFeatures()) {
                var removeDeferred = $q.defer();
                promises.push(removeDeferred.promise);
                $http.delete(targetUrl, {
                    params: {
                        'ids': featureStore.removedFeatures().join(',')
                    }
                }).then(function() {
                    featureStore.clearRemoved();
                    removeDeferred.resolve();
                }, function(reason) {
                    removeDeferred.reject(reason);
                });
            }
            return $q.all(promises);
        };
        /**
         * @ngdoc method
         * @name commit
         * @methodOd anol.savemanager.SaveManagerService
         * @param {anol.layer.Feature} layer
         * @description
         * Commits changes for given layer
         */
        SaveManager.prototype.commit = function(layer) {
            var self = this;
            var deferred = $q.defer();

            if(layer.name in self.changedLayers) {
                var featureStore = self.featureStoreByLayer(layer);
                var promise = self.commitFeatures(featureStore, layer.name, layer.saveUrl || self.saveUrl);
                promise.then(function() {
                    self.changesDone(layer.name);
                    deferred.resolve();
                }, function(reason) {
                    deferred.reject(reason);
                });
            } else {
                deferred.reject('No changes for layer ' + layer.name + ' present');
            }

            return deferred.promise;
        };

        return new SaveManager(_saveUrl);
    }];
}]);<|endoftext|>