<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 gyroscope = null;
var sensorfreq = 60;
var selectedSensor = null;

//var roll = null;
//var pitch = null;
//var yaw = null;
var accel = {"x": null, "y": null, "z": null};
var velGyro = {"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;
var extraFrames = 0;

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 });
        }
}

function update_debug()
{
                        document.getElementById("ori").textContent = `${ori.roll} ${ori.pitch} ${ori.yaw}`;
                        document.getElementById("accel").textContent = `${accel.x} ${accel.y} ${accel.z}`;
                        document.getElementById("rrate").textContent = `${velGyro.x} ${velGyro.y} ${velGyro.z}`;
                        document.getElementById("selectedSensor").textContent = `${selectedSensor}`;
}

function selectSensor() {
        selectedSensor = document.getElementById("selectSensor").value;
        console.log(selectedSensor, " selected");
}

//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();
                gyroscope = new Gyroscope();
                gyroscope.onreading = () => {
                        velGyro = {x:gyroscope.x, y:gyroscope.y, z:gyroscope.z};
                };
                gyroscope.onactivate = () => {
                };
                gyroscope.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(update_debug,100);
	        };

	        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("frame");

        nFrame = videoElement.webkitDecodedFrameCount - extraFrames;
        //console.log(videoElement.webkitDecodedFrameCount);      //only works in webkit browsers
        //console.log(timestamps[nFrame] - timestamps[0], videoElement.currentTime);
        //while(!videoElement.ended)
        //{
        let dx = 0;
        let dy = 0;
        let oriDiff = null;
                //videoElement.playbackRate = 0.5;        //fix playback being too fast
                let ori = orientationData[nFrame];
                if(ori !== undefined)
                {
                        oriDiff = {"roll": ori.roll-oriInitial.roll, "pitch": ori.pitch-oriInitial.pitch, "yaw": ori.yaw-oriInitial.yaw};
                        if(selectedSensor === "acceleration")
                        {
                                dx = videoElement.videoWidth*(accel.x/(2*Math.PI));
                                dy = -videoElement.videoHeight*(accel.y/(2*Math.PI));     //each 2pi means 1 video height

                        }
                        else if(selectedSensor === "gyro")
                        {
                                dx = videoElement.videoWidth*(velGyro.x/(2*Math.PI));
                                dy = -videoElement.videoHeight*(velGyro.y/(2*Math.PI));     //each 2pi means 1 video height

                        }
                        else    //orientation - default
                        {
                                dx = videoElement.videoWidth*(oriDiff.yaw/(2*Math.PI));
                                //x = 100*oriDiff.yaw;
                                dy = -videoElement.videoHeight*(oriDiff.roll/(2*Math.PI));     //each 2pi means 1 video height
                                //y = 100*oriDiff.roll;
                        }
                }
                else
                {
                        dx = 0;
                        dy = 0;
                }
                //console.log(x, y);
                let widthR = 0.8*canvas.width;
                let heightR = 0.8*canvas.height;
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                ctx.drawImage(videoElement,0,0, videoElement.videoWidth, videoElement.videoHeight);
                ctx.beginPath();
                ctx.rect(dx+0.1*canvas.width,dy+0.1*canvas.height,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(ori !== undefined) {
                        //let timestamp = dataArray[nFrame].time;
                        //let frameData2 = {"imagedata": imageData, "time": timestamp, "oridiff": oriDiff};
                        //dataArray2.push(frameData2);
                        //console.log(pixeldataArray);
                        //newImageData.data = data;
                    // Draw the pixels onto the visible canvas
                    //ctx.putImageData(newImageData,0,0);
                        //ctx.putImageData(imageData, 0, 0)
                        //xD
                }
        //}
                //nFrame = nFrame + 1;
                ref = requestAnimationFrame(readFrameData);
        /*
        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);
        } */
        if(videoElement.ended)
        {
                console.log("ended");
        }
        if(nFrame >= orientationData.length-1)
        {
                extraFrames = extraFrames + nFrame;
                nFrame = 0;
                //cancelAnimationFrame(ref);
        }
}

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>Sensor init stuff<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 gyroscope = null;
var sensorfreq = 60;
var selectedSensor = null;

//var roll = null;
//var pitch = null;
//var yaw = null;
var accel = {"x": null, "y": null, "z": null};
var velGyro = {"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;
var extraFrames = 0;

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 });
        }
}

function update_debug()
{
                        document.getElementById("ori").textContent = `${ori.roll} ${ori.pitch} ${ori.yaw}`;
                        document.getElementById("accel").textContent = `${accel.x} ${accel.y} ${accel.z}`;
                        document.getElementById("rrate").textContent = `${velGyro.x} ${velGyro.y} ${velGyro.z}`;
                        document.getElementById("selectedSensor").textContent = `${selectedSensor}`;
}

function selectSensor() {
        selectedSensor = document.getElementById("selectSensor").value;
        console.log(selectedSensor, "selected");
}

//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({frequency: sensorfreq, includeGravity: false});
                accel_sensor.onreading = () => {
                        accel = {"x": accel_sensor.x, "y": accel_sensor.y, "z": accel_sensor.z};
                };
                accel_sensor.onactivate = () => {
                };
                accel_sensor.start();
                gyroscope = new Gyroscope({frequency: sensorfreq});
                gyroscope.onreading = () => {
                        velGyro = {x:gyroscope.x, y:gyroscope.y, z:gyroscope.z};
                };
                gyroscope.onactivate = () => {
                };
                gyroscope.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(update_debug,100);
	        };

	        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("frame");

        nFrame = videoElement.webkitDecodedFrameCount - extraFrames;
        //console.log(videoElement.webkitDecodedFrameCount);      //only works in webkit browsers
        //console.log(timestamps[nFrame] - timestamps[0], videoElement.currentTime);
        //while(!videoElement.ended)
        //{
        let dx = 0;
        let dy = 0;
        let oriDiff = null;
                //videoElement.playbackRate = 0.5;        //fix playback being too fast
                let ori = orientationData[nFrame];
                if(ori !== undefined)
                {
                        oriDiff = {"roll": ori.roll-oriInitial.roll, "pitch": ori.pitch-oriInitial.pitch, "yaw": ori.yaw-oriInitial.yaw};
                        if(selectedSensor === "acceleration")
                        {
                                dx = videoElement.videoWidth*(accel.x/(2*Math.PI));
                                dy = -videoElement.videoHeight*(accel.y/(2*Math.PI));     //each 2pi means 1 video height

                        }
                        else if(selectedSensor === "gyro")
                        {
                                dx = videoElement.videoWidth*(velGyro.x/(2*Math.PI));
                                dy = -videoElement.videoHeight*(velGyro.y/(2*Math.PI));     //each 2pi means 1 video height

                        }
                        else    //orientation - default
                        {
                                dx = videoElement.videoWidth*(oriDiff.yaw/(2*Math.PI));
                                //x = 100*oriDiff.yaw;
                                dy = -videoElement.videoHeight*(oriDiff.roll/(2*Math.PI));     //each 2pi means 1 video height
                                //y = 100*oriDiff.roll;
                        }
                }
                else
                {
                        dx = 0;
                        dy = 0;
                }
                //console.log(x, y);
                let widthR = 0.8*canvas.width;
                let heightR = 0.8*canvas.height;
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                ctx.drawImage(videoElement,0,0, videoElement.videoWidth, videoElement.videoHeight);
                ctx.beginPath();
                ctx.rect(dx+0.1*canvas.width,dy+0.1*canvas.height,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(ori !== undefined) {
                        //let timestamp = dataArray[nFrame].time;
                        //let frameData2 = {"imagedata": imageData, "time": timestamp, "oridiff": oriDiff};
                        //dataArray2.push(frameData2);
                        //console.log(pixeldataArray);
                        //newImageData.data = data;
                    // Draw the pixels onto the visible canvas
                    //ctx.putImageData(newImageData,0,0);
                        //ctx.putImageData(imageData, 0, 0)
                        //xD
                }
        //}
                //nFrame = nFrame + 1;
                ref = requestAnimationFrame(readFrameData);
        /*
        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);
        } */
        if(videoElement.ended)
        {
                console.log("ended");
        }
        if(nFrame >= orientationData.length-1)
        {
                extraFrames = extraFrames + nFrame;
                nFrame = 0;
                //cancelAnimationFrame(ref);
        }
}

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>'use strict';

const Script = require('smooch-bot').Script;
const SefzigBot = "[SefzigBot] ";
const LinkBot = "[LinkBot] ";
const TextBot = "[TextBot] ";
const SlackBot = "[SlackBot] ";
const AndreasSefzig = "[AndreasSefzig] ";

module.exports = new Script({
    processing: {
        prompt: (bot) => bot.say(SefzigBot+'Nicht so schnell bitte...'),
        receive: () => 'processing'
    },

    start: {
        receive: (bot) => {
            return bot.say(SefzigBot+'Neues Skript.')
                .then(() => 'register'); /* <-- vorname: automatisches Onboarding */
        }
    },

 // -------------------------
 // Onboarding
 // -------------------------

    vorname: {
        prompt: (bot) => bot.say(SefzigBot+'Wie heissen Sie mit Vornamen?'),
        receive: (bot, message) => {
            var vorname = message.text;
            return bot.setProp('vorname', vorname)
                .then(() => bot.say(SefzigBot+`${vorname}, prima.`))
                .then(() => 'nachname');
        }
    },

    nachname: {
        prompt: (bot) => bot.say(SefzigBot+'Und wie heissen Sie mit Nachnamen?'),
        receive: (bot, message) => {
            var nachname = message.text;
            bot.setProp('nachname', nachname)
            return bot.getProp('vorname')
                .then((vorname) => bot.say(SefzigBot+`Sie heissen ${vorname} ${nachname}, ist das richtig?`))
                .then((vorname) => bot.say(SefzigBot+`Bitte bestätigen Sie, indem Sie --ja oder --nein schreiben!`))
                .then(() => 'name');
        }
    },

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

            var antwort = message.text.trim().toUpperCase();
            var name_falsch = "";
            var dann = "";

            if (antwort == "--JA")   {

               bot.say(SefzigBot+'Sie können hier jederzeit eine Nachricht an Andreas schreiben!');
               bot.say(SefzigBot+'Unterhalten Sie sich mit mir: Bitte schreiben Sie --bot:');
               name_falsch == "nein";
               dann = "register";

            }
            if (antwort == "--NEIN") {

               name_falsch == "ja";
               dann = "vorname";

            }
            if (antwort == "--BOT") {

               name_falsch == "";
               dann = "register";

            }

            return bot.setProp('name_falsch', name_falsch)
                .then(() => dann);
        }
    },

 // -------------------------
 // Register
 // -------------------------

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

            var befehl = message.text.trim().toUpperCase();
            var dann = "register";

         // -----------------
         // Bots
         // -----------------

            if  (~befehl.indexOf("--SLACK"))          { bot.say(SlackBot +'Andreas mag Interne Kommunikation und Automatisierung - er liebt Slack! Das sollte Ihr Team auch tun...');
                                                        bot.say(SlackBot +'(Schreiben Sie --bot, um wieder mit SefzigBot zu sprechen.)');
                                                        bot.say(SlackBot +'Lesen Sie Andreas --Artikel oder --Blogpost, öffnen Sie seine --Links oder treten Sie Andreas offenem Slack --Team bei.');
                                                        dann = "slack"; }

            if (~befehl.indexOf("--EMPFANG"))         { bot.say(EmpfangsBot+'Empfang 1');
                                                        bot.say(EmpfangsBot+'Empfang 2');
                                                        bot.say(EmpfangsBot+'Empfang 3');
                                                        dann = "empfang"; }

         // -----------------
         // System
         // -----------------

            if  (~befehl.indexOf("--BEFEHLE"))        { bot.say(SefzigBot+'--bot '
                                                              +'\n○ --mobil '
                                                              +'\n○ --befehle '
                                                              +'\n○ --abbrechen '); }

            if ((~befehl.indexOf("--BOT")) ||
                (~befehl.indexOf("--UBER")))          { bot.say(SefzigBot+'Ich weiß eine Menge über Andreas - und bin sein Ersatz für eine klassische Webseite. Rufen Sie mein Wissen durch Schreiben der mit -- beginnenden Wörter ab!');
                                                        bot.say(SefzigBot+'Wollen Sie etwas über seine --Person oder --Neues von ihm erfahren? Oder auf anderem Wege --Kontakt  aufnehmen?'); }
            if  (~befehl.indexOf("--ABBRECHEN"))      { bot.say(SefzigBot+'Sie können das Gespräch mit mir beenden'); }
            if  (~befehl.indexOf("--MOBIL"))          { bot.say(SefzigBot+'Diesen Chat mobil öffnen: [Bild:https://zxing.org/w/chart?cht=qr&chs=200x200&chld=L&choe=UTF-8&chl=http%3A%2F%2Fsefzigbot.herokuapp.com%2F]');
                                                        bot.say(SefzigBot+'(Leider werden Sie dort nicht wiedererkannt. Das sollte in einer späteren Version möglich sein...)'); }
            if  (~befehl.indexOf("--NAME"))           { dann = "name"; }

         // -----------------
         // Tests
         // -----------------

            if  (~befehl.indexOf("--JAVASCRIPT"))     { bot.say(SefzigBot+'[Javascript:test_alert]'); }
            if  (~befehl.indexOf("--VIDEO"))          { bot.say(SefzigBot+'[Youtube:u07XONlDwX8]'); }

         // -----------------
         // Vorlage
         // -----------------

            if  (~befehl.indexOf("--VORLAGE"))        { bot.say(SefzigBot+'Text: Vorlage.'); }

         // .then(function(){ bot.say(''); })
            return bot.setProp('register', 'gesprochen')
                .then(() => dann);
        }
    },

 // -------------------------
 // Empfangs-Bot
 // -------------------------

    empfang: {

        receive: (bot, message) => {

         // Befehl normalisieren
            var befehl = message.text.trim().toUpperCase();

         // Nächster Schritt default
            var dann = "empfang";

         // Befehle
            if  (~befehl.indexOf("--BEFEHLE"))        { bot.say(EmpfangsBot +'--Empfang '
                                                              +'\n○ --Folgt '
                                                              +'\n○ --Folgt '
                                                              +'\n○ --Folgt '
                                                              +'\n○ --Folgt '
                                                              +'\n○ --Folgt'); }

            if ((~befehl.indexOf("--AUS")) ||
                (~befehl.indexOf("--ZURÜCK")) ||
                (~befehl.indexOf("--ABBRECHEN")))     { bot.say(EmpfangsBot +'Bis später!');
                                                        dann = "register"; }

         // Inhalte
            if ((~befehl.indexOf("--EMPFANG")) ||
                (~befehl.indexOf("--BEFEHL")))        { bot.say(EmpfangsBot +'Text Befehl.');
                                                        bot.say(EmpfangsBot +'Text Befehl.'); }
         // if  (~befehl.indexOf("--BEFEHL"))         { bot.say(EmpfangsBot +'Text Befehl.'); }

         // Konversation fortführen
            return bot.setProp('empfang', 'gesprochen')
            .then(() => dann);

        }

    },

    finish: {
        receive: (bot, message) => {
            return bot.getProp('name')
                .then(() => 'finish');
        }
    }
});
<commit_msg>slack<commit_after>'use strict';

const Script = require('smooch-bot').Script;
const SefzigBot = "[SefzigBot] ";
const LinkBot = "[LinkBot] ";
const TextBot = "[TextBot] ";
const SlackBot = "[SlackBot] ";
const AndreasSefzig = "[AndreasSefzig] ";

module.exports = new Script({
    processing: {
        prompt: (bot) => bot.say(SefzigBot+'Nicht so schnell bitte...'),
        receive: () => 'processing'
    },

    start: {
        receive: (bot) => {
            return bot.say(SefzigBot+'Neues Skript.')
                .then(() => 'register'); /* <-- vorname: automatisches Onboarding */
        }
    },

 // -------------------------
 // Onboarding
 // -------------------------

    vorname: {
        prompt: (bot) => bot.say(SefzigBot+'Wie heissen Sie mit Vornamen?'),
        receive: (bot, message) => {
            var vorname = message.text;
            return bot.setProp('vorname', vorname)
                .then(() => bot.say(SefzigBot+`${vorname}, prima.`))
                .then(() => 'nachname');
        }
    },

    nachname: {
        prompt: (bot) => bot.say(SefzigBot+'Und wie heissen Sie mit Nachnamen?'),
        receive: (bot, message) => {
            var nachname = message.text;
            bot.setProp('nachname', nachname)
            return bot.getProp('vorname')
                .then((vorname) => bot.say(SefzigBot+`Sie heissen ${vorname} ${nachname}, ist das richtig?`))
                .then((vorname) => bot.say(SefzigBot+`Bitte bestätigen Sie, indem Sie --ja oder --nein schreiben!`))
                .then(() => 'name');
        }
    },

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

            var antwort = message.text.trim().toUpperCase();
            var name_falsch = "";
            var dann = "";

            if (antwort == "--JA")   {

               bot.say(SefzigBot+'Sie können hier jederzeit eine Nachricht an Andreas schreiben!');
               bot.say(SefzigBot+'Unterhalten Sie sich mit mir: Bitte schreiben Sie --bot:');
               name_falsch == "nein";
               dann = "register";

            }
            if (antwort == "--NEIN") {

               name_falsch == "ja";
               dann = "vorname";

            }
            if (antwort == "--BOT") {

               name_falsch == "";
               dann = "register";

            }

            return bot.setProp('name_falsch', name_falsch)
                .then(() => dann);
        }
    },

 // -------------------------
 // Register
 // -------------------------

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

            var befehl = message.text.trim().toUpperCase();
            var dann = "register";

         // -----------------
         // Bots
         // -----------------

            if  (~befehl.indexOf("--SLACK"))          { bot.say(SlackBot +'Andreas mag Interne Kommunikation und Automatisierung - er liebt Slack! Das sollte Ihr Team auch tun...');
                                                        bot.say(SlackBot +'(Schreiben Sie --bot, um wieder mit SefzigBot zu sprechen.)');
                                                        bot.say(SlackBot +'Lesen Sie Andreas --Artikel oder --Blogpost, öffnen Sie seine --Links oder treten Sie Andreas offenem Slack --Team bei.');
                                                        dann = "slack"; }

         // -----------------
         // System
         // -----------------

            if  (~befehl.indexOf("--BEFEHLE"))        { bot.say(SefzigBot+'--bot '
                                                              +'\n○ --mobil '
                                                              +'\n○ --befehle '
                                                              +'\n○ --abbrechen '); }

            if ((~befehl.indexOf("--BOT")) ||
                (~befehl.indexOf("--UBER")))          { bot.say(SefzigBot+'Ich weiß eine Menge über Andreas - und bin sein Ersatz für eine klassische Webseite. Rufen Sie mein Wissen durch Schreiben der mit -- beginnenden Wörter ab!');
                                                        bot.say(SefzigBot+'Wollen Sie etwas über seine --Person oder --Neues von ihm erfahren? Oder auf anderem Wege --Kontakt  aufnehmen?'); }
            if  (~befehl.indexOf("--ABBRECHEN"))      { bot.say(SefzigBot+'Sie können das Gespräch mit mir beenden'); }
            if  (~befehl.indexOf("--MOBIL"))          { bot.say(SefzigBot+'Diesen Chat mobil öffnen: [Bild:https://zxing.org/w/chart?cht=qr&chs=200x200&chld=L&choe=UTF-8&chl=http%3A%2F%2Fsefzigbot.herokuapp.com%2F]');
                                                        bot.say(SefzigBot+'(Leider werden Sie dort nicht wiedererkannt. Das sollte in einer späteren Version möglich sein...)'); }
            if  (~befehl.indexOf("--NAME"))           { dann = "name"; }

         // -----------------
         // Tests
         // -----------------

            if  (~befehl.indexOf("--JAVASCRIPT"))     { bot.say(SefzigBot+'[Javascript:test_alert]'); }
            if  (~befehl.indexOf("--VIDEO"))          { bot.say(SefzigBot+'[Youtube:u07XONlDwX8]'); }

         // -----------------
         // Vorlage
         // -----------------

            if  (~befehl.indexOf("--VORLAGE"))        { bot.say(SefzigBot+'Text: Vorlage.'); }

         // .then(function(){ bot.say(''); })
            return bot.setProp('register', 'gesprochen')
                .then(() => dann);
        }
    },

 // -------------------------
 // Slack
 // -------------------------

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

         // Befehl normalisieren
            var befehl = message.text.trim().toUpperCase();

         // Nächster Schritt default
            var dann = "slack";

         // Befehle
            if  (~befehl.indexOf("--BEFEHLE"))        { bot.say(SlackBot +'--Slack '
                                                              +'\n○ --Über '
                                                              +'\n○ --Artikel '
                                                              +'\n○ --Blogpost '
                                                              +'\n○ --Links '
                                                              +'\n○ --Team'); }
            if ((~befehl.indexOf("--BOT")) ||
                (~befehl.indexOf("--ABBRECHEN")))     { bot.say(SlackBot +'Zurück an Sefzig --Bot. Bis später!');
                                                        dann = "register"; }

         // Inhalte
            if ((~befehl.indexOf("--UBER")) ||
                (~befehl.indexOf("--ÜBER")))          { bot.say(SlackBot +'Slack ist zur Zeit die beste Chat-Anwendung für Teams. Bedienfreundlich, automatisierbar und operationalisierbar. Über Slack wurde Andreas auf #Robogeddon aufmerksam!');
                                                        bot.say(SlackBot +'[Bild:http://sefzig.net/text/seiten/SefzignetSlack/dateien/slack_logo.png]'); }
            if  (~befehl.indexOf("--ARTIKEL"))        { bot.say(SlackBot +'Andreas hat einen fundierten Artikel zu Slack geschrieben: [Text:Slack] Was Sie als Marketer über Slack wissen müssen.'); }
            if  (~befehl.indexOf("--BLOGPOST"))       { bot.say(SlackBot +'Lesen Sie auch Andreas Blogpost zu Slack: [Text:SefzignetBlogSlack] Was ist Slack und wie nutzt man es? '); }
            if  (~befehl.indexOf("--LINKS"))          { bot.say(SlackBot +'Andreas hat viele Artikel zu Slack gesammelt: [Linkliste:Slack;Artikel] '); }
            if  (~befehl.indexOf("--TEAM"))           { bot.say(SlackBot +'Treten Sie dem offenen Slack-Team von Andreas bei, um sich mit ihm zu beraten und um Slack im laufenden Betrieb zu sehen: [Button:Anmeldung,http://sefzig.net/link/SlackAnmeldung/] '); }

         // Konversation fortführen
            return bot.setProp('text', 'gesprochen')
                .then(() => dann);

        }

    },

 // -------------------------
 // Empfangs-Bot
 // -------------------------

    empfang: {

        receive: (bot, message) => {

         // Befehl normalisieren
            var befehl = message.text.trim().toUpperCase();

         // Nächster Schritt default
            var dann = "empfang";

         // Befehle
            if  (~befehl.indexOf("--BEFEHLE"))        { bot.say(EmpfangsBot +'--Empfang '
                                                              +'\n○ --Folgt '
                                                              +'\n○ --Folgt '
                                                              +'\n○ --Folgt '
                                                              +'\n○ --Folgt '
                                                              +'\n○ --Folgt'); }

            if ((~befehl.indexOf("--AUS")) ||
                (~befehl.indexOf("--ZURÜCK")) ||
                (~befehl.indexOf("--ABBRECHEN")))     { bot.say(EmpfangsBot +'Bis später!');
                                                        dann = "register"; }

         // Inhalte
            if ((~befehl.indexOf("--EMPFANG")) ||
                (~befehl.indexOf("--BEFEHL")))        { bot.say(EmpfangsBot +'Text Befehl.');
                                                        bot.say(EmpfangsBot +'Text Befehl.'); }
         // if  (~befehl.indexOf("--BEFEHL"))         { bot.say(EmpfangsBot +'Text Befehl.'); }

         // Konversation fortführen
            return bot.setProp('empfang', 'gesprochen')
            .then(() => dann);

        }

    },

    finish: {
        receive: (bot, message) => {
            return bot.getProp('name')
                .then(() => 'finish');
        }
    }
});
<|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](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`)
            .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'
},

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: () => 'processing'
},

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>pl<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'
},

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>// xx -- review best practices for jquery plugins
( function ( $, window, document, undefined ) {

	// take a row in googl-ese json and return it as name:value pairs
	function rowToObject(cell){

		var returner = {};

		var properties = Object.getOwnPropertyNames(cell);
    // sorting is important for catching numbered properties below
    // name sure the un-numbered name is first
		properties.sort();

		properties.forEach(function(key){

			var val = cell[key].$t;

			// don't bother with empty values
			// which also means properties will not be set for empty values!
			if(val === '') return;

			if(key.substring(0,4) === 'gsx$'){
				var name = key.substr(4);

				// the only tricky thing is to turn the property value into an array
				// if the property name has variations that end in a number
				// Address, Address1, Address2... etc.
				var num = name.charAt(name.length - 1);
				if(/^\d+$/.test(num)){ // indexed propery
					name = name.substr(0, name.length - 1);
					var arr = returner[name];
          // if arr is not an array, but exists its the unnumbered value: ex. Address
          // replace its position with an array and push it in first
					if(!Array.isArray(arr)){
						returner[name] = [];
						if(arr) returner[name].push(arr);
					}
					returner[name].push(val);
				} else returner[name] = val;
			}
		});
		return returner;
	}

	$.googleSheetToJSON = function googleSheetToJSON(id, worksheet){

		var deferred = new $.Deferred();
		var url = [
			'https://spreadsheets.google.com/feeds/list',
			id,
			(worksheet || 'od6'),
			'public/values?alt=json&callback=?'].join('/');

		$.getJSON(url)
			.done(function(data){
				// try to fail w/ info if we cant get any data from the sheets
				if(!data.feed) throw new Error('Unable to retrieve google spreadsheet JSON data for ' + url);
				if(!data.feed.entry) throw new Error('Google spreadsheet seems empty for ' + url);
				deferred.resolve(data.feed.entry.map(rowToObject));
			})
			.fail(deferred.reject);

		return deferred.promise();
	};

} )( jQuery, window, document );
<commit_msg>more comments<commit_after>// xx -- review best practices for jquery plugins
( function ( $, window, document, undefined ) {

	// take a row in googl-ese json and return it as name:value pairs
	function rowToObject(cell){

		var returner = {};

		var properties = Object.getOwnPropertyNames(cell);
    // sorting is important for catching numbered properties below
    // name sure the un-numbered name is first
		properties.sort();

		properties.forEach(function(key){

			var val = cell[key].$t;

			// don't bother with empty values
			// which also means properties will not be set for empty values!
			if(val === '') return;

			if(key.substring(0,4) === 'gsx$'){
				var name = key.substr(4);

				// the only tricky thing is to turn the property value into an array
				// if the property name has variations that end in a number
				// Address, Address1, Address2... etc.
				var num = name.charAt(name.length - 1);
				if(/^\d+$/.test(num)){ // indexed propery
					name = name.substr(0, name.length - 1);
					var arr = returner[name];
          // if arr is not an array, but exists its the unnumbered value: ex. Address
          // replace its position with an array and push it in first
					if(!Array.isArray(arr)){
						returner[name] = [];
						if(arr) returner[name].push(arr);
					}
					returner[name].push(val);
				} else returner[name] = val; // the basic case for a name/value pair
			}
		});
		return returner;
	}

	$.googleSheetToJSON = function googleSheetToJSON(id, worksheet){

		var deferred = new $.Deferred();
		var url = [
			'https://spreadsheets.google.com/feeds/list',
			id,
			(worksheet || 'od6'), // od6 is the default id of the first worksheet
			'public/values?alt=json&callback=?'].join('/');

		$.getJSON(url)
			.done(function(data){
				// try to fail w/ info if we cant get any data from the sheets
				// very errorable these sheets, using a spacer row for instance
				// under the headers and boom! no data. meh.
				if(!data.feed) throw new Error('Unable to retrieve google spreadsheet JSON data for ' + url);
				if(!data.feed.entry) throw new Error('Google spreadsheet seems empty for ' + url);
				deferred.resolve(data.feed.entry.map(rowToObject));
			})
			.fail(deferred.reject);

		return deferred.promise();
	};

} )( jQuery, window, document );
<|endoftext|>


<commit_before>var self,
    clickHandlers = [], // bindet click handlers (for removing them)
    shadow = [],        // shadow copy of children
    visibleButtons,
    _first,             // holds first index
    _last,              // holds last index
    _direction,
    exclusive;

/**
 * prepares the group behavior for that component
 */

function create(that, options) {
    self = that;
    _direction = options.direction || Qt.Horizontal;
    exclusive = self.exclusive|| options.exclusive;
    self.childrenChanged.connect(childrenChanged);
//    self.widthChanged.connect(resizeChildren);
    build();
}

// fun is taken from qt-components
// "duck-typing" to identify the Buttons, find a better way to do it :-P
function isButton(item) {
    if (item && item["__position"] !== undefined)
        return true;
    return false;
}

function hasChecked(item) {
    if (item && item["checked"] !== undefined)
        return true;
    return false;
}

/**
 * Destroy behavior for that component
 */
function destroy() {
    self.childrenChanged.disconnect(childrenChanged);
//    self.widthChanged.disconnect(resizeChildren);
    cleanup();
}

/**
 * prepare the buttongroup
 */
function build() {
    // copy of children because its not an array. also we need a copy
    shadow = [];
    shadow.length = self.children.length;
    visibleButtons = 0;
    _first = undefined;
    _last = 0;
    var isCheckedPresent = false;
    for (var i = 0, item; (item = self.children[i]); i++) {
        if (hasChecked(item)) {
            shadow[i] = item;
            if (item.visible) {
                if (_first === undefined)
                    _first = i;
                _last = i;
                visibleButtons = visibleButtons + 1;
            }
            if (item === self.checkedButton) {
                isCheckedPresent = true;
            }
        }
    }
    if (!isCheckedPresent) {
        self.checkedButton = undefined;
    }

    shadow.forEach(function(item, i) {
        if (isButton(item) ) {
            item.__position = _first===_last ?
                                        "only":
                             _first === i ?
                                        (_direction == Qt.Horizontal ? "leftmost" : "top")  :
                             _last === i ?
                                        (_direction == Qt.Horizontal ? "rightmost" : "bottom") :
                                        (_direction == Qt.Horizontal ? "h_middle": "v_middle"); // middle

            if (self.width > 0) { // fixed: ASGARD-18
                if (_direction == Qt.Vertical) {
                    item.anchors.left = self.left
                    item.anchors.right = self.right
                }
            }
            item.visibleChanged.connect(childrenChanged);
        }
        if (exclusive && hasChecked(item)) {
            if (item["checkable"]!==undefined) {
                item.checkable = true;
            }
            clickHandlers[i] = checkExclusive(item);
            item.clicked.connect(clickHandlers[i]);
        }

    });
}

/**
 * cleanup the buttongroup
 */
function cleanup() {
    shadow.forEach(function(item, i) {
        if (item) {
            if (clickHandlers[i])
                item.clicked.disconnect(clickHandlers[i]);
            if (isButton(shadow[i]))
                item.visibleChanged.disconnect(childrenChanged);
        }
    });
    clickHandlers = [];
}

/**
 * rebuild if buttongroup has changed
 */
function childrenChanged() {
    cleanup();
    build();
}

function resizeChildren() {
    if (_direction != Qt.Horizontal)
        return;

    console.log("resizeChildren");
    var extraPixels = self.width % visibleButtons;
    var buttonSize = (self.width - extraPixels) / visibleButtons;
    shadow.forEach(function(item, i) {
        if (!item || !item.visible)
            return;
        item.width = buttonSize + (extraPixels > 0 ? 1 : 0);
        if (extraPixels > 0)
            extraPixels--;
    });
}

function checkExclusive(item) {
    var button = item;
    return function() {
        for (var i = 0, ref; (ref = shadow[i]); i++) {
            ref.checked = button === ref;
        }
        self.checkedButton = button;
    }
}
<commit_msg>More cleaning on ButtonGroup.js<commit_after>var self;
var clickHandlers = [];
var visibleButtons = [];
var nonVisibleButtons = [];
var direction;
var exclusive;

function create(that, options) {
    self = that;
    direction = options.direction || Qt.Horizontal;
    exclusive = self.exclusive|| options.exclusive;
    self.childrenChanged.connect(rebuild);
//    self.widthChanged.connect(resizeChildren);
    build();
}

function isButton(item) {
    if (item && item["__position"] !== undefined)
        return true;
    return false;
}

function hasChecked(item) {
    if (item && item["checked"] !== undefined)
        return true;
    return false;
}

function destroy() {
    self.childrenChanged.disconnect(rebuild);
//    self.widthChanged.disconnect(resizeChildren);
    cleanup();
}

function build() {
    visibleButtons = [];
    nonVisibleButtons = [];

    for (var i = 0, item; (item = self.children[i]); i++) {
        if (!hasChecked(item))
            continue;

        item.visibleChanged.connect(rebuild); // Not optimal, but hardly a bottleneck in your app
        if (!item.visible) {
            nonVisibleButtons.push(item);
            continue;
        }
        visibleButtons.push(item);

        if (exclusive && hasChecked(item)) {
            if (item["checkable"]!==undefined) {
                item.checkable = true;
            }
            clickHandlers[i] = checkExclusive(item);
            item.clicked.connect(clickHandlers[i]);
        }
    }

    if (self.checkedButton && !self.checkedButton.visible)
        self.checkedButton = undefined;

    var nrButtons = visibleButtons.length;
    if (nrButtons == 0)
        return;

    if (nrButtons == 1) {
        finishButton(visibleButtons[0], "only");
    } else {
        finishButton(visibleButtons[0], direction == Qt.Horizontal ? "leftmost" : "top");
        for (var i = 1; i < nrButtons - 1; i++)
            finishButton(visibleButtons[i], direction == Qt.Horizontal ? "h_middle": "v_middle");
        finishButton(visibleButtons[nrButtons - 1], direction == Qt.Horizontal ? "rightmost" : "bottom");
    }
}

function finishButton(button, position) {
    if (isButton(button)) {
        button.__position = position;
        if (direction == Qt.Vertical) {
            button.anchors.left = self.left
            button.anchors.right = self.right
        }
    }
}

function cleanup() {
    visibleButtons.forEach(function(item, i) {
        if (clickHandlers[i])
            item.clicked.disconnect(clickHandlers[i]);
        item.visibleChanged.disconnect(rebuild);
    });
    clickHandlers = [];

    nonVisibleButtons.forEach(function(item, i) {
        item.visibleChanged.disconnect(rebuild);
    });
}

function rebuild() {
    cleanup();
    build();
}

function resizeChildren() {
    if (direction != Qt.Horizontal)
        return;

    var extraPixels = self.width % visibleButtons;
    var buttonSize = (self.width - extraPixels) / visibleButtons;
    visibleButtons.forEach(function(item, i) {
        if (!item || !item.visible)
            return;
        item.width = buttonSize + (extraPixels > 0 ? 1 : 0);
        if (extraPixels > 0)
            extraPixels--;
    });
}

function checkExclusive(item) {
    var button = item;
    return function() {
        for (var i = 0, ref; (ref = visibleButtons[i]); i++) {
            ref.checked = button === ref;
        }
        self.checkedButton = button;
    }
}
<|endoftext|>


<commit_before>jsio('from base import *');
jsio('import logging');
jsio('from net.interfaces import Protocol');

var logger = logging.getLogger('net.buffer.Buffer');

var EmptyBufferError = exports.EmptyBufferError = Class(function () {
	this.init = function(message) { this.message = message; }
})

exports.Buffer = Class(function(supr) {

	this.init = function(rawBuffer) {

		this._rawBuffer = !!rawBuffer ? rawBuffer : "";
	}

	this.getLength = function() {
		return this._rawBuffer.length;
	}

	this.append = function(data) {
		logger.info('append', JSON.stringify(data));
		this._rawBuffer += data;
	}

	this.peekBytes = function(num) {
		if (!!num)
			return this._rawBuffer.slice(0, num);
		else
			return this._rawBuffer;
	}

	this.peekToDelimiter = function(delimiter) {
		delimiter = delimiter ? delimiter : '\n';
		var i = this._rawBuffer.indexOf(delimiter);
		if (i == -1)
			throw new EmptyBufferError("delimiter " + delmiter + "not present in buffer");
		else
			return this._rawBuffer.slice(0, i);
	}

	this.consumeBytes = function(num) {
		var output = this.peekBytes(num);
		this._rawBuffer = this._rawBuffer.slice(output.length);
		return output;
	}
	this.consumeMaxBytes = function(num) {
		var output = this._rawBuffer.slice(0, num);
		this._rawBuffer = this._rawBuffer(num);
		return output;
	}
	this.consumeAllBytes = function() {
		var temp = this._rawBuffer;
		this._rawBuffer = "";
		return temp;
	}

	this.consumeThroughDelimiter = function(delimiter) {
		return this.consumeToDelimiter(delimiter) + this.consumeBytes(delimiter.length);
	}

	this.consumeToDelimiter = function(delimiter) {
		delimiter = !!delimiter ? delimiter : "\n"
		var output = this.peekToDelimiter(delimiter);
		this._rawBuffer = this._rawBuffer.slice(output.length);
		return output;
	}

	this.hasBytes = function(num) {
		num = num ? num : 0;
		return this._rawBuffer.length >= num;
	}

	this.hasDelimiter = function(delimiter) {
		delimiter = !!delimiter ? delimiter : '\n';
		return (this._rawBuffer.indexOf(delimiter) != -1);
	}

})
<commit_msg>remove spurious logger.info call<commit_after>jsio('from base import *');
jsio('import logging');
jsio('from net.interfaces import Protocol');

var logger = logging.getLogger('net.buffer.Buffer');

var EmptyBufferError = exports.EmptyBufferError = Class(function () {
	this.init = function(message) { this.message = message; }
})

exports.Buffer = Class(function(supr) {

	this.init = function(rawBuffer) {

		this._rawBuffer = !!rawBuffer ? rawBuffer : "";
	}

	this.getLength = function() {
		return this._rawBuffer.length;
	}

	this.append = function(data) {
		logger.debug('append', JSON.stringify(data));
		this._rawBuffer += data;
	}

	this.peekBytes = function(num) {
		if (!!num)
			return this._rawBuffer.slice(0, num);
		else
			return this._rawBuffer;
	}

	this.peekToDelimiter = function(delimiter) {
		delimiter = delimiter ? delimiter : '\n';
		var i = this._rawBuffer.indexOf(delimiter);
		if (i == -1)
			throw new EmptyBufferError("delimiter " + delmiter + "not present in buffer");
		else
			return this._rawBuffer.slice(0, i);
	}

	this.consumeBytes = function(num) {
		var output = this.peekBytes(num);
		this._rawBuffer = this._rawBuffer.slice(output.length);
		return output;
	}
	this.consumeMaxBytes = function(num) {
		var output = this._rawBuffer.slice(0, num);
		this._rawBuffer = this._rawBuffer(num);
		return output;
	}
	this.consumeAllBytes = function() {
		var temp = this._rawBuffer;
		this._rawBuffer = "";
		return temp;
	}

	this.consumeThroughDelimiter = function(delimiter) {
		return this.consumeToDelimiter(delimiter) + this.consumeBytes(delimiter.length);
	}

	this.consumeToDelimiter = function(delimiter) {
		delimiter = !!delimiter ? delimiter : "\n"
		var output = this.peekToDelimiter(delimiter);
		this._rawBuffer = this._rawBuffer.slice(output.length);
		return output;
	}

	this.hasBytes = function(num) {
		num = num ? num : 0;
		return this._rawBuffer.length >= num;
	}

	this.hasDelimiter = function(delimiter) {
		delimiter = !!delimiter ? delimiter : '\n';
		return (this._rawBuffer.indexOf(delimiter) != -1);
	}

})
<|endoftext|>


<commit_before>import path from 'path';

export default function (req, res, { rulesRepository, metaRepository }, { params }) {
  const keyPath = params.splat;

  (async function () {
    const ruleData = await rulesRepository.getRule(keyPath);

    return {
      ruleDef: {
        type: path.extname(keyPath).substring(1),
        source: ruleData.fileContent,
        modificationData: ruleData.fileModificationData,
      },
      meta: await metaRepository.getRuleMeta(keyPath),
    };
  }()).then((x) => res.json(x), console.error.bind(console));
}
<commit_msg>- trying to see myself in the commits dashbord!<commit_after>import path from 'path';

export default function (req, res, { rulesRepository, metaRepository }, { params }) {
  const keyPath = params.splat;
  (async function () {
    const ruleData = await rulesRepository.getRule(keyPath);

    return {
      ruleDef: {
        type: path.extname(keyPath).substring(1),
        source: ruleData.fileContent,
        modificationData: ruleData.fileModificationData,
      },
      meta: await metaRepository.getRuleMeta(keyPath),
    };
  }()).then((x) => res.json(x), console.error.bind(console));
}
<|endoftext|>


<commit_before>var playerName = ['Aさん', 'Bさん', 'Cさん', 'Dさん'];
var PointLeft = [25000, 25000, 25000, 25000];
var jushu = 1; //局数
var changfeng = '东'; //场风
var benchang = 0; //本场数

var rong_flag = [false, false, false, false];
var dianpao_flag = [false, false, false, false];

var mainView = 0; //点差模式下主视角

$(document).ready(
    function () {
        $('input').bind('change', EditPlayerName);
        UpdateUserName();

        $('#myonoffswitch').change(ChangePointShowMode);
        ShowPoint(false);

        UpdateAllView();
    }
);

function UpdateAllView() {
    ChangePointShowMode(); //更新点差显示模式
    UpdateGameProcess(); //更新右上角进度
    UpdateFengwei(); //更新风位
    UpdateRank(); //更新顺位
}

function $q(pattern, idx) { //jQuery辅助函数
    return $(pattern + ":eq(" + idx + ')');
}

function UpdateRank() {

}

function ShowPoint(DiffMode) {
    for (var i = 0; i < 4; i++) {
        if (DiffMode) {
            $('.playerscore', $('.playerinfoarea')[i]).text(PointLeft[i] - PointLeft[mainView] * (i != mainView));
        } else {
            $('.playerscore', $('.playerinfoarea')[i]).text(PointLeft[i]);
        }
    }
}

function UpdateFengwei() //更新风位
{
    $q('.playerpos', (jushu + 3) % 4).text('东');
    $q('.playerpos', (jushu + 4) % 4).text('南');
    $q('.playerpos', (jushu + 5) % 4).text('西');
    $q('.playerpos', (jushu + 6) % 4).text('北');

}

function ChangePointShowMode() {
    $('.playerpos').not(function (id) {
        return id == mainView
    }).removeClass('mainviewcl');
    $q('.playerpos', mainView).addClass('mainviewcl');
    ShowPoint(!$("#myonoffswitch").is(':checked'));
}

function EditPlayerName() {
    for (var i = 0; i < 4; i++) {
        playerName[i] = $('#playerName input')[i].value;
    }
    UpdateUserName();
}

function UpdateUserName() {
    for (var i = 0; i < 4; i++) {
        $("#playerName  input")[i].value = playerName[i];
        $('.playername', $('.playerinfoarea')[i]).text(playerName[i]);
        $('#randpos input')[i].value = playerName[i];
    }
}

function UpdateGameProcess() {
    var chn = ['一', '二', '三', '四'];
    $("#changkuang").text(changfeng + chn[jushu - 1] + '局');
    $("#benchangshu").text(benchang + '本场');
}

//随机换座位
function randomOrder(targetArray) {
    var arrayLength = targetArray.length
    var tempArray1 = new Array();
    for (var i = 0; i < arrayLength; i++) {
        tempArray1[i] = i
    }
    var tempArray2 = new Array();
    for (var i = 0; i < arrayLength; i++) {
        tempArray2[i] = tempArray1.splice(Math.floor(Math.random() * tempArray1.length), 1)
    }
    var tempArray3 = new Array();
    for (var i = 0; i < arrayLength; i++) {
        tempArray3[i] = targetArray[tempArray2[i]]
    }
    return tempArray3
}

function make_random_position() {
    playerName = randomOrder(playerName)
    UpdateUserName();
}

function rong_click(idx) {
    rong_flag[idx] = !rong_flag[idx];
    if (rong_flag[idx] == false) {
        $("#player" + idx + "_rong")[0].value = "胡牌";
        $("#player" + idx + "_rong").removeClass('t_btn_click');
    } else {
        $("#player" + idx + "_rong")[0].value = "取消";
        $("#player" + idx + "_rong").addClass('t_btn_click');
        if (dianpao_flag[idx] == true) {
            $("#player" + idx + "_dianpao")[0].value = "点炮";
            $("#player" + idx + "_dianpao").removeClass('t_btn_click');
            dianpao_flag[idx] = false;
        }
    }
}

function dianpao_click(idx) {
    dianpao_flag[idx] = !dianpao_flag[idx];
    if (dianpao_flag[idx] == false) {
        $("#player" + idx + "_dianpao")[0].value = "点炮";
        $("#player" + idx + "_dianpao").removeClass('t_btn_click');
    } else {
        $("#player" + idx + "_dianpao")[0].value = "取消";
        $("#player" + idx + "_dianpao").addClass('t_btn_click');
        if (rong_flag[idx] == true) {
            $("#player" + idx + "_rong")[0].value = "胡牌";
            $("#player" + idx + "_rong").removeClass('t_btn_click');
            rong_flag[idx] = false;
        }
    }
}

function changeView(idx) {
    mainView = idx;
    ChangePointShowMode();
}<commit_msg>【js】排位逻辑<commit_after>var playerName = ['Aさん', 'Bさん', 'Cさん', 'Dさん'];
var PointLeft = [25000, 25000, 25000, 25000];
var jushu = 1; //局数
var changfeng = '东'; //场风
var benchang = 0; //本场数

var rong_flag = [false, false, false, false];
var dianpao_flag = [false, false, false, false];

var mainView = 0; //点差模式下主视角

function $q(pattern, idx) { //jQuery辅助函数
    return $(pattern + ":eq(" + idx + ')');
}

$(document).ready(
    function () {
        $('input').bind('change', EditPlayerName);
        UpdateUserName();

        $('#myonoffswitch').change(ChangePointShowMode);
        ShowPoint(false);

        UpdateAllView();
    }
);

function UpdateAllView() {
    ChangePointShowMode(); //更新点差显示模式
    UpdateGameProcess(); //更新右上角进度
    UpdateFengwei(); //更新风位
    UpdateRank(); //更新顺位
}

function sortRank(a,b)
{
    /*同分逻辑需要重写，高位同分首庄开始算起(已完成)，地位同分离高位近的开始算起！！*/
    return PointLeft[a] < PointLeft[b] || b<a;
}

function UpdateRank() {
    var ori = [0,1,2,3];
    ori = ori.sort(sortRank);
    for(var i = 0;i < 4;i++)
    {
        $q('.weici',ori[i]).text(i+1+'位');
    }
}

function ShowPoint(DiffMode) {
    for (var i = 0; i < 4; i++) {
        if (DiffMode) {
            $('.playerscore', $('.playerinfoarea')[i]).text(PointLeft[i] - PointLeft[mainView] * (i != mainView));
        } else {
            $('.playerscore', $('.playerinfoarea')[i]).text(PointLeft[i]);
        }
    }
}

function UpdateFengwei() //更新风位
{
    $q('.playerpos', (jushu + 3) % 4).text('东');
    $q('.playerpos', (jushu + 4) % 4).text('南');
    $q('.playerpos', (jushu + 5) % 4).text('西');
    $q('.playerpos', (jushu + 6) % 4).text('北');

}

function ChangePointShowMode() {
    $('.playerpos').not(function (id) {
        return id == mainView
    }).removeClass('mainviewcl');
    $q('.playerpos', mainView).addClass('mainviewcl');
    ShowPoint(!$("#myonoffswitch").is(':checked'));
}

function EditPlayerName() {
    for (var i = 0; i < 4; i++) {
        playerName[i] = $('#playerName input')[i].value;
    }
    UpdateUserName();
}

function UpdateUserName() {
    for (var i = 0; i < 4; i++) {
        $("#playerName  input")[i].value = playerName[i];
        $('.playername', $('.playerinfoarea')[i]).text(playerName[i]);
        $('#randpos input')[i].value = playerName[i];
    }
}

function UpdateGameProcess() {
    var chn = ['一', '二', '三', '四'];
    $("#changkuang").text(changfeng + chn[jushu - 1] + '局');
    $("#benchangshu").text(benchang + '本场');
}

//随机换座位
function randomOrder(targetArray) {
    var arrayLength = targetArray.length
    var tempArray1 = new Array();
    for (var i = 0; i < arrayLength; i++) {
        tempArray1[i] = i
    }
    var tempArray2 = new Array();
    for (var i = 0; i < arrayLength; i++) {
        tempArray2[i] = tempArray1.splice(Math.floor(Math.random() * tempArray1.length), 1)
    }
    var tempArray3 = new Array();
    for (var i = 0; i < arrayLength; i++) {
        tempArray3[i] = targetArray[tempArray2[i]]
    }
    return tempArray3
}

function make_random_position() {
    playerName = randomOrder(playerName)
    UpdateUserName();
}

function rong_click(idx) {
    rong_flag[idx] = !rong_flag[idx];
    if (rong_flag[idx] == false) {
        $("#player" + idx + "_rong")[0].value = "胡牌";
        $("#player" + idx + "_rong").removeClass('t_btn_click');
    } else {
        $("#player" + idx + "_rong")[0].value = "取消";
        $("#player" + idx + "_rong").addClass('t_btn_click');
        if (dianpao_flag[idx] == true) {
            $("#player" + idx + "_dianpao")[0].value = "点炮";
            $("#player" + idx + "_dianpao").removeClass('t_btn_click');
            dianpao_flag[idx] = false;
        }
    }
}

function dianpao_click(idx) {
    dianpao_flag[idx] = !dianpao_flag[idx];
    if (dianpao_flag[idx] == false) {
        $("#player" + idx + "_dianpao")[0].value = "点炮";
        $("#player" + idx + "_dianpao").removeClass('t_btn_click');
    } else {
        $("#player" + idx + "_dianpao")[0].value = "取消";
        $("#player" + idx + "_dianpao").addClass('t_btn_click');
        if (rong_flag[idx] == true) {
            $("#player" + idx + "_rong")[0].value = "胡牌";
            $("#player" + idx + "_rong").removeClass('t_btn_click');
            rong_flag[idx] = false;
        }
    }
}

function changeView(idx) {
    mainView = idx;
    ChangePointShowMode();
}<|endoftext|>


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

    // Variables with names starting with '$' are DOM-elements.
    // Function and variables with names starting with 'g' are global.
    // Variables with names starting with 'a' are parameters.

    var $buttonsContainer = document.getElementById('buttons_container'),
        $canvas = document.getElementById('canvas'),
        gCtx = $canvas.getContext('2d'),
        gCanvasMetrics = {
            DEFAULT_WIDTH: 640,
            DEFAULT_HEIGHT: 480,
            width: null,
            height: null,
            scaleFactor: null,
            offsetX: null,
            offsetY: null,
        },

        gImagesPaths = ['img/card1.png', 'img/card2.png', 'img/card3.png'],
        gImagesMetrics = {
            DEFAULT_WIDTH: 150,
            DEFAULT_HEIGHT: 250,
            ADDITION: 20,
            OFFSET_X: 10,
            OFFSET_Y: 20
        },
        gImages = {},
        gImagesOnCanvasStack = [],

        gCurrentDraggingImageIndex = -1,
        gDraggingDeltas = { x: null, y: null },
        gIsAnimationFrameRequested = false,

        gButtons = [];

    gInitCanvasAndButtonsResizing();
    gStartImagesLoading();

    function gInitCanvasAndButtonsResizing() {
        var debounceTmt = null;

        //initial canvas size setting
        setCanvasSize();

        window.onresize = function() {
            clearTimeout(debounceTmt);
            debounceTmt = setTimeout(function() {
                setCanvasSize();
                setButtonsPosition();
                gDraw();
            }, 100);
        };

        function setCanvasSize() {
            gCanvasMetrics.width = window.innerWidth;
            gCanvasMetrics.height = window.innerHeight;

            $canvas.width = gCanvasMetrics.width;
            $canvas.height = gCanvasMetrics.height;
            console.log('Canvas size is set to ' + gCanvasMetrics.width + 'x' + gCanvasMetrics.height);

            gCanvasMetrics.scaleFactor = Math.min(gCanvasMetrics.width/gCanvasMetrics.DEFAULT_WIDTH,
                                                 gCanvasMetrics.height/gCanvasMetrics.DEFAULT_HEIGHT);
            console.log('Scale factor is set to ' + gCanvasMetrics.scaleFactor);

            gCanvasMetrics.offsetX = Math.floor((gCanvasMetrics.width - gCanvasMetrics.DEFAULT_WIDTH*gCanvasMetrics.scaleFactor)/2);
            gCanvasMetrics.offsetY = Math.floor((gCanvasMetrics.height - gCanvasMetrics.DEFAULT_HEIGHT*gCanvasMetrics.scaleFactor)/2);
            console.log('Offsets: x=' + gCanvasMetrics.offsetX + ', y=' + gCanvasMetrics.offsetY);

            gCtx.setTransform(gCanvasMetrics.scaleFactor, 0, 0, gCanvasMetrics.scaleFactor, gCanvasMetrics.offsetX, gCanvasMetrics.offsetY);
        }

        function setButtonsPosition() {
            for (var i = 0, len = gButtons.length; i < len; i++) {
                gSetButtonPosition(gButtons[i]);
            }
        }
    }

    function gSetButtonPosition(aButton) {
        aButton.style.top = gCanvasMetrics.height*0.8 + 'px';
        aButton.style.left = (gCanvasMetrics.offsetX + gCanvasMetrics.scaleFactor*gCanvasMetrics.DEFAULT_WIDTH*(0.1 + 0.8*aButton.number/(gImagesPaths.length - 1))) + 'px';
    }

    function gStartImagesLoading() {
        for (var i = 0, len = gImagesPaths.length; i < len; i++) {
            gImages[i] = new Image();
            gImages[i].onload = addButtonForImage.bind(null, i);
            gImages[i].src = gImagesPaths[i];
        }

        function addButtonForImage(aNumber) {
            console.log('Image ' + aNumber + ' is loaded.');

            var $button = document.createElement('button');
            $button.className = 'image_button';
            $button.textContent = 'Image ' + (aNumber + 1);
            $button.number = aNumber;

            gSetButtonPosition($button);

            $buttonsContainer.insertBefore($button, null);

            gButtons.push($button);

            $button.onclick = buttonClickAction.bind(null, aNumber);
        }

        function buttonClickAction(aNumber) {
            var lastImageOnStack, index = indexOfImageOnStack(aNumber);

            if (~index) {
                // Remove image from canvas image stack array.
                gImagesOnCanvasStack = gImagesOnCanvasStack.slice(0, index).concat(gImagesOnCanvasStack.slice(index + 1));
            } else {
                lastImageOnStack = gImagesOnCanvasStack.length ? gImagesOnCanvasStack[gImagesOnCanvasStack.length - 1] : null;
                gImagesOnCanvasStack.push({
                    x: lastImageOnStack ? lastImageOnStack.x + gImagesMetrics.OFFSET_X : (gCanvasMetrics.DEFAULT_WIDTH - gImagesMetrics.DEFAULT_WIDTH)/2,
                    y: lastImageOnStack ? lastImageOnStack.y + gImagesMetrics.OFFSET_Y : (gCanvasMetrics.DEFAULT_HEIGHT - gImagesMetrics.DEFAULT_HEIGHT)/2,
                    imageNo: aNumber});
            }
            gDraw();
        }

        function indexOfImageOnStack(aNumber) {
            for (var i = 0, len = gImagesOnCanvasStack.length; i < len; i++) {
                if (gImagesOnCanvasStack[i].imageNo === aNumber) {
                    return i;
                }
            }
            return -1;
        }
    }

    function gDraw() {
        gCtx.clearRect(-gCanvasMetrics.offsetX, -gCanvasMetrics.offsetY, gCanvasMetrics.width, gCanvasMetrics.height);

        var currentImage;
        for (var i = 0, len = gImagesOnCanvasStack.length; i < len; i++) {
            currentImage = gImagesOnCanvasStack[i];
            gCtx.drawImage(gImages[currentImage.imageNo], currentImage.x, currentImage.y);
        }
    }

    $canvas.onmousedown = function(aMouseEvent) {
        var canvasCoords = calculateCanvasCoords(aMouseEvent);
        gCurrentDraggingImageIndex = gIndexOfImageUnderMouse(canvasCoords.x, canvasCoords.y);
        if (~gCurrentDraggingImageIndex) {
            gDraggingDeltas.x = canvasCoords.x;
            gDraggingDeltas.y = canvasCoords.y;
        }
    };

    $canvas.onmouseup = function(aMouseEvent) {
        gCurrentDraggingImageIndex = -1;
    };

    $canvas.onmousemove = function(aMouseEvent) {
        var canvasCoords = calculateCanvasCoords(aMouseEvent);
        if (~gCurrentDraggingImageIndex && !gIsAnimationFrameRequested) {
            gIsAnimationFrameRequested = true;

            gImagesOnCanvasStack[gCurrentDraggingImageIndex].x += canvasCoords.x - gDraggingDeltas.x;
            gImagesOnCanvasStack[gCurrentDraggingImageIndex].y += canvasCoords.y - gDraggingDeltas.y;

            gDraggingDeltas.x = canvasCoords.x;
            gDraggingDeltas.y = canvasCoords.y;

            window.requestAnimationFrame(function() {
                gIsAnimationFrameRequested = false;
                gDraw();
            });
        }
    };

    function calculateCanvasCoords(aMouseEvent) {
        var x = (aMouseEvent.clientX - gCanvasMetrics.offsetX)*gCanvasMetrics.scaleFactor,
            y = (aMouseEvent.clientY - gCanvasMetrics.offsetY)*gCanvasMetrics.scaleFactor;
        return { x: x, y: y};
    }

    function gIndexOfImageUnderMouse(aX, aY) {
        var currentImage;
        for (var i = gImagesOnCanvasStack.length - 1; i >= 0; i--) {
            currentImage = gImagesOnCanvasStack[i];
            if (aX >= currentImage.x && aX <= currentImage.x + gImagesMetrics.DEFAULT_WIDTH &&
                aY >= currentImage.y && aY <= currentImage.y + gImagesMetrics.DEFAULT_HEIGHT) {
                return i;
            }
        }
        return -1;
    }
})();<commit_msg>Fix canvas clearing<commit_after>(function() {
    'use strict';

    // Variables with names starting with '$' are DOM-elements.
    // Function and variables with names starting with 'g' are global.
    // Variables with names starting with 'a' are parameters.

    var $buttonsContainer = document.getElementById('buttons_container'),
        $canvas = document.getElementById('canvas'),
        gCtx = $canvas.getContext('2d'),
        gCanvasMetrics = {
            DEFAULT_WIDTH: 640,
            DEFAULT_HEIGHT: 480,
            width: null,
            height: null,
            scaleFactor: null,
            offsetX: null,
            offsetY: null,
        },

        gImagesPaths = ['img/card1.png', 'img/card2.png', 'img/card3.png'],
        gImagesMetrics = {
            DEFAULT_WIDTH: 150,
            DEFAULT_HEIGHT: 250,
            ADDITION: 20,
            OFFSET_X: 10,
            OFFSET_Y: 20
        },
        gImages = {},
        gImagesOnCanvasStack = [],

        gCurrentDraggingImageIndex = -1,
        gDraggingDeltas = { x: null, y: null },
        gIsAnimationFrameRequested = false,

        gButtons = [];

    gInitCanvasAndButtonsResizing();
    gStartImagesLoading();

    function gInitCanvasAndButtonsResizing() {
        var debounceTmt = null;

        //initial canvas size setting
        setCanvasSize();

        window.onresize = function() {
            clearTimeout(debounceTmt);
            debounceTmt = setTimeout(function() {
                setCanvasSize();
                setButtonsPosition();
                gDraw();
            }, 100);
        };

        function setCanvasSize() {
            gCanvasMetrics.width = window.innerWidth;
            gCanvasMetrics.height = window.innerHeight;

            $canvas.width = gCanvasMetrics.width;
            $canvas.height = gCanvasMetrics.height;
            console.log('Canvas size is set to ' + gCanvasMetrics.width + 'x' + gCanvasMetrics.height);

            gCanvasMetrics.scaleFactor = Math.min(gCanvasMetrics.width/gCanvasMetrics.DEFAULT_WIDTH,
                                                 gCanvasMetrics.height/gCanvasMetrics.DEFAULT_HEIGHT);
            console.log('Scale factor is set to ' + gCanvasMetrics.scaleFactor);

            gCanvasMetrics.offsetX = Math.floor((gCanvasMetrics.width - gCanvasMetrics.DEFAULT_WIDTH*gCanvasMetrics.scaleFactor)/2);
            gCanvasMetrics.offsetY = Math.floor((gCanvasMetrics.height - gCanvasMetrics.DEFAULT_HEIGHT*gCanvasMetrics.scaleFactor)/2);
            console.log('Offsets: x=' + gCanvasMetrics.offsetX + ', y=' + gCanvasMetrics.offsetY);

            gCtx.setTransform(gCanvasMetrics.scaleFactor, 0, 0, gCanvasMetrics.scaleFactor, gCanvasMetrics.offsetX, gCanvasMetrics.offsetY);
        }

        function setButtonsPosition() {
            for (var i = 0, len = gButtons.length; i < len; i++) {
                gSetButtonPosition(gButtons[i]);
            }
        }
    }

    function gSetButtonPosition(aButton) {
        aButton.style.top = gCanvasMetrics.height*0.8 + 'px';
        aButton.style.left = (gCanvasMetrics.offsetX + gCanvasMetrics.scaleFactor*gCanvasMetrics.DEFAULT_WIDTH*(0.1 + 0.8*aButton.number/(gImagesPaths.length - 1))) + 'px';
    }

    function gStartImagesLoading() {
        for (var i = 0, len = gImagesPaths.length; i < len; i++) {
            gImages[i] = new Image();
            gImages[i].onload = addButtonForImage.bind(null, i);
            gImages[i].src = gImagesPaths[i];
        }

        function addButtonForImage(aNumber) {
            console.log('Image ' + aNumber + ' is loaded.');

            var $button = document.createElement('button');
            $button.className = 'image_button';
            $button.textContent = 'Image ' + (aNumber + 1);
            $button.number = aNumber;

            gSetButtonPosition($button);

            $buttonsContainer.insertBefore($button, null);

            gButtons.push($button);

            $button.onclick = buttonClickAction.bind(null, aNumber);
        }

        function buttonClickAction(aNumber) {
            var lastImageOnStack, index = indexOfImageOnStack(aNumber);

            if (~index) {
                // Remove image from canvas image stack array.
                gImagesOnCanvasStack = gImagesOnCanvasStack.slice(0, index).concat(gImagesOnCanvasStack.slice(index + 1));
            } else {
                lastImageOnStack = gImagesOnCanvasStack.length ? gImagesOnCanvasStack[gImagesOnCanvasStack.length - 1] : null;
                gImagesOnCanvasStack.push({
                    x: lastImageOnStack ? lastImageOnStack.x + gImagesMetrics.OFFSET_X : (gCanvasMetrics.DEFAULT_WIDTH - gImagesMetrics.DEFAULT_WIDTH)/2,
                    y: lastImageOnStack ? lastImageOnStack.y + gImagesMetrics.OFFSET_Y : (gCanvasMetrics.DEFAULT_HEIGHT - gImagesMetrics.DEFAULT_HEIGHT)/2,
                    imageNo: aNumber});
            }
            gDraw();
        }

        function indexOfImageOnStack(aNumber) {
            for (var i = 0, len = gImagesOnCanvasStack.length; i < len; i++) {
                if (gImagesOnCanvasStack[i].imageNo === aNumber) {
                    return i;
                }
            }
            return -1;
        }
    }

    function gDraw() {
        gCtx.clearRect(
            -gCanvasMetrics.offsetX/gCanvasMetrics.scaleFactor,
            -gCanvasMetrics.offsetY/gCanvasMetrics.scaleFactor,
            gCanvasMetrics.width/gCanvasMetrics.scaleFactor,
            gCanvasMetrics.height/gCanvasMetrics.scaleFactor
        );

        var currentImage;
        for (var i = 0, len = gImagesOnCanvasStack.length; i < len; i++) {
            currentImage = gImagesOnCanvasStack[i];
            gCtx.drawImage(gImages[currentImage.imageNo], currentImage.x, currentImage.y);
        }
    }

    $canvas.onmousedown = function(aMouseEvent) {
        var canvasCoords = calculateCanvasCoords(aMouseEvent);
        gCurrentDraggingImageIndex = gIndexOfImageUnderMouse(canvasCoords.x, canvasCoords.y);
        if (~gCurrentDraggingImageIndex) {
            gDraggingDeltas.x = canvasCoords.x;
            gDraggingDeltas.y = canvasCoords.y;
        }
    };

    $canvas.onmouseup = function(aMouseEvent) {
        gCurrentDraggingImageIndex = -1;
    };

    $canvas.onmousemove = function(aMouseEvent) {
        var canvasCoords = calculateCanvasCoords(aMouseEvent);
        if (~gCurrentDraggingImageIndex && !gIsAnimationFrameRequested) {
            gIsAnimationFrameRequested = true;

            gImagesOnCanvasStack[gCurrentDraggingImageIndex].x += canvasCoords.x - gDraggingDeltas.x;
            gImagesOnCanvasStack[gCurrentDraggingImageIndex].y += canvasCoords.y - gDraggingDeltas.y;

            gDraggingDeltas.x = canvasCoords.x;
            gDraggingDeltas.y = canvasCoords.y;

            window.requestAnimationFrame(function() {
                gIsAnimationFrameRequested = false;
                gDraw();
            });
        }
    };

    function calculateCanvasCoords(aMouseEvent) {
        var x = (aMouseEvent.clientX - gCanvasMetrics.offsetX)*gCanvasMetrics.scaleFactor,
            y = (aMouseEvent.clientY - gCanvasMetrics.offsetY)*gCanvasMetrics.scaleFactor;
        return { x: x, y: y};
    }

    function gIndexOfImageUnderMouse(aX, aY) {
        var currentImage;
        for (var i = gImagesOnCanvasStack.length - 1; i >= 0; i--) {
            currentImage = gImagesOnCanvasStack[i];
            if (aX >= currentImage.x && aX <= currentImage.x + gImagesMetrics.DEFAULT_WIDTH &&
                aY >= currentImage.y && aY <= currentImage.y + gImagesMetrics.DEFAULT_HEIGHT) {
                return i;
            }
        }
        return -1;
    }
})();<|endoftext|>