<commit_before>var get = function(id) {
    return document.getElementById(id);
}

var divider = "\n------------------------------------------------------";
var that;
var gameCommandsArray = ["adventurer.adventurerData()","adventurer.addToInventory()","adventurer.viewInventory()", "adventurer.addSpell(spell)",
                "adventurer.viewSpells()", "adventurer.setWeapon(woodenMeleeWeapon || woodenRangeWeapon)",
                "adventurer.lotOfPots() -- Adds 50 HP Potions", "adventurer.playerOneHealthItem.use()",
                "adventurer.playerTwoHealthItem.use()", "adventurer.battle()", "adventurer.attack()"];

var Game = {
    gameItems : ["HP Pot", "MP Pot", "Brass Guard", "Wooden Sword", "Wooden Staff"],
    commands : function(){
        var i = 0;
        while(i < gameCommandsArray.length){ console.log(gameCommandsArray[i] + divider); i++ }
    },
    enemy : undefined,
    enemyList : ["Skeleton Warrior", "Vale Rat"],
    gameEnemies : {
        skeleton : {
            name : "Skeleton Warrior",
            health : 40,
            attack : "Skeletal Slash",
            damage : 6,
            itemList: ["Wooden Sword", "HP Pot", "Brass Guard"]
        },
        rat : {
            name : "Vale Rat",
            health : 20,
            attack : "Scratch",
            damage : 2,
            itemList: ["MP Pot", "Wooden Staff"]
        },
    },
    enemyHealth : undefined,
    inBattle : false,

    playerTurn : true
};

var Adventurer = function(name, health, mana) {
    this.name = name;
    this.health = health;
    this.maxHealth = health;
    this.maxOverheal = this.maxHealth * 2;
    this.mana = mana;
    this.inventory = [];
    this.spells = [];
    this.weapon;
    this.level = 1;
    this.attackPower = 1;
    /*var experience = 5;
    var neededExperience = experience * 2;

    this.addExperience = function(experienceGiven){
        experience += experienceGiven;
        console.log(experience);
        console.log(neededExperience);

        if(experience >= neededExperience){
            this.level += 1;
            var previousLevel = this.level - 1;
            console.log(this.name + " has " + "LEVELED UP!" + "(" + previousLevel + "->" + this.level + ")");
            neededExperience = experience * 2;
        }
    }*/

}

var woodenMeleeWeapon = {
    damage : 8,
    name : "Wooden Sword",
    uses : 40,
    info : "Your weathered but trusty wooden sword"
};

var woodenRangeWeapon = {
    damage : 4,
    rangedDamage : 13,
    mana : 5,
    name : "Wooden Staff",
    uses: 40,
    info : "A wooden staff with a rock-hard tip"
};

Adventurer.prototype.addToInventory = function(item) {
    for(i = 0; i < Game.gameItems.length; i++){
        if(item == Game.gameItems[i]){ this.inventory.push(item); }
    }
}

Adventurer.prototype.addSpell = function(spell) {
    this.spells.push(spell);
}

Adventurer.prototype.setWeapon = function(weapon) {
    if(weapon == woodenMeleeWeapon){
        this.weapon = woodenMeleeWeapon;
        this.inventory.push(weapon.name);
    }
    else if(weapon == woodenRangeWeapon){
        this.weapon = woodenRangeWeapon; Game.gameItems.push(weapon);
        this.inventory.push(weapon.name);
    }
}

var HealthItem = function(adventurer) {
    this.healthItemName = "";
    this.healAmount = 0;

    this.use = function() {
        that = adventurer;
        console.log(that.name);
        for (var x = 0; x < that.inventory.length; x++) {
            if (that.inventory[x] == "HP Pot") {
                this.healthItemName = "HP Pot";
                this.healAmount = 30;
                that.health += this.healAmount;
                console.log(that.name + " Has Used " + this.healthItemName + " For " + this.healAmount + divider);
                if (that.health > that.maxHealth && that.health < that.maxOverheal) {
                    var overheal = that.health - that.maxHealth;
                    console.log("Overhealed by " + overheal + "!");
                } else if (that.health > that.maxOverheal) {
                    console.log(that.name + " cannot " + "be " + "overhealed " + "anymore!");
                    that.health = that.maxOverheal;
                }
                that.inventory[x] = "";
                return;
            }
        }
        console.log("No Health Items in Inventory" + divider);
    }
}

Adventurer.prototype.adventurerData = function() {
    console.log(this.name);
    console.log("Health: " + this.health);
    console.log("Mana: " + this.mana + divider);
}

Adventurer.prototype.viewSpells = function() {
    for (var i = 0; i < this.spells.length; i++) {
        console.log(this.spells[i] + divider);
    }
}

Adventurer.prototype.useSpell = function(spell) {
    for (var i = 0; i < this.spells.length; i++) {
        if (this.spells[i] == spell) {
            console.log("Yep");
            return;
        }
    }
    console.log("You don't know how to do that..." + divider);

}

Adventurer.prototype.viewInventory = function() {
    for (var x = 0; x < this.inventory.length; x++) {
        console.log(this.inventory[x] + divider);
    }
    if (this.inventory.length == 0) {
        console.log(this.name + "'s" + " bag is empty");
    }
}

Adventurer.prototype.lotOfPots = function() {
    for (var i = 0; i < 50; i++) {
        this.addToInventory("HP Pot");
    }
}

Adventurer.prototype.battle = function(){
    if(Game.enemy != undefined){
        console.log("You're already in a battle!");
    }
    else{
    Game.inBattle = true;
    Game.enemy = Game.enemyList[Math.floor(Math.random()*Game.enemyList.length)];
    if(Game.enemy == "Skeleton Warrior"){ Game.enemy = Game.gameEnemies.skeleton; }
    else{ Game.enemy = Game.gameEnemies.rat; }
    Game.enemyHealth = Game.enemy.health;
    console.log(this.name + "'s" + " party has encountered " + Game.enemy.name + "(HP:" + Game.enemy.health + ")");
}
}

Adventurer.prototype.attack = function(){
    while(Game.playerTurn){
        damage = this.weapon.damage + (this.attackPower * 0.5);
        Game.enemyHealth -= damage;
        console.log(this.name +  " hit " + Game.enemy.name + " for " + damage + "!");
        console.log(Game.enemy.name + " HP: " + Game.enemyHealth + divider);
        if(Game.enemyHealth <= 0){
            Game.enemyHealth = 0;
            console.log(this.name + "'s" + " party has defeated " + Game.enemy.name + "!" + divider);
            for(var i = 0; i < 1; i++){
                var loot = Game.enemy.itemList[Math.floor(Math.random()*Game.enemy.itemList.length)];
                this.addToInventory(loot);
                console.log(this.name + " looted " + loot + " from " + Game.enemy.name);
            }
            Game.enemy = undefined;
        }
        Game.playerTurn = false;
    }
    Game.playerTurn = true;
}

var isaac = new Adventurer("Isaac", 100, 50);
var mia = new Adventurer("Mia", 80, 90);

isaac.setWeapon(woodenMeleeWeapon);
mia.setWeapon(woodenRangeWeapon);

Adventurer.prototype.playerOneHealthItem = new HealthItem(isaac);
Adventurer.prototype.playerTwoHealthItem = new HealthItem(mia);

isaac.addSpell("Earthquake");
isaac.addSpell("Push");

mia.addSpell("Soothing Waters");
mia.addSpell("Sleet");

console.log("Golden Sun Battle Sim" + divider);
console.log("Enter - Game.commands() - to view all usable functions" + divider);
<commit_msg>added critical hits for enemies<commit_after>var get = function(id) {
    return document.getElementById(id);
}

var divider = "\n------------------------------------------------------";
var that;
var gameCommandsArray = ["adventurer.adventurerData()","adventurer.addToInventory()","adventurer.viewInventory()", "adventurer.addSpell(spell)",
                "adventurer.viewSpells()", "adventurer.setWeapon(woodenMeleeWeapon || woodenRangeWeapon)",
                "adventurer.lotOfPots() -- Adds 50 HP Potions", "adventurer.playerOneHealthItem.use()",
                "adventurer.playerTwoHealthItem.use()", "adventurer.battle()", "adventurer.attack()"];

var Game = {
    gameItems : ["HP Pot", "MP Pot", "Brass Guard", "Wooden Sword", "Wooden Staff"],
    commands : function(){
        var i = 0;
        while(i < gameCommandsArray.length){ console.log(gameCommandsArray[i] + divider); i++ }
    },
    enemy : undefined,
    enemyList : ["Skeleton Warrior", "Vale Rat"],
    gameEnemies : {
        skeleton : {
            name : "Skeleton Warrior",
            health : 40,
            attack : "Skeletal Slash",
            damage : 9,
            itemList: ["Wooden Sword", "HP Pot", "Brass Guard"]
        },
        rat : {
            name : "Vale Rat",
            health : 20,
            attack : "Scratch",
            damage : 7,
            itemList: ["MP Pot", "Wooden Staff"]
        },
    },
    enemyHealth : undefined,
    inBattle : false,

    playerTurn : true
};

var Adventurer = function(name, health, mana) {
    this.name = name;
    this.health = health;
    this.maxHealth = health;
    this.maxOverheal = this.maxHealth * 2;
    this.mana = mana;
    this.inventory = [];
    this.spells = [];
    this.weapon;
    this.level = 1;
    this.attackPower = 1;
    /*var experience = 5;
    var neededExperience = experience * 2;

    this.addExperience = function(experienceGiven){
        experience += experienceGiven;
        console.log(experience);
        console.log(neededExperience);

        if(experience >= neededExperience){
            this.level += 1;
            var previousLevel = this.level - 1;
            console.log(this.name + " has " + "LEVELED UP!" + "(" + previousLevel + "->" + this.level + ")");
            neededExperience = experience * 2;
        }
    }*/

}

var woodenMeleeWeapon = {
    damage : 8,
    name : "Wooden Sword",
    uses : 40,
    info : "Your weathered but trusty wooden sword"
};

var woodenRangeWeapon = {
    damage : 4,
    rangedDamage : 13,
    mana : 5,
    name : "Wooden Staff",
    uses: 40,
    info : "A wooden staff with a rock-hard tip"
};

Adventurer.prototype.addToInventory = function(item) {
    for(i = 0; i < Game.gameItems.length; i++){
        if(item == Game.gameItems[i]){ this.inventory.push(item); }
    }
}

Adventurer.prototype.addSpell = function(spell) {
    this.spells.push(spell);
}

Adventurer.prototype.setWeapon = function(weapon) {
    if(weapon == woodenMeleeWeapon){
        this.weapon = woodenMeleeWeapon;
        this.inventory.push(weapon.name);
    }
    else if(weapon == woodenRangeWeapon){
        this.weapon = woodenRangeWeapon; Game.gameItems.push(weapon);
        this.inventory.push(weapon.name);
    }
}

var HealthItem = function(adventurer) {
    this.healthItemName = "";
    this.healAmount = 0;

    this.use = function() {
        that = adventurer;
        console.log(that.name);
        for (var x = 0; x < that.inventory.length; x++) {
            if (that.inventory[x] == "HP Pot") {
                this.healthItemName = "HP Pot";
                this.healAmount = 30;
                that.health += this.healAmount;
                console.log(that.name + " Has Used " + this.healthItemName + " For " + this.healAmount + divider);
                if (that.health > that.maxHealth && that.health < that.maxOverheal) {
                    var overheal = that.health - that.maxHealth;
                    console.log("Overhealed by " + overheal + "!");
                } else if (that.health > that.maxOverheal) {
                    console.log(that.name + " cannot " + "be " + "overhealed " + "anymore!");
                    that.health = that.maxOverheal;
                }
                that.inventory[x] = "";
                return;
            }
        }
        console.log("No Health Items in Inventory" + divider);
    }
}

Adventurer.prototype.adventurerData = function() {
    console.log(this.name);
    console.log("Health: " + this.health);
    console.log("Mana: " + this.mana + divider);
}

Adventurer.prototype.viewSpells = function() {
    for (var i = 0; i < this.spells.length; i++) {
        console.log(this.spells[i] + divider);
    }
}

Adventurer.prototype.useSpell = function(spell) {
    for (var i = 0; i < this.spells.length; i++) {
        if (this.spells[i] == spell) {
            console.log("Yep");
            return;
        }
    }
    console.log("You don't know how to do that..." + divider);

}

Adventurer.prototype.viewInventory = function() {
    for (var x = 0; x < this.inventory.length; x++) {
        console.log(this.inventory[x] + divider);
    }
    if (this.inventory.length == 0) {
        console.log(this.name + "'s" + " bag is empty");
    }
}

Adventurer.prototype.lotOfPots = function() {
    for (var i = 0; i < 50; i++) {
        this.addToInventory("HP Pot");
    }
}

Adventurer.prototype.battle = function(){
    if(Game.enemy != undefined){
        console.log("You're already in a battle!");
    }
    else{
    Game.inBattle = true;
    Game.enemy = Game.enemyList[Math.floor(Math.random()*Game.enemyList.length)];
    if(Game.enemy == "Skeleton Warrior"){ Game.enemy = Game.gameEnemies.skeleton; }
    else{ Game.enemy = Game.gameEnemies.rat; }
    Game.enemyHealth = Game.enemy.health;
    console.log(this.name + "'s" + " party has encountered " + Game.enemy.name + "(HP:" + Game.enemy.health + ")");
}
}

Adventurer.prototype.attack = function(){
    if(Game.enemyHealth > 0){
    while(Game.playerTurn){
        damage = this.weapon.damage + (this.attackPower * 0.5);
        Game.enemyHealth -= damage;
        console.log(this.name +  " hit " + Game.enemy.name + " for " + damage + "!");
        if(Game.enemyHealth < 0) { Game.enemyHealth = 0; console.log(Game.enemy.name + " HP: " + Game.enemyHealth + divider); }
        else { console.log(Game.enemy.name + " HP: " + Game.enemyHealth + divider); }
        Game.playerTurn = false;
    }
    if(Game.enemyHealth <= 0){
            Game.enemyHealth = 0;
            console.log(this.name + "'s" + " party has defeated " + Game.enemy.name + "!" + divider);
            for(var i = 0; i < 1; i++){
                var loot = Game.enemy.itemList[Math.floor(Math.random()*Game.enemy.itemList.length)];
                this.addToInventory(loot);
                console.log(this.name + " looted " + loot + " from " + Game.enemy.name);
            }
            Game.enemy = undefined;
        }
    if(!Game.playerTurn && Game.enemyHealth > 0){
        var critCheck = Math.floor(Math.random()*10);
        if(critCheck == 9) {
            this.health -= Game.enemy.damage * 1.5;
            var critDamage = Game.enemy.damage * 1.5;
            console.log(">> CRITICAL HIT BONUS <<");
            console.log("**" + Game.enemy.name + " hits " + this.name + " for " + critDamage + "!**");
        }
        else {
            this.health -= Game.enemy.damage;
            console.log("**" + Game.enemy.name + " hits " + this.name + " for " + Game.enemy.damage + "!**");
        }

    }
    }
    Game.playerTurn = true;
}

var isaac = new Adventurer("Isaac", 100, 50);
var mia = new Adventurer("Mia", 80, 90);

isaac.setWeapon(woodenMeleeWeapon);
mia.setWeapon(woodenRangeWeapon);

Adventurer.prototype.playerOneHealthItem = new HealthItem(isaac);
Adventurer.prototype.playerTwoHealthItem = new HealthItem(mia);

isaac.addSpell("Earthquake");
isaac.addSpell("Push");

mia.addSpell("Soothing Waters");
mia.addSpell("Sleet");

console.log("Golden Sun Battle Sim" + divider);
console.log("Enter - Game.commands() - to view all usable functions" + divider);
<|endoftext|>


<commit_before>/*
 * Websensor video stabilization project
 * https://github.com/jessenie-intel/websensor-video
 *
 * Copyright (c) 2017 Jesse Nieminen
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
*/

'use strict';

var constraints = {audio: true,video: {  width: { min: 640, ideal: 640, max: 640 },  height: { min: 480, ideal: 480, max: 480 }}};
var mediaRecorder = null;
var chunks = [];
var videoData = null;
var interval = null;

var accel_sensor = null;
var orientation_sensor = null;
var sensorfreq = 60;

//var roll = null;
//var pitch = null;
//var yaw = null;
var accel = {"x": null, "y": null, "z": null};
var ori = {"roll": null, "pitch": null, "yaw": null, "time": null};
var oriInitial = {"roll": null, "pitch": null, "yaw": null, "time": null};
var initialoriobtained = false;
var orientationData = [];       //array to store all the orientation data
var frameData = {"data": null, "time": null, "ori": null};
var dataArray = [];     //array to store all the combined data
var dataArray2 = [];     //array to store all the combined data

var time = null;
var timestamps = [];
var nFrame = 0; //frame number with which we can combine timestamp and frame data

//canvas
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');

//video element
var videoElement = document.querySelector('video');
videoElement.controls = false;

var ref = null;

class AbsOriSensor {
        constructor() {
        const sensor = new AbsoluteOrientationSensor({ frequency: sensorfreq });
        const mat4 = new Float32Array(16);
        const euler = new Float32Array(3);
        sensor.onreading = () => {
                sensor.populateMatrix(mat4);
                toEulerianAngle(sensor.quaternion, euler);      //From quaternion to Eulerian angles
                this.roll = euler[0];
                this.pitch = euler[1];
                this.yaw = euler[2];
                this.timestamp = sensor.timestamp;
                if (this.onreading) this.onreading();
        };
        sensor.onactivate = () => {
                if (this.onactivate) this.onactivate();
        };
        const start = () => sensor.start();
        Object.assign(this, { start });
        }
}

//WINDOWS 10 HAS DIFFERENT CONVENTION: Yaw z, pitch x, roll y
function toEulerianAngle(quat, out)
{
        const ysqr = quat[1] ** 2;

        // Roll (x-axis rotation).
        const t0 = 2 * (quat[3] * quat[0] + quat[1] * quat[2]);
        const t1 = 1 - 2 * (ysqr + quat[0] ** 2);
        out[0] = Math.atan2(t0, t1);
        // Pitch (y-axis rotation).
        let t2 = 2 * (quat[3] * quat[1] - quat[2] * quat[0]);
        t2 = t2 > 1 ? 1 : t2;
        t2 = t2 < -1 ? -1 : t2;
        out[1] = Math.asin(t2);
        // Yaw (z-axis rotation).
        const t3 = 2 * (quat[3] * quat[2] + quat[0] * quat[1]);
        const t4 = 1 - 2 * (ysqr + quat[2] ** 2);
        out[2] = Math.atan2(t3, t4);
        return out;
}

function errorCallback(error){
	console.log("error: ", error);
}

function startDemo () {
		navigator.getUserMedia(constraints, startRecording, errorCallback);
}

function startRecording(stream) {

                try {
                //Initialize sensors
                /*accel_sensor = new Accelerometer();
                accel_sensor.onreading = () => {
                        accel = {"x": accel_sensor.x, "y": accel_sensor.y, "z": accel_sensor.z};
                };
                accel_sensor.onactivate = () => {
                };
                accel_sensor.start();*/
                orientation_sensor = new AbsOriSensor();
                orientation_sensor.onreading = () => {
                        let roll = orientation_sensor.roll;
                        let pitch = orientation_sensor.pitch;
                        let yaw = orientation_sensor.yaw;
                        time = orientation_sensor.timestamp;
                        if(!initialoriobtained) //obtain initial orientation
                        {
                                oriInitial = {"roll:": orientation_sensor.roll, "pitch:": orientation_sensor.pitch, "yaw:": orientation_sensor.yaw, "time": orientation_sensor.timestamp};
                                initialoriobtained = true;
                        }
                        ori = {"roll:": orientation_sensor.roll, "pitch:": orientation_sensor.pitch, "yaw:": orientation_sensor.yaw, "time": orientation_sensor.timestamp};
                };
                orientation_sensor.onactivate = () => {
                };
                orientation_sensor.start();
                }
                catch(err) {
                        console.log(err.message);
                        console.log("Your browser doesn't seem to support generic sensors. If you are running Chrome, please enable it in about:flags.");
                        //this.innerHTML = "Your browser doesn't seem to support generic sensors. If you are running Chrome, please enable it in about:flags";
                }
	        //var options = {mimeType: 'video/webm;codecs=vp9'};
		//mediaRecorder = new MediaRecorder(stream, options);
		mediaRecorder = new MediaRecorder(stream);

	        mediaRecorder.start(10);

	        var url = window.URL;
	        videoElement.src = url ? url.createObjectURL(stream) : stream;
                //videoElement.play();

	        mediaRecorder.ondataavailable = function(e) {
                        //console.log("Data available", e);
                        //console.log(time);
                        timestamps.push(time);
                        frameData.time = time;
		        chunks.push(e.data);
                        frameData.data = e.data;
                        orientationData.push(ori);
                        frameData.ori = ori;
                        var b = new Object;     //need to push by value
                        Object.assign(b, frameData);
                        dataArray.push(b);
	        };

	        mediaRecorder.onerror = function(e){
		        console.log('Error: ', e);
	        };

	        mediaRecorder.onstart = function(){
                        console.log("Recording started", mediaRecorder.state);
	        };

	        mediaRecorder.onstop = function(){
		        var blob = new Blob(chunks, {type: "video/webm"});
		        chunks = [];

		        var videoURL = window.URL.createObjectURL(blob);

		        videoElement.src = videoURL;
                        videoElement.load();

                        //resize canvas
videoElement.addEventListener('loadedmetadata', function() {
  canvas.width = videoElement.videoWidth;
  canvas.height = videoElement.videoHeight;
});

                        /*//Read blob data so we can stabilize the video
                        var reader = new FileReader();
                         reader.onload = function(event){
                                let text = reader.result;
                                console.log(text);
                          };
                        reader.readAsText(blob, "video/webm");*/
                        //console.log(orientationData);
                        //console.log(timestamps);
                        //console.log(dataArray);
/*
var blobUrl = URL.createObjectURL(blob);
var x = new XMLHttpRequest();
// set x.responseType = 'blob' if you want to get a Blob object:
// x.responseType = 'blob';
x.onload = function() {
    alert(x.responseText);
};
console.log(x.open('get', blobUrl));*/
                        readFrameData(blob, orientationData);    //reads the video into dataArray2
                        videoElement.onended = function() {
                                alert("The video has ended");
                                cancelAnimationFrame(ref);
                        };
                        //ctx.clearRect(0, 0, canvas.width, canvas.height);
                        //stabilize(dataArray2);        //now we can operate on it
                        //interval=window.setInterval(stabilize,20);
	        };

	        mediaRecorder.onpause = function(){
	        }

	        mediaRecorder.onresume = function(){
	        }

	        mediaRecorder.onwarning = function(e){
	        };
}

function stopRecording(){
	mediaRecorder.stop();
        //Now stabilize
	videoElement.controls = true;
}
//Idea: copy video to canvas, operate on the video, and then use the canvas with the stabilized video as source for the video element
function readFrameData(blob, oriArray) {     //Read video data from blob to object form with pixel data we can operate on
        //console.log(orientationData);
        //console.log(oriInitial);
        //console.log(timestamps[nFrame] - timestamps[0], videoElement.currentTime);
        //while(!videoElement.ended)
        //{
                let x = 0;
                let y = 0;
                let widthR = 100;
                let heightR = 100;
                let ori = orientationData[nFrame];
                let oriDiff = {"roll": ori.roll-oriInitial.roll, "pitch": ori.pitch-oriInitial.pitch, "yaw": ori.yaw-oriInitial.yaw};
                ctx.drawImage(videoElement,0,0, videoElement.videoWidth, videoElement.videoHeight);
                ctx.beginPath();
                ctx.rect(x,y,widthR,heightR);
                ctx.stroke();

                //ctx.drawImage(videoElement, 0, 0);
                let imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
                let pixeldataArray = [];
                //loop through every pixel
                for(let i=0; i<imageData.data.length; i = i+4)
                {
                        let pixeldata = {"red": imageData.data[i], "green":imageData.data[i+1], "blue": imageData.data[i+2], "alpha":imageData.data[i+3]};
                        //pixeldataArray.push(pixeldata);
                }
                //pixeldataArray.push(imageData);
                //if(nFrame < dataArray.length) {
                        let timestamp = dataArray[nFrame].time;
                        let frameData2 = {"imagedata": imageData, "time": timestamp, "oridiff": oriDiff};
                        //var b = new Object;     //need to push by value
                        //Object.assign(b, frameData2);
                        //dataArray2.push(b);
                        dataArray2.push(frameData2);
                        //console.log(pixeldataArray);
                        //newImageData.data = data;
                    // Draw the pixels onto the visible canvas
                    //ctx.putImageData(newImageData,0,0);
                        //xD
                        nFrame = nFrame + 1;
                //}
        //}
        if(dataArray2.length === timestamps.length)     //now we have read the whole blob - should use callback here instead of if condition
        {
                console.log("ended");
                cancelAnimationFrame(ref);
                console.log(dataArray2);
                stabilize(dataArray2);
        }
        ref = requestAnimationFrame(readFrameData);
}

function stabilize(dataArrayArg) { //Create a stabilized video from the pixel data given as input
        let frame = dataArrayArg[0];      //first frame
        console.log(frame);
        //ctx.drawImage(frame.imagedata,0,0, videoElement.videoWidth, videoElement.videoHeight);
        ctx.putImageData(frame.imagedata, 0, 0);
}
<commit_msg>Combine sensor data, video data and timestamp<commit_after>/*
 * Websensor video stabilization project
 * https://github.com/jessenie-intel/websensor-video
 *
 * Copyright (c) 2017 Jesse Nieminen
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
*/

'use strict';

var constraints = {audio: true,video: {  width: { min: 640, ideal: 640, max: 640 },  height: { min: 480, ideal: 480, max: 480 }}};
var mediaRecorder = null;
var chunks = [];
var videoData = null;
var interval = null;

var accel_sensor = null;
var orientation_sensor = null;
var sensorfreq = 60;

//var roll = null;
//var pitch = null;
//var yaw = null;
var accel = {"x": null, "y": null, "z": null};
var ori = {"roll": null, "pitch": null, "yaw": null, "time": null};
var oriInitial = {"roll": null, "pitch": null, "yaw": null, "time": null};
var initialoriobtained = false;
var orientationData = [];       //array to store all the orientation data
var frameData = {"data": null, "time": null, "ori": null};
var dataArray = [];     //array to store all the combined data
var dataArray2 = [];     //array to store all the combined data

var time = null;
var timestamps = [];
var nFrame = 0; //frame number with which we can combine timestamp and frame data

//canvas
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');

//video element
var videoElement = document.querySelector('video');
videoElement.controls = false;

var ref = null;

class AbsOriSensor {
        constructor() {
        const sensor = new AbsoluteOrientationSensor({ frequency: sensorfreq });
        const mat4 = new Float32Array(16);
        const euler = new Float32Array(3);
        sensor.onreading = () => {
                sensor.populateMatrix(mat4);
                toEulerianAngle(sensor.quaternion, euler);      //From quaternion to Eulerian angles
                this.roll = euler[0];
                this.pitch = euler[1];
                this.yaw = euler[2];
                this.timestamp = sensor.timestamp;
                if (this.onreading) this.onreading();
        };
        sensor.onactivate = () => {
                if (this.onactivate) this.onactivate();
        };
        const start = () => sensor.start();
        Object.assign(this, { start });
        }
}

//WINDOWS 10 HAS DIFFERENT CONVENTION: Yaw z, pitch x, roll y
function toEulerianAngle(quat, out)
{
        const ysqr = quat[1] ** 2;

        // Roll (x-axis rotation).
        const t0 = 2 * (quat[3] * quat[0] + quat[1] * quat[2]);
        const t1 = 1 - 2 * (ysqr + quat[0] ** 2);
        out[0] = Math.atan2(t0, t1);
        // Pitch (y-axis rotation).
        let t2 = 2 * (quat[3] * quat[1] - quat[2] * quat[0]);
        t2 = t2 > 1 ? 1 : t2;
        t2 = t2 < -1 ? -1 : t2;
        out[1] = Math.asin(t2);
        // Yaw (z-axis rotation).
        const t3 = 2 * (quat[3] * quat[2] + quat[0] * quat[1]);
        const t4 = 1 - 2 * (ysqr + quat[2] ** 2);
        out[2] = Math.atan2(t3, t4);
        return out;
}

function errorCallback(error){
	console.log("error: ", error);
}

function startDemo () {
		navigator.getUserMedia(constraints, startRecording, errorCallback);
}

function startRecording(stream) {

                try {
                //Initialize sensors
                /*accel_sensor = new Accelerometer();
                accel_sensor.onreading = () => {
                        accel = {"x": accel_sensor.x, "y": accel_sensor.y, "z": accel_sensor.z};
                };
                accel_sensor.onactivate = () => {
                };
                accel_sensor.start();*/
                orientation_sensor = new AbsOriSensor();
                orientation_sensor.onreading = () => {
                        let roll = orientation_sensor.roll;
                        let pitch = orientation_sensor.pitch;
                        let yaw = orientation_sensor.yaw;
                        time = orientation_sensor.timestamp;
                        if(!initialoriobtained) //obtain initial orientation
                        {
                                oriInitial = {"roll": orientation_sensor.roll, "pitch": orientation_sensor.pitch, "yaw": orientation_sensor.yaw, "time": orientation_sensor.timestamp};
                                initialoriobtained = true;
                        }
                        ori = {"roll:": orientation_sensor.roll, "pitch:": orientation_sensor.pitch, "yaw:": orientation_sensor.yaw, "time": orientation_sensor.timestamp};
                };
                orientation_sensor.onactivate = () => {
                };
                orientation_sensor.start();
                }
                catch(err) {
                        console.log(err.message);
                        console.log("Your browser doesn't seem to support generic sensors. If you are running Chrome, please enable it in about:flags.");
                        //this.innerHTML = "Your browser doesn't seem to support generic sensors. If you are running Chrome, please enable it in about:flags";
                }
	        //var options = {mimeType: 'video/webm;codecs=vp9'};
		//mediaRecorder = new MediaRecorder(stream, options);
		mediaRecorder = new MediaRecorder(stream);

	        mediaRecorder.start(10);

	        var url = window.URL;
	        videoElement.src = url ? url.createObjectURL(stream) : stream;
                //videoElement.play();

	        mediaRecorder.ondataavailable = function(e) {
                        //console.log("Data available", e);
                        //console.log(time);
                        timestamps.push(time);
                        frameData.time = time;
		        chunks.push(e.data);
                        frameData.data = e.data;
                        orientationData.push(ori);
                        frameData.ori = ori;
                        var b = new Object;     //need to push by value
                        Object.assign(b, frameData);
                        dataArray.push(b);
	        };

	        mediaRecorder.onerror = function(e){
		        console.log('Error: ', e);
	        };

	        mediaRecorder.onstart = function(){
                        console.log("Recording started", mediaRecorder.state);
	        };

	        mediaRecorder.onstop = function(){
		        var blob = new Blob(chunks, {type: "video/webm"});
		        chunks = [];

		        var videoURL = window.URL.createObjectURL(blob);

		        videoElement.src = videoURL;
                        videoElement.load();

                        //resize canvas
videoElement.addEventListener('loadedmetadata', function() {
  canvas.width = videoElement.videoWidth;
  canvas.height = videoElement.videoHeight;
});

                        /*//Read blob data so we can stabilize the video
                        var reader = new FileReader();
                         reader.onload = function(event){
                                let text = reader.result;
                                console.log(text);
                          };
                        reader.readAsText(blob, "video/webm");*/
                        //console.log(orientationData);
                        //console.log(timestamps);
                        //console.log(dataArray);
/*
var blobUrl = URL.createObjectURL(blob);
var x = new XMLHttpRequest();
// set x.responseType = 'blob' if you want to get a Blob object:
// x.responseType = 'blob';
x.onload = function() {
    alert(x.responseText);
};
console.log(x.open('get', blobUrl));*/
                        readFrameData(blob, orientationData);    //reads the video into dataArray2
                        videoElement.onended = function() {
                                alert("The video has ended");
                                cancelAnimationFrame(ref);
                        };
                        //ctx.clearRect(0, 0, canvas.width, canvas.height);
                        //stabilize(dataArray2);        //now we can operate on it
                        //interval=window.setInterval(stabilize,20);
	        };

	        mediaRecorder.onpause = function(){
	        }

	        mediaRecorder.onresume = function(){
	        }

	        mediaRecorder.onwarning = function(e){
	        };
}

function stopRecording(){
	mediaRecorder.stop();
        //Now stabilize
	videoElement.controls = true;
}
//Idea: copy video to canvas, operate on the video, and then use the canvas with the stabilized video as source for the video element
function readFrameData(blob, oriArray) {     //Read video data from blob to object form with pixel data we can operate on
        //console.log(orientationData);
        //console.log(oriInitial);
        //console.log(timestamps[nFrame] - timestamps[0], videoElement.currentTime);
        //while(!videoElement.ended)
        //{
                let x = 0;
                let y = 0;
                let widthR = 100;
                let heightR = 100;
                let ori = orientationData[nFrame];
                let oriDiff = {"roll": ori.roll-oriInitial.roll, "pitch": ori.pitch-oriInitial.pitch, "yaw": ori.yaw-oriInitial.yaw};
                ctx.drawImage(videoElement,0,0, videoElement.videoWidth, videoElement.videoHeight);
                ctx.beginPath();
                ctx.rect(x,y,widthR,heightR);
                ctx.stroke();

                //ctx.drawImage(videoElement, 0, 0);
                let imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
                let pixeldataArray = [];
                //loop through every pixel
                for(let i=0; i<imageData.data.length; i = i+4)
                {
                        let pixeldata = {"red": imageData.data[i], "green":imageData.data[i+1], "blue": imageData.data[i+2], "alpha":imageData.data[i+3]};
                        //pixeldataArray.push(pixeldata);
                }
                //pixeldataArray.push(imageData);
                //if(nFrame < dataArray.length) {
                        let timestamp = dataArray[nFrame].time;
                        let frameData2 = {"imagedata": imageData, "time": timestamp, "oridiff": oriDiff};
                        //var b = new Object;     //need to push by value
                        //Object.assign(b, frameData2);
                        //dataArray2.push(b);
                        dataArray2.push(frameData2);
                        //console.log(pixeldataArray);
                        //newImageData.data = data;
                    // Draw the pixels onto the visible canvas
                    //ctx.putImageData(newImageData,0,0);
                        //xD
                        nFrame = nFrame + 1;
                //}
        //}
        if(dataArray2.length === timestamps.length)     //now we have read the whole blob - should use callback here instead of if condition
        {
                console.log("ended");
                cancelAnimationFrame(ref);
                console.log(dataArray2);
                stabilize(dataArray2);
        }
        ref = requestAnimationFrame(readFrameData);
}

function stabilize(dataArrayArg) { //Create a stabilized video from the pixel data given as input
        let frame = dataArrayArg[0];      //first frame
        console.log(frame);
        //ctx.drawImage(frame.imagedata,0,0, videoElement.videoWidth, videoElement.videoHeight);
        ctx.putImageData(frame.imagedata, 0, 0);
}
<|endoftext|>


<commit_before>/*jshint multistr: true */

/*
 * Load Map
**/

// Load tiles
var world = L.tileLayer('http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
    attribution: 'Esri',
    maxZoom: 9
});

var wind = L.tileLayer('http://{s}.tile.openweathermap.org/map/wind/{z}/{x}/{y}.png', {
    attribution: 'OpenWeatherMap',
    opacity: 0.5
});

// Create map
var map = L.map('map', {
    layers: [world],
});
map.fitBounds([[28.11, -80.74], [42.20, -9.54]]); // Show whole north atlantic ocean at first

// Add GitHub page to the attribution
map.attributionControl.options.prefix += ' | Source Code';

// Add the optional layers to a selection control
L.control.layers(undefined, {
    "Wind": wind
}).addTo(map);

// Load icons
var icons = {
    // past location
    point: L.icon({
        iconUrl: 'img/point.svg',
        iconSize: [9, 9]
    }),

    // current location
    boat: L.icon({
        iconUrl: 'img/boat.svg',
        iconSize: [16, 16]
    })
};

// Create data layer and add polyline to it
var polyline = L.polyline([], {
    color: 'white',
    opacity: 0.2,
    lineCap: 'butt',
    weight: 2
});
var data_layer = L.featureGroup([polyline]);

/*
 * Retrieve charger location data.
 * I am using YQL as a proxy because the noaa server does not allow cross-server requests.
**/
// ID ESN MONTH DAY HOUR MINUTE DECIMAL_DATE LONGITUDE LATITUDE ? ?
var data_url = 'http://www.nefsc.noaa.gov/drifter/drift_ep_2014_1.dat';
var yql_query = 'SELECT * FROM csv WHERE url="' + data_url + '"';
var yql_url = 'http://query.yahooapis.com/v1/public/yql?q=' + encodeURIComponent(yql_query) + '&format=json';

var boat_esn = '995094'; // ID of the boat
var current_time = moment();

var raw_data = []; // This will be populated with the raw data
var processed_data = []; // This will be populated with the data that has been processed

var stats = {
    launch_date: 0,
    last_date: 0,
    logged_duration: moment.duration(0),
    real_duration: moment.duration(0),
    distance: 0,
    average_speed: 0,
    last_24h: {
        distance: 0,
        average_speed: 0
    }
};

// Download data
new Ajax.Request(yql_url, {
    method: 'get',
    onSuccess: function(transport){
        // Split downloaded data into a list
        transport.responseJSON.query.results.row.each(function(row, i){
            split_row = row.col0.replace(/\s+/g, ' ').replace(/(^\s|\s$)/g, '').split(' ');

            // Filter out points from previous launches
            if (split_row[1] == boat_esn) raw_data.push(split_row);
        });

        // Process the data into usable variables
        var year = 2014; // Keep track of the point's year, as it is not in the raw data
        raw_data.each(function(raw_point, i){
            // Increment year if the last waypoint's decimal date is larger than this
            if (i > 0 && parseFloat(raw_data[i-1][6]) > parseFloat(raw_data[i][6])) year++;

            var point = processed_data[i] = {
                latitude:  parseFloat(raw_point[8]),
                longitude: parseFloat(raw_point[7]),
                date:      moment("{0}/{1}/{2} {3}:{4}".format(year, raw_point[2], raw_point[3], raw_point[4], raw_point[5])),
                isLatest:  i === raw_data.length - 1,
                isFirst:   i === 0,
                previous:  processed_data[i-1],
                next:      undefined
            };

            point.latLng = L.latLng(point.latitude, point.longitude);
            if (!point.isFirst) point.previous.next = point;
            point.time_ago = moment.duration(current_time.diff(point.date));
        });

        // Analyse the data
        processed_data.reverse(false).each(function(point, i) {
            /*
             *  Fill up launch date and last date
             */
            if (point.isFirst)       stats.launch_date = point.date;
            else if (point.isLatest) stats.last_date   = point.date;

            /*
             *  Calculate deltas from last point, if this is not the first
             */
            point.distance_delta = point.isFirst ? 0: point.latLng.distanceTo(point.previous.latLng)/1000;
            point.time_delta = point.isFirst ? moment.duration(0): moment.duration(point.date.diff(point.previous.date));
            point.average_speed  = point.isFirst ? 0: kph_to_knots(point.distance_delta/point.time_delta.asHours());

            /*
             *  Increment global stats
             */
            stats.distance += point.distance_delta;
            stats.logged_duration.add(point.time_delta);

            /*
             *  Calculate last 24h stats
             */

            // If this point was in the last 24h
            if (point.time_ago.asHours() <= 24)
            {
                stats.last_24h.distance += point.distance_delta;
            }
            // If the next point was in the last 24h
            else if (point.next.time_ago.asHours() <= 24)
            {
                stats.last_24h.distance += (1-(24/point.time_ago.asHours()))*point.distance_delta;
            }
        });
        /*
         *  Calculate remaining stats
         */
        stats.real_duration = moment.duration(current_time.diff(stats.launch_date));
        stats.average_speed = kph_to_knots(stats.distance/stats.logged_duration.asHours());
        stats.last_24h.average_speed = kph_to_knots(stats.last_24h.distance/24);

        // Create markers
        processed_data.each(function(point, i) {
            var pointMarker = L.marker(point.latLng, {
                // The marker will be a little boat if it's the latest point
                icon: (point.isLatest) ? icons.boat: icons.point
            });

            // Add info to a popup
            pointMarker.bindPopup(
                'Date: ' + point.date.format("DD-MM-YYYY HH:mm") + '
' +
                (point.isFirst ? '': 'Average Speed: ' + point.average_speed.round(2) + ' knots
') +
                'Coordinates: ' + point.latitude + '°, ' + point.longitude + '°'
            );

            // Add point to polyline and data layer
            polyline.addLatLng(point.latLng);
            data_layer.addLayer(pointMarker);
        });

        // Add stats to the map
        var legend = L.control({position: 'bottomleft'});
        legend.onAdd = function (map){
            var div = L.DomUtil.create('div', 'leaflet-bar info-box');
            div.innerHTML += '\
            Launch date: ' + stats.launch_date.format("DD-MM-YYYY HH:mm") + ' UTC
 \
            Last fix date: ' + stats.last_date.format("DD-MM-YYYY HH:mm") + ' UTC
 \
            Days travelled: ' + stats.real_duration.asDays().round(1) + '
 \
            Distance travelled: ' + stats.distance.round() + ' km
 \
            Average speed ' + stats.average_speed.round(2) + ' knots \

 \
            Distance travelled (last 24h): ' + stats.last_24h.distance.round() + ' km
 \
            Average speed (last 24h) ' + stats.last_24h.average_speed.round(2) + ' knots \
            ';
            return div;
        };
        legend.addTo(map);

        // Fit map to polyline bounds, always showing Lisbon
        var bounds = new L.LatLngBounds([[38.726662, -9.155274], polyline.getBounds().getSouthWest()]);
        map.fitBounds(bounds, {padding: [10, 10]});

        // Add polyline and markers to map, after the map finishes zooming
        map.addOneTimeEventListener('zoomend', function(e) {
            data_layer.addTo(map);
        });
    },

    onFailure: function() {
        alert('There was an error loading the data...');
    },

    // Fix for Prototype sending more headers than it should
    onCreate: function(response) {
        var t = response.transport;
        t.setRequestHeader = t.setRequestHeader.wrap(function(original, k, v) {
            if (/^(accept|accept-language|content-language)$/i.test(k))
                return original(k, v);
            if (/^content-type$/i.test(k) &&
                /^(application\/x-www-form-urlencoded|multipart\/form-data|text\/plain)(;.+)?$/i.test(v))
                return original(k, v);
            return;
        });
    }
});

/*
 * Helper Functions
**/

// String formatting
if (!String.prototype.format) {
  String.prototype.format = function() {
    var args = arguments;
    return this.replace(/{(\d+)}/g, function(match, number) {
      return typeof args[number] != 'undefined' ? args[number] : match;
    });
  };
}

// Round to decimal places
Number.prototype.round = function(places) {
  return !places ? Math.round(this): +(Math.round(this + "e+" + places)  + "e-" + places);
};

// km/h to knots
function kph_to_knots(value)
{
    return value/1.852;
}
<commit_msg>bunch of bug fixes: - last 24h function was reading the wrong objects - boundaries will now adjust properly if the path moves over lisbon's latitude - fixed issue with data not showing up if the map didn't need zooming in after adding the data - fixed issue that appeared when there were no points in the last 24h<commit_after>/*jshint multistr: true */

/*
 * Load Map
**/

// Load tiles
var world = L.tileLayer('http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
    attribution: 'Esri',
    maxZoom: 9
});

var wind = L.tileLayer('http://{s}.tile.openweathermap.org/map/wind/{z}/{x}/{y}.png', {
    attribution: 'OpenWeatherMap',
    opacity: 0.5
});

// Create map
var map = L.map('map', {
    layers: [world],
});
map.fitBounds([[28.11, -80.74], [42.20, -9.54]]); // Show whole north atlantic ocean at first

// Add GitHub page to the attribution
map.attributionControl.options.prefix += ' | Source Code';

// Add the optional layers to a selection control
L.control.layers(undefined, {
    "Wind": wind
}).addTo(map);

// Load icons
var icons = {
    // past location
    point: L.icon({
        iconUrl: 'img/point.svg',
        iconSize: [9, 9]
    }),

    // current location
    boat: L.icon({
        iconUrl: 'img/boat.svg',
        iconSize: [16, 16]
    })
};

// Create data layer and add polyline to it
var polyline = L.polyline([], {
    color: 'white',
    opacity: 0.2,
    lineCap: 'butt',
    weight: 2
});
var data_layer = L.featureGroup([polyline]);

/*
 * Retrieve charger location data.
 * I am using YQL as a proxy because the noaa server does not allow cross-server requests.
**/
// ID ESN MONTH DAY HOUR MINUTE DECIMAL_DATE LONGITUDE LATITUDE ? ?
var data_url = 'http://www.nefsc.noaa.gov/drifter/drift_ep_2014_1.dat';
var yql_query = 'SELECT * FROM csv WHERE url="' + data_url + '"';
var yql_url = 'http://query.yahooapis.com/v1/public/yql?q=' + encodeURIComponent(yql_query) + '&format=json';

var launch_year = 2014;
var boat_esn = '995094'; // ID of the boat

var current_time = moment();

var raw_data = []; // This will be populated with the raw data
var processed_data = []; // This will be populated with the data that has been processed

var stats = {
    launch_date: 0,
    last_date: 0,
    logged_duration: moment.duration(0),
    real_duration: moment.duration(0),
    distance: 0,
    average_speed: 0,
    last_24h: {
        distance: 0,
        average_speed: 0
    }
};

// Download data
new Ajax.Request(yql_url, {
    method: 'get',
    onSuccess: function(transport){
        // Split downloaded data into a list
        transport.responseJSON.query.results.row.each(function(row, i){
            split_row = row.col0.replace(/\s+/g, ' ').replace(/(^\s|\s$)/g, '').split(' ');

            // Filter out points from previous launches
            if (split_row[1] == boat_esn) raw_data.push(split_row);
        });

        // Process the data into usable variables
        var year = launch_year; // Keep track of the point's year, as it is not in the raw data
        raw_data.each(function(raw_point, i){
            // Increment year if the last waypoint's decimal date is larger than this
            if (i > 0 && parseFloat(raw_data[i-1][6]) > parseFloat(raw_data[i][6])) year++;

            var point = processed_data[i] = {
                latitude:  parseFloat(raw_point[8]),
                longitude: parseFloat(raw_point[7]),
                date:      moment("{0}/{1}/{2} {3}:{4}".format(year, raw_point[2], raw_point[3], raw_point[4], raw_point[5])),
                isLatest:  i === raw_data.length - 1,
                isFirst:   i === 0,
                previous:  processed_data[i-1],
                next:      undefined
            };

            point.latLng = L.latLng(point.latitude, point.longitude);
            if (!point.isFirst) point.previous.next = point;
            point.time_ago = moment.duration(current_time.diff(point.date));
        });

        // Analyse the data
        processed_data.reverse(false).each(function(point, i) {
            /*
             *  Fill up launch date and last date
             */
            if (point.isFirst)       stats.launch_date = point.date;
            else if (point.isLatest) stats.last_date   = point.date;

            /*
             *  Calculate deltas from last point, if this is not the first
             */
            point.distance_delta = point.isFirst ? 0: point.latLng.distanceTo(point.previous.latLng)/1000;
            point.time_delta = point.isFirst ? moment.duration(0): moment.duration(point.date.diff(point.previous.date));
            point.average_speed  = point.isFirst ? 0: kph_to_knots(point.distance_delta/point.time_delta.asHours());

            /*
             *  Increment global stats
             */
            stats.distance += point.distance_delta;
            stats.logged_duration.add(point.time_delta);

            /*
             *  Calculate last 24h stats
             */

            // If this point was in the last 24h
            if (point.time_ago.asHours() <= 24)
            {
                stats.last_24h.distance += point.distance_delta;
            }
            // If the next point was in the last 24h
            else if (!point.isFirst && point.previous.time_ago.asHours() <= 24)
            {
                stats.last_24h.distance += (1-(24/point.time_ago.asHours()))*point.distance_delta;
            }
        });
        /*
         *  Calculate remaining stats
         */
        stats.real_duration = moment.duration(current_time.diff(stats.launch_date));
        stats.average_speed = kph_to_knots(stats.distance/stats.logged_duration.asHours());
        stats.last_24h.average_speed = kph_to_knots(stats.last_24h.distance/24);

        // Create markers
        processed_data.each(function(point, i) {
            var pointMarker = L.marker(point.latLng, {
                // The marker will be a little boat if it's the latest point
                icon: (point.isLatest) ? icons.boat: icons.point
            });

            // Add info to a popup
            pointMarker.bindPopup(
                'Date: ' + point.date.format("DD-MM-YYYY HH:mm") + '
' +
                (point.isFirst ? '': 'Average Speed: ' + point.average_speed.round(2) + ' knots
') +
                'Coordinates: ' + point.latitude + '°, ' + point.longitude + '°'
            );

            // Add point to polyline and data layer
            polyline.addLatLng(point.latLng);
            data_layer.addLayer(pointMarker);
        });

        // Add stats to the map
        var legend = L.control({position: 'bottomleft'});
        legend.onAdd = function (map){
            var div = L.DomUtil.create('div', 'leaflet-bar info-box');
            div.innerHTML += '\
            Launch date: ' + stats.launch_date.format("DD-MM-YYYY HH:mm") + ' UTC
 \
            Last fix date: ' + stats.last_date.format("DD-MM-YYYY HH:mm") + ' UTC
 \
            Days travelled: ' + stats.real_duration.asDays().round(1) + '
 \
            Distance travelled: ' + stats.distance.round() + ' km
 \
            Average speed ' + stats.average_speed.round(2) + ' knots \

 \
            Distance travelled (last 24h): ' + stats.last_24h.distance.round() + ' km
 \
            Average speed (last 24h) ' + stats.last_24h.average_speed.round(2) + ' knots \
            ';
            return div;
        };
        legend.addTo(map);

        // Fit map to polyline bounds, always showing Lisbon
        var lisbon_latLng = L.latLng([38.726662, -9.155274]);
        var bounds = polyline.getBounds().extend(lisbon_latLng);
        map.fitBounds(bounds, {padding: [10, 10]});

        // Add polyline and markers to map
        data_layer.addTo(map);
    },

    onFailure: function() {
        alert('There was an error loading the data...');
    },

    // Fix for Prototype sending more headers than it should
    onCreate: function(response) {
        var t = response.transport;
        t.setRequestHeader = t.setRequestHeader.wrap(function(original, k, v) {
            if (/^(accept|accept-language|content-language)$/i.test(k))
                return original(k, v);
            if (/^content-type$/i.test(k) &&
                /^(application\/x-www-form-urlencoded|multipart\/form-data|text\/plain)(;.+)?$/i.test(v))
                return original(k, v);
            return;
        });
    }
});

/*
 * Helper Functions
**/

// String formatting
if (!String.prototype.format) {
  String.prototype.format = function() {
    var args = arguments;
    return this.replace(/{(\d+)}/g, function(match, number) {
      return typeof args[number] != 'undefined' ? args[number] : match;
    });
  };
}

// Round to decimal places
Number.prototype.round = function(places) {
  return !places ? Math.round(this): +(Math.round(this + "e+" + places)  + "e-" + places);
};

// km/h to knots
function kph_to_knots(value)
{
    return value/1.852;
}
<|endoftext|>


<commit_before>
'use strict';

const _ = require('lodash');
const Script = require('smooch-bot').Script;

const scriptRules = require('./script.json');

var myDate = new Date();
var groet = '';

/* hour is before noon */
if ( myDate.getHours() < 12 )
{
groet = "Goeiemorgen";
}
else  /* Hour is from noon to 5pm (actually to 5:59 pm) */
if ( myDate.getHours() >= 12 && myDate.getHours() <= 17 )
{
groet = "Goedendag";
}
else  /* the hour is after 5pm, so it is between 6pm and midnight */
if ( myDate.getHours() > 17 && myDate.getHours() <= 24 )
{
groet = "Goedenavond";
}
else  /* the hour is not between 0 and 24, so something is wrong */
{
groet = "Welkom";
}

function wait(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}

module.exports = new Script({

 processing: {
prompt: (bot) => bot.say('...'),
 receive: () => 'processing'
 },

start: {
    receive: (bot,message) => {
        const opening = message.text;
        return bot.say(`${groet}, waar ben je naar op zoek? %[Starters hypotheek](postback:hypotheektype_starter) %[Nieuwe hypotheek](postback:hypotheektype_nieuw) %[Hypotheek oversluiten](postback:hypotheektype_oversluiten)`)
        .then(() => 'showUserMenu');
    }
},

showUserMenu: {
    receive: (bot, message) => {

      switch(message.text) {
        case 'Hoi':
            return bot.say(`${groet} waar ben je naar op zoek? %[Starters hypotheek](postback:hypotheektype_starter) %[Nieuwe hypotheek](postback:hypotheektype_nieuw) %[Hypotheek oversluiten](postback:hypotheektype_oversluiten)`)
            .then(() => '')
        case 'hoi':
            return bot.say(`${groet} waar ben je naar op zoek? %[Starters hypotheek](postback:hypotheektype_starter) %[Nieuwe hypotheek](postback:hypotheektype_nieuw) %[Hypotheek oversluiten](postback:hypotheektype_oversluiten)`)
            .then(() => '')
        case 'Starters hypotheek':
          return bot.say(`Daar help ik je graag bij. Weet je al wat voor soort woning?`)
            .then(() => bot.say(`%[Appartement](reply:hypotheekkeuze_appartement) %[Tussenwoning](reply:hypotheekkeuze_tussenwoning) %[Vrijstaand](reply:hypotheekkeuze_vrijstaand)`))

          break;
        case 'Nieuwe hypotheek':
          return bot.say(`Helaas biedt Independer momenteel alleen Starters een hypotheek aan.`)
          .then(() => bot.say(`Via onderstaande link kun je de beste hypotheekadviseur voor jou vinden. %[Hypotheek Adviseur](https://www.independer.nl/hypotheekadviseur/intro.aspx)`))
            .then(() => 'processing')
          break;
        case 'Hypotheek oversluiten':
          return bot.say(`Sorry. Momenteel biedt Independer alleen hypotheken aan voor Starters.`)
            .then(() => 'bye')
          break;
        default:
          return bot.say(`hmm...`)
            .then(() => 'processing')
          break;
      }
    }
},

hypotheekkeuze_appartement: {
    prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`),
    receive: () => 'processing'
},
hypotheekkeuze_tussenwoning: {
    prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`),
    receive: () => 'processing'
},
hypotheekkeuze_vrijstaand: {
    prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`),
    receive: () => 'processing'
},
hypotheektype_nieuw: {
    prompt: (bot) => bot.say(`Independer biedt momenteel alleen voor Starters een hypotheek. Onderstaande link bied je meer informatie %[Hypotheek Adviseur](https://www.independer.nl/hypotheekadviseur/intro.aspx)`),
    receive: () => 'bye'
},

bye: {
    prompt: (bot) => bot.say('Bedankt voor je tijd'),
    receive: () => 'processing'
},

doorVragen: {
    prompt: (bot) => bot.say('Postback is working. What\'s your name?'),
    receive: (bot, message) => {
        const name = message.text;
        return bot.setProp('name', name)
            .then(() => bot.say(`Great! I\'ll call you ${name}`))
            .then(()=> bot.say('Is that OK? %[Yes](postback:yes) %[No](postback:nee)'))
            .then(() => 'speak');
    }
},

// error: {
// prompt: (bot) => bot.say('Sorry - kun je dat nog eens zeggen?  Er ging iets mis...'),
// receive: () => ''
// },

finish: {
receive: () => 'finish'
},

  speak: {
          receive: (bot, message) => {

              let upperText = message.text.trim().toUpperCase();

              function updateSilent() {
                  switch (upperText) {
                      case "CONNECT ME":
                          return bot.setProp("silent", true);
                      case "DISCONNECT":
                          return bot.setProp("silent", false);
                      default:
                          return Promise.resolve();
                  }
              }

              function getSilent() {
                  return bot.getProp("silent");
              }

              function processMessage(isSilent) {
                  if (isSilent) {
                      return Promise.resolve("speak");
                  }

                  if (!_.has(scriptRules, upperText)) {
                      return bot.say(`So, I'm good at structured conversations but stickers, emoji and sentences still confuse me. Say 'more' to chat about something else.`).then(() => 'speak');
                  }

                  var response = scriptRules[upperText];
                  var lines = response.split('\n');

                  var p = Promise.resolve();
                  _.each(lines, function(line) {
                      line = line.trim();
                      p = p.then(function() {
                          console.log(line);
                          return wait(50).then(function() {
                              return bot.say(line);
                          });
                      });
                  });

                  return p.then(() => 'speak');
              }

              return updateSilent()
                  .then(getSilent)
                  .then(processMessage);
          }
      }
});
<commit_msg>as<commit_after>
'use strict';

const _ = require('lodash');
const Script = require('smooch-bot').Script;

const scriptRules = require('./script.json');

var myDate = new Date();
var groet = '';

/* hour is before noon */
if ( myDate.getHours() < 12 )
{
groet = "Goeiemorgen";
}
else  /* Hour is from noon to 5pm (actually to 5:59 pm) */
if ( myDate.getHours() >= 12 && myDate.getHours() <= 17 )
{
groet = "Goedendag";
}
else  /* the hour is after 5pm, so it is between 6pm and midnight */
if ( myDate.getHours() > 17 && myDate.getHours() <= 24 )
{
groet = "Goedenavond";
}
else  /* the hour is not between 0 and 24, so something is wrong */
{
groet = "Welkom";
}

function wait(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}

module.exports = new Script({

 processing: {
prompt: (bot) => bot.say('...'),
 receive: () => 'processing'
 },

start: {
    receive: (bot,message) => {
        const opening = message.text;
        return bot.say(`${groet}, waar ben je naar op zoek? %[Starters hypotheek](postback:hypotheektype_starter) %[Nieuwe hypotheek](postback:hypotheektype_nieuw) %[Hypotheek oversluiten](postback:hypotheektype_oversluiten)`)
        .then(() => 'showUserMenu');
    }
},

showUserMenu: {
    receive: (bot, message) => {

      switch(message.text) {
        case 'Hoi':
            return bot.say(`${groet} waar ben je naar op zoek? %[Starters hypotheek](postback:hypotheektype_starter) %[Nieuwe hypotheek](postback:hypotheektype_nieuw) %[Hypotheek oversluiten](postback:hypotheektype_oversluiten)`)
            .then(() => '')
        case 'hoi':
            return bot.say(`${groet} waar ben je naar op zoek? %[Starters hypotheek](postback:hypotheektype_starter) %[Nieuwe hypotheek](postback:hypotheektype_nieuw) %[Hypotheek oversluiten](postback:hypotheektype_oversluiten)`)
            .then(() => '')
        case 'Starters hypotheek':
          return bot.say(`Daar help ik je graag bij. Weet je al wat voor soort woning?`)
            .then(() => bot.say(`%[Appartement](postback:hypotheekkeuze_appartement) %[Tussenwoning](postback:hypotheekkeuze_tussenwoning) %[Vrijstaand](postback:hypotheekkeuze_vrijstaand)`))
            .then(() => 'processing')
          break;
        case 'Nieuwe hypotheek':
          return bot.say(`Helaas biedt Independer momenteel alleen Starters een hypotheek aan.`)
          .then(() => bot.say(`Via onderstaande link kun je de beste hypotheekadviseur voor jou vinden. %[Hypotheek Adviseur](https://www.independer.nl/hypotheekadviseur/intro.aspx)`))
            .then(() => 'processing')
          break;
        case 'Hypotheek oversluiten':
          return bot.say(`Sorry. Momenteel biedt Independer alleen hypotheken aan voor Starters.`)
            .then(() => 'bye')
          break;
        default:
          return bot.say(`hmm...`)
            .then(() => 'processing')
          break;
      }
    }
},

hypotheekkeuze_appartement: {
    prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`),
    receive: () => 'processing'
},
hypotheekkeuze_tussenwoning: {
    prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`),
    receive: () => 'processing'
},
hypotheekkeuze_vrijstaand: {
    prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`),
    receive: () => 'processing'
},
hypotheektype_nieuw: {
    prompt: (bot) => bot.say(`Independer biedt momenteel alleen voor Starters een hypotheek. Onderstaande link bied je meer informatie %[Hypotheek Adviseur](https://www.independer.nl/hypotheekadviseur/intro.aspx)`),
    receive: () => 'bye'
},

bye: {
    prompt: (bot) => bot.say('Bedankt voor je tijd'),
    receive: () => 'processing'
},

doorVragen: {
    prompt: (bot) => bot.say('Postback is working. What\'s your name?'),
    receive: (bot, message) => {
        const name = message.text;
        return bot.setProp('name', name)
            .then(() => bot.say(`Great! I\'ll call you ${name}`))
            .then(()=> bot.say('Is that OK? %[Yes](postback:yes) %[No](postback:nee)'))
            .then(() => 'speak');
    }
},

// error: {
// prompt: (bot) => bot.say('Sorry - kun je dat nog eens zeggen?  Er ging iets mis...'),
// receive: () => ''
// },

finish: {
receive: () => 'finish'
},

  speak: {
          receive: (bot, message) => {

              let upperText = message.text.trim().toUpperCase();

              function updateSilent() {
                  switch (upperText) {
                      case "CONNECT ME":
                          return bot.setProp("silent", true);
                      case "DISCONNECT":
                          return bot.setProp("silent", false);
                      default:
                          return Promise.resolve();
                  }
              }

              function getSilent() {
                  return bot.getProp("silent");
              }

              function processMessage(isSilent) {
                  if (isSilent) {
                      return Promise.resolve("speak");
                  }

                  if (!_.has(scriptRules, upperText)) {
                      return bot.say(`So, I'm good at structured conversations but stickers, emoji and sentences still confuse me. Say 'more' to chat about something else.`).then(() => 'speak');
                  }

                  var response = scriptRules[upperText];
                  var lines = response.split('\n');

                  var p = Promise.resolve();
                  _.each(lines, function(line) {
                      line = line.trim();
                      p = p.then(function() {
                          console.log(line);
                          return wait(50).then(function() {
                              return bot.say(line);
                          });
                      });
                  });

                  return p.then(() => 'speak');
              }

              return updateSilent()
                  .then(getSilent)
                  .then(processMessage);
          }
      }
});
<|endoftext|>


<commit_before>var app = angular.module('app', []);
app.controller('InfoCtrl',[function(){
  console.log('controller has loaded!');
  var self = this;

  self.tiles = [
    { title: 'About', content: 'I enjoy the technical and social - science, art, psychology, sociology - which enhance my creative skills and art. I love working in teams, making products which communicate their use and their purpose well. Looking for work that is both creative and challenging.', picture: '../img/profile.png', tag: 'about'},
    { title: 'Skills', content: 'JavaScript, AngularJS, Ruby, HTML/CSS, Sinatra, the ability to pick things up as quickly as Spidey catches crooks.', picture: 'img/spider-man-60s-cartoon.jpg', tag: 'skills'},
    { title: 'Why Dev?', content: 'After graduating from college, I found myself with an excellent degree but no hard skills. I found work where I could, leveraging my design instincts and work ethic wherever possible. Then I found Dev Bootcamp. I pursued my own education, gathering hard skills in Web Dev. Now I go on, but not unarmed.', picture: 'img/dangerous-to-go.jpg', tag: 'why-dev'},
  ];

  self.finalTile = { title: 'Resumé', content: "Sometimes, people like things on paper. I understand that! You can get a copy of my resumé here!", picture: 'img/resume-card.png', tag: 'resume', link: 'img/resume-ux.pdf'}

  self.education = [
    { institution: 'Dev Bootcamp', major: 'Web Dev Graduate', description: '+1000 hour, 19 week immersive coding boot camp, based in San Francisco.', timePeriod: 'Aug 2014-Jan 2015'},
    { institution: 'Westmont College', major: 'Bachelors of Arts, Communication Studies', description: 'Classical Liberal Arts education, with specific focus on graphics, rhetoric, and marketing.', timePeriod: 'Aug 2008-May 2012'},
    { institution: 'Illustration Academy', major: 'Graduate', description: '3 week illustration intensive program in classical media and graphics.', timePeriod: 'July 2010'},
  ];

  self.experience = [
    { company: 'Dev Bootcamp', position: 'Web Dev Student', timePeriod: 'Aug 2014-Jan 2015' },
    { company: 'PSAV Presentaions', position: 'Presentation Tech, Core Team member', timePeriod: 'April-Aug 2014' },
    { company: 'Cheetah Conservation Fund', position: 'Advertising Rep, Graphic Designer (volunteer)', timePeriod: 'Feb 2014' },
    { company: 'Sur La Table', position: 'Retail Associate, Team Member', timePeriod: 'Nov 2013-Feb 2014' },
  ];

  self.projects = [
    { name: 'Code Crush', description: 'Interactive typing game built in one week as final project for Dev Boot Camp. Created to increase skill and speed in typing symbols and code.', contribution: 'Assets, Front End, Site Design, UX', tech: 'Phaser.io, JavaScript, MongoDB, Express, AngularJS, Node', link:'http://codecrush.herokuapp.com/#/home', repoLink: 'https://github.com/descartez/code-crush'},
    { name: 'Invisible Kingdom', description: 'Story generator which ties randomly generated content to geolocation coordinates.', contribution: 'Content, Functionality, UX', tech: 'Sinatra, ActiveRecord, jQuery, AJAX', link:'http://invisiblekingdom.herokuapp.com/', repoLink: 'https://github.com/descartez/invisiblekingdom'},
    { name: 'algorithm.ic', description: 'A collection of popular algorithms used in coding interviews, and their solutions.', contribution: 'Content', tech: 'n/a', link:'https://github.com/descartez/algorithm.ic', repoLink: 'github.com/descartez/algorithm.ic'},
  ];

}]);
<commit_msg>fixes typos<commit_after>var app = angular.module('app', []);
app.controller('InfoCtrl',[function(){
  console.log('controller has loaded!');
  var self = this;

  self.tiles = [
    { title: 'About', content: 'I enjoy the technical and social - science, art, psychology, sociology - which enhance my creative skills and art. I love working in teams, making products which communicate their use and their purpose well. Looking for work that is both creative and challenging.', picture: '../img/profile.png', tag: 'about'},
    { title: 'Skills', content: 'JavaScript, AngularJS, Ruby, HTML/CSS, Sinatra, the ability to pick things up as quickly as Spidey catches crooks.', picture: 'img/spider-man-60s-cartoon.jpg', tag: 'skills'},
    { title: 'Why Dev?', content: 'After graduating from college, I found myself with an excellent degree but no hard skills. I found work where I could, leveraging my design instincts and work ethic wherever possible. Then I found Dev Bootcamp. I pursued my own education, gathering hard skills in Web Dev. Now I go on, but not unarmed.', picture: 'img/dangerous-to-go.jpg', tag: 'why-dev'},
  ];

  self.finalTile = { title: 'Resumé', content: "Sometimes, people like things on paper. I understand that! You can get a copy of my resumé here!", picture: 'img/resume-card.png', tag: 'resume', link: 'img/resume-ux.pdf'}

  self.education = [
    { institution: 'Dev Bootcamp', major: 'Web Dev Graduate', description: '+1000 hour, 19 week immersive coding boot camp, based in San Francisco.', timePeriod: 'Aug 2014-Jan 2015'},
    { institution: 'Westmont College', major: 'Bachelors of Arts, Communication Studies', description: 'Classical Liberal Arts education, with specific focus on graphics, rhetoric, and marketing.', timePeriod: 'Aug 2008-May 2012'},
    { institution: 'Illustration Academy', major: 'Graduate', description: '3 week illustration intensive program in classical media and graphics.', timePeriod: 'July 2010'},
  ];

  self.experience = [
    { company: 'Dev Bootcamp', position: 'Web Dev Student', timePeriod: 'Aug 2014-Jan 2015' },
    { company: 'PSAV Presentations', position: 'Presentation Tech, Core Team member', timePeriod: 'April-Aug 2014' },
    { company: 'Cheetah Conservation Fund', position: 'Advertising Rep, Graphic Designer (volunteer)', timePeriod: 'Feb 2014' },
    { company: 'Sur La Table', position: 'Retail Associate, Team Member', timePeriod: 'Nov 2013-Feb 2014' },
  ];

  self.projects = [
    { name: 'Code Crush', description: 'Interactive typing game built in one week as final project for Dev Boot Camp. Created to increase skill and speed in typing symbols and code.', contribution: 'Assets, Front End, Site Design, UX', tech: 'Phaser.io, JavaScript, MongoDB, Express, AngularJS, Node', link:'http://codecrush.herokuapp.com/#/home', repoLink: 'https://github.com/descartez/code-crush'},
    { name: 'Invisible Kingdom', description: 'Story generator which ties randomly generated content to geolocation coordinates.', contribution: 'Content, Functionality, UX', tech: 'Sinatra, ActiveRecord, jQuery, AJAX', link:'http://invisiblekingdom.herokuapp.com/', repoLink: 'https://github.com/descartez/invisiblekingdom'},
    { name: 'algorithm.ic', description: 'A collection of popular algorithms used in coding interviews, and their solutions.', contribution: 'Content', tech: 'n/a', link:'https://github.com/descartez/algorithm.ic', repoLink: 'github.com/descartez/algorithm.ic'},
  ];

}]);
<|endoftext|>


<commit_before>/*
 *
 * Asynchronous Modal Dialog Window, a utility which can replace the default JavaScript dialog windows for webpages (alert(), prompt(), confirm())
 *
 * The program integrates 3 elements.
 *
 * ## The first is a global Object named `dialogSettings` that you can use to modify the default behavior of the dialog windows ##
 *
 * __object_key__   __type__   __default_value__       __comment__
 * defType          string     "alert"                 default type
 * defTitle         string     "Message"               default title
 * defContent       string     "Missing text"   default message of the dialog
 * okText           string     "OK"                    default content of the <ok> button
 * continueText     string     "Continue"              default content of the <continue> button
 * cancelText       string     "Cancel"                default content of the <cancel> button
 *
 *
 * ## The second element is the main Function, `dialog()`, which needs the following options, passed with an object as first argument ##
 *
 * __object_key__   __type__   __comment__
 * type             string     type of the dialog window. Possible values are ['alert', 'prompt', 'confirm']
 * title            string     text which will be displayed as the title of the dialog window
 * content          string     message of the dialog window
 * placeholder      string     if the type is 'prompt', this will define a placeholder text for the input box
 * id               string     identifier which can be retrieved afterwards in the `returnObj`, on the callback function
 * vars             Object     object of convenience that will be returned in the `returnObj`, on the callback function
 * callback         Function   function to be called when the dialog window is closed
 *
 *
 * ## The last one is an Object that will be returned in the callback function as first argument, named `returnObj` for convenience of this guide ##
 *
 * __object_key__   __type__   __comment__
 * id               string     identifier passed when calling the `dialog()` function, defaults to undefined
 * vars             Object     same object passed with the function (NB: same reference), defaults to undefined
 * action           boolean    `true` if the user has pressed <ok> or <continue>, `false` for <cancel>
 * value            string     if the type of the requested dialog window was "prompt" it will contain the value inserted in the input box, otherwise it will be undefined
 *
 * ================================================================================================
 *
 * Version: 2.0.1
 * Copyright (c) 2015 Matteo Bernardini
 * Licensed under the MIT License (refer to the LICENSE file for further information).
 *
 * Check this project on GitHub:
 * http://github.com/mttbernardin/dialog
 *
 */

// Backwards compatibility with IE < 9
if (!window.addEventListener) {
	Object.defineProperties(Element.prototype, {
		"addEventListener": {
			value: function(evt, handler, capture) {
				this.attachEvent("on"+evt, handler);
			}
		},
		"removeEventListener": {
			value: function(evt, handler, capture) {
				this.detachEvent("on"+evt, handler);
			}
		},
	});
}

// MAIN FUNCTION //

var dialogSettings = new Object();

function dialog(params) {

	params         = params         || new Object();
	dialogSettings = dialogSettings || new Object();

	// == Default Values == //
	dialogSettings.defTitle     =  dialogSettings.defTitle      ||  "Message";
	dialogSettings.defType      =  dialogSettings.defType       ||  "alert";
	dialogSettings.defContent   =  dialogSettings.defContent    ||  "Missing text";
	dialogSettings.okText       =  dialogSettings.okText        ||  "OK";
	dialogSettings.continueText =  dialogSettings.continueText  ||  "Continue";
	dialogSettings.cancelText   =  dialogSettings.cancelText    ||  "Cancel";

	// == Switch between default values or passed values == //
	params.title    =  params.title    ||  dialogSettings.defTitle;
	params.type     =  params.type     ||  dialogSettings.defType;
	params.content  =  params.content  ||  dialogSettings.defContent;

	// == Creating elements == //
	var struct = {
		"div":     ["window", "wrapper", "title", "body", "message", "prompt", "actions"],
		"button":  ["ok", "cancel"]
	};
	var elms = {};

	for (var i in struct) {
		elms[i] = {};
		for (var j in struct[i]) {
			elms[i][struct[i][j]] = document.createElement(i);
			elms[i][struct[i][j]].className = "dialog-" + struct[i][j];
			if (i === "button") {
				elms[i][struct[i][j]].className += "-button";
				elms[i][struct[i][j]].type = "button";
				elms[i][struct[i][j]].setAttribute("data-action", struct[i][j]);
			}
		}
	}

	var prompt = document.createElement("input");
	prompt.setAttribute("type", "text");
	prompt.className = "dialog-prompt-input";

	// == Arranging elements == //
	elms["div"]["window"].appendChild(elms["div"]["wrapper"]);
	elms["div"]["wrapper"].appendChild(elms["div"]["title"]);
	elms["div"]["wrapper"].appendChild(elms["div"]["body"]);
	elms["div"]["body"].appendChild(elms["div"]["message"]);
	elms["div"]["actions"].appendChild(elms["button"]["ok"]);

	switch (params.type) {
		case "prompt":
			elms["div"]["prompt"].appendChild(prompt);
			elms["div"]["body"].appendChild(elms["div"]["prompt"]);
		case "confirm": // or "prompt", notice no break here
			elms["div"]["actions"].appendChild(elms["button"]["cancel"]);
	}

	elms["div"]["body"].appendChild(elms["div"]["actions"]);

	// == Assigning values == //
	elms["div"]["title"].textContent        =  params.title;
	elms["div"]["message"].textContent      =  params.content;
	elms["button"]["ok"].textContent        =  params.type === "confirm" ? dialogSettings.continueText : dialogSettings.okText;
	elms["button"]["cancel"].textContent    =  dialogSettings.cancelText;
	prompt.placeholder                      =  params.placeholder || "";

	// == Appending to body & focus == //
	var dialogWindow = elms["div"]["window"];
	dialogWindow.setAttribute("data-dialog-type", params.type);

	document.body.appendChild(dialogWindow);

	if (params.type === "prompt")
		prompt.focus();

	// == Adding event listeners == //

	// Will be triggered when closing the dialog
	function action(e, userAction) {
		e = e || window.event;
		var target = e.target ? e.target : e.srcElement;

		if (typeof userAction === "boolean" || target.getAttribute("data-action") === "ok" || target.getAttribute("data-action") === "cancel") {
			document.removeEventListener("keyup", useKeys, false);
			document.body.removeChild(dialogWindow);
			//Callback function if defined
			if (params.callback) {
				var returnObj = {
					id: params.id,
					action: typeof userAction === "boolean" ? userAction : target.getAttribute("data-action") === "ok",
					value: prompt.value,
					vars: params.vars
				};
				params.callback(returnObj);
			}
		}
	}

	// Handler for keyboard events
	function useKeys(e) {
		e = e || window.event;
		if (e.keyCode === 13) // ENTER key
			action(null, true);
		else if (e.keyCode === 27 && params.type !== "alert") // ESC key
			action(null, false);
	}

	document.addEventListener("keyup", useKeys, false);
	elms["div"]["actions"].addEventListener("click", action, false);

}
<commit_msg>Rewritten elements map initialization in a more semantic way.<commit_after>/*
 *
 * Asynchronous Modal Dialog Window, a utility which can replace the default JavaScript dialog windows for webpages (alert(), prompt(), confirm())
 *
 * The program integrates 3 elements.
 *
 * ## The first is a global Object named `dialogSettings` that you can use to modify the default behavior of the dialog windows ##
 *
 * __object_key__   __type__   __default_value__       __comment__
 * defType          string     "alert"                 default type
 * defTitle         string     "Message"               default title
 * defContent       string     "Missing text"   default message of the dialog
 * okText           string     "OK"                    default content of the <ok> button
 * continueText     string     "Continue"              default content of the <continue> button
 * cancelText       string     "Cancel"                default content of the <cancel> button
 *
 *
 * ## The second element is the main Function, `dialog()`, which needs the following options, passed with an object as first argument ##
 *
 * __object_key__   __type__   __comment__
 * type             string     type of the dialog window. Possible values are ['alert', 'prompt', 'confirm']
 * title            string     text which will be displayed as the title of the dialog window
 * content          string     message of the dialog window
 * placeholder      string     if the type is 'prompt', this will define a placeholder text for the input box
 * id               string     identifier which can be retrieved afterwards in the `returnObj`, on the callback function
 * vars             Object     object of convenience that will be returned in the `returnObj`, on the callback function
 * callback         Function   function to be called when the dialog window is closed
 *
 *
 * ## The last one is an Object that will be returned in the callback function as first argument, named `returnObj` for convenience of this guide ##
 *
 * __object_key__   __type__   __comment__
 * id               string     identifier passed when calling the `dialog()` function, defaults to undefined
 * vars             Object     same object passed with the function (NB: same reference), defaults to undefined
 * action           boolean    `true` if the user has pressed <ok> or <continue>, `false` for <cancel>
 * value            string     if the type of the requested dialog window was "prompt" it will contain the value inserted in the input box, otherwise it will be undefined
 *
 * ================================================================================================
 *
 * Version: 2.0.1
 * Copyright (c) 2015 Matteo Bernardini
 * Licensed under the MIT License (refer to the LICENSE file for further information).
 *
 * Check this project on GitHub:
 * http://github.com/mttbernardin/dialog
 *
 */

// Backwards compatibility with IE < 9
if (!window.addEventListener) {
	Object.defineProperties(Element.prototype, {
		"addEventListener": {
			value: function(evt, handler, capture) {
				this.attachEvent("on"+evt, handler);
			}
		},
		"removeEventListener": {
			value: function(evt, handler, capture) {
				this.detachEvent("on"+evt, handler);
			}
		},
	});
}

// MAIN FUNCTION //

var dialogSettings = new Object();

function dialog(params) {

	params         = params         || new Object();
	dialogSettings = dialogSettings || new Object();

	// == Default Values == //
	dialogSettings.defTitle     =  dialogSettings.defTitle      ||  "Message";
	dialogSettings.defType      =  dialogSettings.defType       ||  "alert";
	dialogSettings.defContent   =  dialogSettings.defContent    ||  "Missing text";
	dialogSettings.okText       =  dialogSettings.okText        ||  "OK";
	dialogSettings.continueText =  dialogSettings.continueText  ||  "Continue";
	dialogSettings.cancelText   =  dialogSettings.cancelText    ||  "Cancel";

	// == Switch between default values or passed values == //
	params.title    =  params.title    ||  dialogSettings.defTitle;
	params.type     =  params.type     ||  dialogSettings.defType;
	params.content  =  params.content  ||  dialogSettings.defContent;

	// == Creating elements == //
	var parts = {
	    	"div":     ["window", "wrapper", "title", "body", "message", "prompt", "actions"],
	    	"button":  ["ok", "cancel"]
	    },
	    elms = {};

	for (var elemType in parts) if (parts.hasOwnProperty(elemType)) {
		elms[elemType] = {};
		for (var j = 0, part; part = parts[elemType][j]; j++) {
			elms[elemType][part] = document.createElement(elemType);
			elms[elemType][part].className = "dialog-" + part;
			if (elemType === "button") {
				elms[elemType][part].className += "-button";
				elms[elemType][part].type = "button";
				elms[elemType][part].setAttribute("data-action", part);
			}
		}
	}

	var prompt = document.createElement("input");
	prompt.setAttribute("type", "text");
	prompt.className = "dialog-prompt-input";

	// == Arranging elements == //
	elms["div"]["window"].appendChild(elms["div"]["wrapper"]);
	elms["div"]["wrapper"].appendChild(elms["div"]["title"]);
	elms["div"]["wrapper"].appendChild(elms["div"]["body"]);
	elms["div"]["body"].appendChild(elms["div"]["message"]);
	elms["div"]["actions"].appendChild(elms["button"]["ok"]);

	switch (params.type) {
		case "prompt":
			elms["div"]["prompt"].appendChild(prompt);
			elms["div"]["body"].appendChild(elms["div"]["prompt"]);
		case "confirm": // or "prompt", notice no break here
			elms["div"]["actions"].appendChild(elms["button"]["cancel"]);
	}

	elms["div"]["body"].appendChild(elms["div"]["actions"]);

	// == Assigning values == //
	elms["div"]["title"].textContent        =  params.title;
	elms["div"]["message"].textContent      =  params.content;
	elms["button"]["ok"].textContent        =  params.type === "confirm" ? dialogSettings.continueText : dialogSettings.okText;
	elms["button"]["cancel"].textContent    =  dialogSettings.cancelText;
	prompt.placeholder                      =  params.placeholder || "";

	// == Appending to body & focus == //
	var dialogWindow = elms["div"]["window"];
	dialogWindow.setAttribute("data-dialog-type", params.type);

	document.body.appendChild(dialogWindow);

	if (params.type === "prompt")
		prompt.focus();

	// == Adding event listeners == //

	// Will be triggered when closing the dialog
	function action(e, userAction) {
		e = e || window.event;
		var target = e.target ? e.target : e.srcElement;

		if (typeof userAction === "boolean" || target.getAttribute("data-action") === "ok" || target.getAttribute("data-action") === "cancel") {
			document.removeEventListener("keyup", useKeys, false);
			document.body.removeChild(dialogWindow);
			//Callback function if defined
			if (params.callback) {
				var returnObj = {
					id: params.id,
					action: typeof userAction === "boolean" ? userAction : target.getAttribute("data-action") === "ok",
					value: prompt.value,
					vars: params.vars
				};
				params.callback(returnObj);
			}
		}
	}

	// Handler for keyboard events
	function useKeys(e) {
		e = e || window.event;
		if (e.keyCode === 13) // ENTER key
			action(null, true);
		else if (e.keyCode === 27 && params.type !== "alert") // ESC key
			action(null, false);
	}

	document.addEventListener("keyup", useKeys, false);
	elms["div"]["actions"].addEventListener("click", action, false);

}
<|endoftext|>


<commit_before>var isBlinking = false;
var refreshIntervalId;
function modify_qty(val) {
	if (!isBlinking) {
    var qty = document.getElementById('qty').innerHTML;
    var new_qty = parseInt(qty,10) + val;

	document.getElementById('qtyhis2').innerHTML = document.getElementById('qtyhis1').innerHTML;
	document.getElementById('ctrhis2').innerHTML = document.getElementById('ctrhis1').innerHTML;
	document.getElementById('qtyhis1').innerHTML = document.getElementById('qty').innerHTML;
	document.getElementById('ctrhis1').innerHTML = document.getElementById('ctr').innerHTML;

 document.getElementById('qty').innerHTML = FormatNumberLength(new_qty, 4);
 document.getElementById('ctr').innerHTML = FormatNumberLength(getRandom1to10(),2);
 blinkFiveSec();
	} else {

	}
}

function FormatNumberLength(num, length) {
    var r = "" + num;
    while (r.length < length) {
        r = "0" + r;
    }
    return r;
}

function blink_current_call() {

	  var f = document.getElementById('blink');
   refreshIntervalId = setInterval(function() {

        f.style.visibility = (f.style.visibility == 'hidden' ? '' : 'hidden');
    }, 600);
}

function blinkFiveSec() {
	//blink_current_call();
	 isBlinking = true;
	 blink_current_call();

	var test = setTimeout(stopblink ,6000);
}

function stopblink() {
  clearInterval(refreshIntervalId);
    var f = document.getElementById('blink');
	f.style.visibility = "visible";
  isBlinking = false;
}

function getRandom1to10() {
	var val = Math.floor(Math.random() * 10) + 1;
	return val;
}<commit_msg>Delete script.js<commit_after><|endoftext|>