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

'use strict';

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

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

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

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

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

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

var ref = null;

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

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

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

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

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

function startRecording(stream) {

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

	        mediaRecorder.start(10);

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

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

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

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

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

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

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

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

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

	        mediaRecorder.onpause = function(){
	        }

	        mediaRecorder.onresume = function(){
	        }

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

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

                //ctx.drawImage(videoElement, 0, 0);
                let imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
                /*let pixeldataArray = [];
                //loop through every pixel
                for(let i=0; i<imageData.data.length; i = i+4)
                {
                        let pixeldata = {"red": imageData.data[i], "green":imageData.data[i+1], "blue": imageData.data[i+2], "alpha":imageData.data[i+3]};
                        //pixeldataArray.push(pixeldata);
                }
                //pixeldataArray.push(imageData);*/
                //if(nFrame < dataArray.length) {
                        //let timestamp = dataArray[nFrame].time;
                        //let frameData2 = {"imagedata": imageData, "time": timestamp, "oridiff": oriDiff};
                        //var b = new Object;     //need to push by value
                        //Object.assign(b, frameData2);
                        //dataArray2.push(b);
                        //dataArray2.push(frameData2);
                        //console.log(pixeldataArray);
                        //newImageData.data = data;
                    // Draw the pixels onto the visible canvas
                    //ctx.putImageData(newImageData,0,0);
                        //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(nFrame >= orientationData.length-1)
        {
                //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>Working on reacting to sensor input<commit_after>/*
 * Websensor video stabilization project
 * https://github.com/jessenie-intel/websensor-video
 *
 * Copyright (c) 2017 Jesse Nieminen
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
*/

'use strict';

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

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

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

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

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

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

var ref = null;

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

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

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

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

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

function startRecording(stream) {

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

	        mediaRecorder.start(10);

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

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

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

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

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

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

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

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

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

	        mediaRecorder.onpause = function(){
	        }

	        mediaRecorder.onresume = function(){
	        }

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

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

                //ctx.drawImage(videoElement, 0, 0);
                let imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
                /*let pixeldataArray = [];
                //loop through every pixel
                for(let i=0; i<imageData.data.length; i = i+4)
                {
                        let pixeldata = {"red": imageData.data[i], "green":imageData.data[i+1], "blue": imageData.data[i+2], "alpha":imageData.data[i+3]};
                        //pixeldataArray.push(pixeldata);
                }
                //pixeldataArray.push(imageData);*/
                //if(nFrame < dataArray.length) {
                        //let timestamp = dataArray[nFrame].time;
                        //let frameData2 = {"imagedata": imageData, "time": timestamp, "oridiff": oriDiff};
                        //var b = new Object;     //need to push by value
                        //Object.assign(b, frameData2);
                        //dataArray2.push(b);
                        //dataArray2.push(frameData2);
                        //console.log(pixeldataArray);
                        //newImageData.data = data;
                    // Draw the pixels onto the visible canvas
                    //ctx.putImageData(newImageData,0,0);
                        //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(nFrame >= orientationData.length-1)
        {
                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>weekdays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];

init();

function init() {
  var fieldsets = document.getElementsByTagName('fieldset');
  for (var i = fieldsets.length - 1; i >= 0; i--) {
    fieldsets[i].onmouseover = function() {
      this.getElementsByTagName('legend')[0].style.borderColor = 'threedhighlight';
      this.style.borderColor = 'threedhighlight'
    };
    fieldsets[i].onmouseout = function() {
      this.getElementsByTagName('legend')[0].style.borderColor = 'threedface';
      this.style.borderColor = 'threedface'
    };
  }
  var output = document.getElementById('output');
  output.onmouseover = function() {
    this.style.borderColor = 'threedhighlight'
  };
  output.onmouseout = function() {
    this.style.borderColor = 'threedface'
  };
  today();
  var formInputs = document.getElementsByTagName('form')[0].getElementsByTagName('input');
  for (var i = formInputs.length - 1; i >= 0; i--) {
    formInputs[i].onmouseover = function() {
      this.style.backgroundColor = '#eee'
    };
    formInputs[i].onmouseout = function() {
      this.style.backgroundColor = '#ddd'
    };
  }
}

function today() {
  var digestDate = document.getElementById('digestDate');
  var todayDate = new Date(Date.now());
  digestDate.value = constructDateString(todayDate, "-", false);
}

function nextSunday() {
  var digestDate = document.getElementById('digestDate');
  today();
  var d = new Date(digestDate.value);
  while (d.getDay() != 0) {
    d.setDate(d.getDate() + 1);
  }
  digestDate.value = constructDateString(d, "-", false);
}

function render() {
  document.getElementById('genButton').innerHTML = 'REGEN ADVISED';
  document.getElementById('genButton').style.color = '#f00';
  document.getElementById('output').style.backgroundColor = '#fdd';
  document.getElementById('outputText').style.backgroundColor = '#fdd';
  var renderWindow = window.open();
  renderWindow.document.write(document.getElementById('outputText').value);
}

function gen() {
  document.getElementById('genButton').innerHTML = 'GENERATE';
  document.getElementById('genButton').style.color = '#000';
  document.getElementById('renderButton').disabled = false;
  document.getElementById('output').style.backgroundColor = '#fff';
  document.getElementById('outputText').style.backgroundColor = '#fff';
  var output = "";
  output += genHeader();
  output += genFooter();
  document.getElementById('outputText').value = output;
}

function genHeader() {
  var digestDate = new Date(document.getElementById('digestDate').value);
  var dateString = constructDateString(digestDate, ".", true);
  var digestCSS = document.getElementById("digestCSS").value;
  var mdyString = constructMDYString(digestDate, true);
  var headerStr =
      '<!doctype HTML>\n'
    + '\n'
    + '  \n'
    + '    <title>EZ Digest - ' + dateString + '</title>\n'
    + '    <link rel="stylesheet" type="text/css" href="' + digestCSS + '">\n'
    + '  \n'
    + '  \n'
    + '
\n'
    + '
\n'
    + '        \n'
    + '          EZ Digest - ' + mdyString + '\n'
    + '        	\n'
    + '
\n';
  return headerStr;
}

function genFooter() {
  var footerStr =
      '
\n'
    + '        \n'
    + '
The goal of the weekly EZ Digest is to provide a concise summary of recent and upcoming chapter activities.
\n'
    + '
Unlike eggs, digests are always better when they\'re Over EZ.
\n'
    + '
Feel free to reply to this message with any comments or suggestions!
\n'
    + '
Alpha Phi Omega - Epsilon Zeta Chapter - Rensselaer Polytechnic Institute
\n'
    + '        	\n'
    + '
\n'
    + '
\n'
    + '  \n'
    + '\n'
  return footerStr;
}

function pad(num, size) {
    var s = num+"";
    while (s.length < size) s = "0" + s;
    return s;
}

function constructDateString(date, separator, utc) {
  return utc
    ? date.getUTCFullYear() + separator + pad(date.getUTCMonth() + 1, 2) + separator + pad(date.getUTCDate(), 2)
    : date.getFullYear() + separator + pad(date.getMonth() + 1, 2) + separator + pad(date.getDate(), 2);
}

function constructMDYString(date, utc) {
  return utc
    ? months[date.getUTCMonth()] + " " + date.getUTCDate() + ", " + date.getUTCFullYear()
    : months[date.getMonth()] + " "  + date.getDate() + ", " + date.getFullYear();

}
<commit_msg>Fix next Sunday UTC bug<commit_after>weekdays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];

init();

function init() {
  var fieldsets = document.getElementsByTagName('fieldset');
  for (var i = fieldsets.length - 1; i >= 0; i--) {
    fieldsets[i].onmouseover = function() {
      this.getElementsByTagName('legend')[0].style.borderColor = 'threedhighlight';
      this.style.borderColor = 'threedhighlight'
    };
    fieldsets[i].onmouseout = function() {
      this.getElementsByTagName('legend')[0].style.borderColor = 'threedface';
      this.style.borderColor = 'threedface'
    };
  }
  var output = document.getElementById('output');
  output.onmouseover = function() {
    this.style.borderColor = 'threedhighlight'
  };
  output.onmouseout = function() {
    this.style.borderColor = 'threedface'
  };
  today();
  var formInputs = document.getElementsByTagName('form')[0].getElementsByTagName('input');
  for (var i = formInputs.length - 1; i >= 0; i--) {
    formInputs[i].onmouseover = function() {
      this.style.backgroundColor = '#eee'
    };
    formInputs[i].onmouseout = function() {
      this.style.backgroundColor = '#ddd'
    };
  }
}

function today() {
  var digestDate = document.getElementById('digestDate');
  var todayDate = new Date(Date.now());
  digestDate.value = constructDateString(todayDate, "-", false);
}

function nextSunday() {
  var digestDate = document.getElementById('digestDate');
  today();
  var d = new Date(digestDate.value);
  while (d.getUTCDay() != 0) {
    d.setDate(d.getUTCDate() + 1);
  }
  digestDate.value = constructDateString(d, "-", true);
}

function render() {
  document.getElementById('genButton').innerHTML = 'REGEN ADVISED';
  document.getElementById('genButton').style.color = '#f00';
  document.getElementById('output').style.backgroundColor = '#fdd';
  document.getElementById('outputText').style.backgroundColor = '#fdd';
  var renderWindow = window.open();
  renderWindow.document.write(document.getElementById('outputText').value);
}

function gen() {
  document.getElementById('genButton').innerHTML = 'GENERATE';
  document.getElementById('genButton').style.color = '#000';
  document.getElementById('renderButton').disabled = false;
  document.getElementById('output').style.backgroundColor = '#fff';
  document.getElementById('outputText').style.backgroundColor = '#fff';
  var output = "";
  output += genHeader();
  output += genFooter();
  document.getElementById('outputText').value = output;
}

function genHeader() {
  var digestDate = new Date(document.getElementById('digestDate').value);
  var dateString = constructDateString(digestDate, ".", true);
  var digestCSS = document.getElementById("digestCSS").value;
  var mdyString = constructMDYString(digestDate, true);
  var headerStr =
      '<!doctype HTML>\n'
    + '\n'
    + '  \n'
    + '    <title>EZ Digest - ' + dateString + '</title>\n'
    + '    <link rel="stylesheet" type="text/css" href="' + digestCSS + '">\n'
    + '  \n'
    + '  \n'
    + '
\n'
    + '
\n'
    + '        \n'
    + '          EZ Digest - ' + mdyString + '\n'
    + '        	\n'
    + '
\n';
  return headerStr;
}

function genFooter() {
  var footerStr =
      '
\n'
    + '        \n'
    + '
The goal of the weekly EZ Digest is to provide a concise summary of recent and upcoming chapter activities.
\n'
    + '
Unlike eggs, digests are always better when they\'re Over EZ.
\n'
    + '
Feel free to reply to this message with any comments or suggestions!
\n'
    + '
Alpha Phi Omega - Epsilon Zeta Chapter - Rensselaer Polytechnic Institute
\n'
    + '        	\n'
    + '
\n'
    + '
\n'
    + '  \n'
    + '\n'
  return footerStr;
}

function pad(num, size) {
    var s = num+"";
    while (s.length < size) s = "0" + s;
    return s;
}

function constructDateString(date, separator, utc) {
  return utc
    ? date.getUTCFullYear() + separator + pad(date.getUTCMonth() + 1, 2) + separator + pad(date.getUTCDate(), 2)
    : date.getFullYear() + separator + pad(date.getMonth() + 1, 2) + separator + pad(date.getDate(), 2);
}

function constructMDYString(date, utc) {
  return utc
    ? months[date.getUTCMonth()] + " " + date.getUTCDate() + ", " + date.getUTCFullYear()
    : months[date.getMonth()] + " "  + date.getDate() + ", " + date.getFullYear();

}
<|endoftext|>


<commit_before>/*
Copyright (c) 2017, Nebil Kawas García.
This source code is subject to the terms of the Mozilla Public License.
You can obtain a copy of the MPLv2 at https://www.mozilla.org/MPL/2.0/.
*/

(function() {
var DAYS = [
    { name: 'sun', color: '#FC3' },
    { name: 'mon', color: '#BBB' },
    { name: 'tue', color: '#C88' },
    { name: 'wed', color: '#C9E' },
    { name: 'thu', color: '#9DD' },
    { name: 'fri', color: '#F9C' },
    { name: 'sat', color: '#9C8' },
];

var currentDay = new Date().getDay();
document.body.style.backgroundColor = DAYS[currentDay].color;

window.onload = function() {
            document.getElementById('octocat')
    .contentDocument.getElementById('quarter')
    .classList.add(DAYS[currentDay].name);
};

var input = document.getElementById('text-input');
input.addEventListener('input', setText);

function setText() {
    var trimmedText = input.value.trim();
    var altoEnText = document.getElementById('alto-en');
    var upperText = document.getElementById('upper');
    var lowerText = document.getElementById('lower');
    var minsalText = document.getElementById('minsal');
    var replacement = trimmedText.toUpperCase() || ' ';
    upperText.textContent = replacement;

    var hasWhitespace = replacement.indexOf(' ') !== -1;
    if (hasWhitespace && upperText.getComputedTextLength() > 108) {
        // First, set the text contents.
        var wordList = replacement.split(/\s+/);
        upperText.textContent = wordList[0];
        lowerText.textContent = wordList.slice(1).join(' ');
        // REVIEW: The number of words in each line should be picked
        // ======= in a more aesthetic way, by automatically finding
        //         an arrangement that provides an equipoise between
        //         the length of both lines.

        // Then, adjust all the positions.
        altoEnText.setAttribute('y', 50);
        upperText.setAttribute('dy', 22);
        lowerText.setAttribute('dy', 22);
        minsalText.setAttribute('dy', 21);
    } else {
        // Otherwise, reset everything.
        lowerText.textContent = '';
        altoEnText.setAttribute('y', 60);
        upperText.setAttribute('dy', 25);
        lowerText.setAttribute('dy', 00);
        minsalText.setAttribute('dy', 30);
    }

    function updateFontSize(newSize) {
        upperText.style.fontSize = newSize;
        lowerText.style.fontSize = newSize;
        upperLength = upperText.getComputedTextLength();
        lowerLength = lowerText.getComputedTextLength();
    }

    var upperLength = upperText.getComputedTextLength();
    var lowerLength = lowerText.getComputedTextLength();
    // Harmonize the text size, depending on its length.
    if (upperLength <= 100 && lowerLength <= 100)
        updateFontSize('20px');
    if (upperLength > 100 || lowerLength > 100)
        updateFontSize('19px');
    if (upperLength > 118 || lowerLength > 118)
        updateFontSize('18px');

    // Adapted from: https://developer.mozilla.org/en-US/docs/Web/API/
    // ======= =====     Canvas_API/Drawing_DOM_objects_into_a_canvas/
    var container = document.getElementById('container');
    var svgString = new XMLSerializer().serializeToString(container);
    var imageBlob = new Blob([svgString], { type: 'image/svg+xml' });

    var canvas = document.getElementById('hidden-canvas');
    var domUrl = window.URL || window.webkitURL || window;
    var svg = domUrl.createObjectURL(imageBlob);
    var img = new Image();
    img.src = svg;

    img.onload = function() {
        canvas.getContext('2d').drawImage(img, 0, 0);
        var caterpillarName = trimmedText.toLowerCase()
                                         .split(/\s+/)
                                         .join('-');
        var downloadFilename = 'alto-en-' + caterpillarName;

        // Offer a PNG version.
        var png = canvas.toDataURL('image/png');
        var pngButton = document.getElementById('to-png');
        pngButton.download = downloadFilename + '.png';
        pngButton.href = png;

        // Offer an SVG version.
        var svgButton = document.getElementById('to-svg');
        svgButton.download = downloadFilename + '.svg';
        svgButton.href = svg;
    };
}

function fetchQueryValue(key) {
    var regex = '[?&]' + key + '=[^&]*';
    var match = RegExp(regex).exec(window.location.search);
    return match && decodeURIComponent(match[0].split('=')[1]);
}

if (value = fetchQueryValue('input')) {
    document.getElementById('text-input').value = value;
    setText();
}

document.getElementById('upper').addEventListener('click', function() {
    document.getElementById('text-input').focus();
});
}());
<commit_msg>:art: Did a slight rearrangement to the script<commit_after>/*
Copyright (c) 2017, Nebil Kawas García.
This source code is subject to the terms of the Mozilla Public License.
You can obtain a copy of the MPLv2 at https://www.mozilla.org/MPL/2.0/.
*/

(function() {
var DAYS = [
    { name: 'sun', color: '#FC3' },
    { name: 'mon', color: '#BBB' },
    { name: 'tue', color: '#C88' },
    { name: 'wed', color: '#C9E' },
    { name: 'thu', color: '#9DD' },
    { name: 'fri', color: '#F9C' },
    { name: 'sat', color: '#9C8' },
];

var currentDay = new Date().getDay();
document.body.style.backgroundColor = DAYS[currentDay].color;

window.onload = function() {
            document.getElementById('octocat')
    .contentDocument.getElementById('quarter')
    .classList.add(DAYS[currentDay].name);
};

function setText() {
    var trimmedText = input.value.trim();
    var altoEnText = document.getElementById('alto-en');
    var upperText = document.getElementById('upper');
    var lowerText = document.getElementById('lower');
    var minsalText = document.getElementById('minsal');
    var replacement = trimmedText.toUpperCase() || ' ';
    upperText.textContent = replacement;

    var hasWhitespace = replacement.indexOf(' ') !== -1;
    if (hasWhitespace && upperText.getComputedTextLength() > 108) {
        // First, set the text contents.
        var wordList = replacement.split(/\s+/);
        upperText.textContent = wordList[0];
        lowerText.textContent = wordList.slice(1).join(' ');
        // REVIEW: The number of words in each line should be picked
        // ======= in a more aesthetic way, by automatically finding
        //         an arrangement that provides an equipoise between
        //         the length of both lines.

        // Then, adjust all the positions.
        altoEnText.setAttribute('y', 50);
        upperText.setAttribute('dy', 22);
        lowerText.setAttribute('dy', 22);
        minsalText.setAttribute('dy', 21);
    } else {
        // Otherwise, reset everything.
        lowerText.textContent = '';
        altoEnText.setAttribute('y', 60);
        upperText.setAttribute('dy', 25);
        lowerText.setAttribute('dy', 00);
        minsalText.setAttribute('dy', 30);
    }

    function updateFontSize(newSize) {
        upperText.style.fontSize = newSize;
        lowerText.style.fontSize = newSize;
        upperLength = upperText.getComputedTextLength();
        lowerLength = lowerText.getComputedTextLength();
    }

    var upperLength = upperText.getComputedTextLength();
    var lowerLength = lowerText.getComputedTextLength();
    // Harmonize the text size, depending on its length.
    if (upperLength <= 100 && lowerLength <= 100)
        updateFontSize('20px');
    if (upperLength > 100 || lowerLength > 100)
        updateFontSize('19px');
    if (upperLength > 118 || lowerLength > 118)
        updateFontSize('18px');

    // Adapted from: https://developer.mozilla.org/en-US/docs/Web/API/
    // ======= =====     Canvas_API/Drawing_DOM_objects_into_a_canvas/
    var container = document.getElementById('container');
    var svgString = new XMLSerializer().serializeToString(container);
    var imageBlob = new Blob([svgString], { type: 'image/svg+xml' });

    var canvas = document.getElementById('hidden-canvas');
    var domUrl = window.URL || window.webkitURL || window;
    var svg = domUrl.createObjectURL(imageBlob);
    var img = new Image();
    img.src = svg;

    img.onload = function() {
        canvas.getContext('2d').drawImage(img, 0, 0);
        var caterpillarName = trimmedText.toLowerCase()
                                         .split(/\s+/)
                                         .join('-');
        var downloadFilename = 'alto-en-' + caterpillarName;

        // Offer a PNG version.
        var png = canvas.toDataURL('image/png');
        var pngButton = document.getElementById('to-png');
        pngButton.download = downloadFilename + '.png';
        pngButton.href = png;

        // Offer an SVG version.
        var svgButton = document.getElementById('to-svg');
        svgButton.download = downloadFilename + '.svg';
        svgButton.href = svg;
    };
}

function fetchQueryValue(key) {
    var regex = '[?&]' + key + '=[^&]*';
    var match = RegExp(regex).exec(window.location.search);
    return match && decodeURIComponent(match[0].split('=')[1]);
}

var input = document.getElementById('text-input');
input.addEventListener('input', setText);

if (value = fetchQueryValue('input')) {
    input.value = value;
    setText();
}

document.getElementById('upper').addEventListener('click', function() {
    input.focus();
});
}());
<|endoftext|>


<commit_before>/*
//1 get user profile
//2 get rit of beebop error
//3 click more buttons
//4 write json for hypo
*/

'use strict';

const _ = require('lodash');
const Script = require('smooch-bot').Script;
const scriptRules = require('./script.json');

/*  CREATE TODAY */
var today = new Date();
var dd = today.getDate();
var mm = today.getMonth()+1; //January is 0!
var yyyy = today.getFullYear();

if(dd<10) {
    dd='0'+dd
}

if(mm<10) {
    mm='0'+mm
}

today =dd+'/'+mm+'/'+yyyy;

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

/* hour is before noon */
if ( myDate.getHours() < 8 )
{
  groet = "Goeiemorgen 🌝.  Bedankt voor je bezoek maar op dit moment is Independer echter gesloten. 🕘 Uiteraard kun je met onze IndyBot verder praten maar er is helaas niemand die jouw vraag specifiek kan beantwoorden. Je kan je vraag ook doormailen 📩 naar info@independer. Dan komt het altijd goed.";
}
else
if ( myDate.getHours() >8 )
{
  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() <= 20 )
{
groet = "Goedenavond 🌙";
}
else
if (myDate.getHours() > 20  || myDate.getHours() <= 24 )
{
  groet = "Goedenavond 🌙  Bedankt voor je bezoek maar op dit moment is Independer echter gesloten. 🕘 Uiteraard kun je met onze IndyBot verder praten maar er is helaas niemand die jouw vraag specifiek kan beantwoorden. Je kan je vraag ook doormailen 📩 naar info@independer. Dan komt het altijd goed.";
}
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('![](http://www.bieg.nl/beeld/speechbubble.gif)'),
 receive: () => 'processing'
 },

start: {
    receive: (bot,message) => {
        const opening = message.text.trim().toUpperCase();
        return bot.say(`${groet}... Wat voor soort hypotheek zoek je? `)
        .then(() => bot.say(`![](http://www.bieg.nl/beeld/woningen.jpg)`))
        .then(() => bot.say(`%[Starters Hypotheek](postback:hypotheektype_starter)`))
        .then(() => bot.say (`%[Nieuwe hypotheek](postback:hypotheektype_nieuw) `))
        .then(() => bot.say (`%[Hypotheek oversluiten](postback:hypotheektype_oversluiten)`))
        .then(() => 'selecteerHypotheek');
    }
},

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

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

                  /*  CREATE EXTRA JSON FILE FOR HYPO AND INCLUDE IT */
                  if (!_.has(scriptRules, upperText)) {
                      return bot.say('![](http://www.bieg.nl/beeld/speechbubble.gif)').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);
          }
},

selecteerHypotheek: {
    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(() => 'askName')
          break;
      case 'Starters Hypotheek':
          return bot.say(`Wat voor type woning zoek je? `)
          .then(() => bot.say(`%[🏬 Appartement](postback:hypotheekkeuze_appartement) %[🏠 Huis](postback:hypotheekkeuze_huis) %[📭 Vakantiewoning](postback:hypotheekkeuze_vakantiewoning)`))
          .then(() => 'woningType')
              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. %[💼 Zoek Hypotheek Adviseur](https://www.independer.nl/hypotheekadviseur/jelocatie.aspx)`))
            .then(() => 'finish')
          break;
        case 'Hypotheek oversluiten':
          return bot.say(`😟 Het spijt me maar op dit moment biedt Independer alleen  Starters een hypotheek.`)
          .then(()=> bot.say(`Als het allemaal wel zo ver is, wil je dan een update ontvangen? %[Ja, dat wil ik wel](postback:update_ja) %[Nee, dat hoeft niet](postback:update_nee)`))
            .then(() => 'updateOntvangen')
          break;
        default:
          return bot.say(`![](http://www.bieg.nl/beeld/speechbubble.gif)`)
            .then(() => 'processing')
          break;
      }
    }
},

updateOntvangen: {
    receive: (bot, message) => {
      switch(message.text) {
        case 'Ja, dat wil ik wel':
            return bot.say(`👍 Leuk, dan houd ik  je op de hoogte zodra er weer nieuws is.`)
            .then(() => 'update_ja');
          break;
          case 'Nee, dat hoeft niet':
              receive: () => 'bye'
              break;
          default:
            receive => 'processing'
            break;
      }
    }
},

update_ja: {
  prompt: (bot) => bot.say('Wat is je email adres?'),
      receive: (bot, message) => {
          const emailer=message.text;
          return bot.setProp('emailer', emailer)
              .then(()  => bot.say(`Ok - ✉  dan hou ik je via ${emailer} op de hoogte.`))
              .then(function() {
    Smooch.updateUser({
      givenName: 'New',
      surname: 'Name',
      email: ${emailer},
      signedUpAt: ${today}
    })
  })
              .then(()  =>'lastCheck')
    }
},

update_nee: {
  receive: () => 'bye'
},

hypotheekStarter: {
    receive: () => 'askName'
},
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'
},

woningType: {
  receive: (bot, message) => {
    switch(message.text) {
        case '🏬 Appartement':
          return bot.say(`Nice!`)
          .then(() => 'vervolgVragen')
          break;
      case '🏠 Huis':
          return bot.say(`Leuk`)
          .then(() => 'vervolgVragen')
          break;
    case '📭 Vakantiewoning':
          return bot.say(`Gezellig`)
          .then(() => 'vervolgVragen')
          break;
      default:
        receive => 'processing'
        break;
        }
    }
},

vervolgVragen: {
  prompt: (bot) => bot.say('Hoe heet je eigelijk? 😋'),
          receive: (bot, message) => {
              const Name = message.text.trim().toUpperCase();
              return bot.setProp('Name', Name)
                  .then(() => bot.say('Hoi ${Name}. 📋 Ik heb nog wat vragen voor je om verder te kunnen.'))
                  .then(() => 'processing')
            }
},

lastCheck: {
    prompt: (bot) => bot.say(' Is er nog iets waar ik  je bij kan helpen?  🔶  %[Ik zoek meer informatie](postback:meerInfo) %[Nee hoor](postback:bye)'),
          receive: (bot, message) => {
            switch(message.text) {
              case 'Nee hoor':
                  receive: ()  => 'bye'
                  break;
             case 'Ik zoek meer informatie':
                  receive: () => 'speak'
                  break;
            case 'Nee':
                  receive: () => 'bye'
                  break;
            default:
              return bot.say('![](http://www.bieg.nl/beeld/speechbubble.gif)')
                .then(() => 'processing')
              break;
            }
        }
},

meerInfo: {
  return bot.say('%[Link 1](http://www.nu.nl)')
  .then(() => bot.say('%[Link 2](http://www.elle.nl)')),
   receive: () => 'processing'
},

bye: {
    prompt: (bot) => bot.say('Fijn je gesproken te hebben. Bedankt voor je tijd ⏲'),
    receive: ()  => 'finish'
},

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

finish: {
receive: () => 'finish'
}
});
<commit_msg>qf<commit_after>/*
//1 get user profile
//2 get rit of beebop error
//3 click more buttons
//4 write json for hypo
*/

'use strict';

const _ = require('lodash');
const Script = require('smooch-bot').Script;
const scriptRules = require('./script.json');

/*  CREATE TODAY */
var today = new Date();
var dd = today.getDate();
var mm = today.getMonth()+1; //January is 0!
var yyyy = today.getFullYear();

if(dd<10) {
    dd='0'+dd
}

if(mm<10) {
    mm='0'+mm
}

today =dd+'/'+mm+'/'+yyyy;

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

/* hour is before noon */
if ( myDate.getHours() < 8 )
{
  groet = "Goeiemorgen 🌝.  Bedankt voor je bezoek maar op dit moment is Independer echter gesloten. 🕘 Uiteraard kun je met onze IndyBot verder praten maar er is helaas niemand die jouw vraag specifiek kan beantwoorden. Je kan je vraag ook doormailen 📩 naar info@independer. Dan komt het altijd goed.";
}
else
if ( myDate.getHours() >8 )
{
  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() <= 20 )
{
groet = "Goedenavond 🌙";
}
else
if (myDate.getHours() > 20  || myDate.getHours() <= 24 )
{
  groet = "Goedenavond 🌙  Bedankt voor je bezoek maar op dit moment is Independer echter gesloten. 🕘 Uiteraard kun je met onze IndyBot verder praten maar er is helaas niemand die jouw vraag specifiek kan beantwoorden. Je kan je vraag ook doormailen 📩 naar info@independer. Dan komt het altijd goed.";
}
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('![](http://www.bieg.nl/beeld/speechbubble.gif)'),
 receive: () => 'processing'
 },

start: {
    receive: (bot,message) => {
        const opening = message.text.trim().toUpperCase();
        return bot.say(`${groet}... Wat voor soort hypotheek zoek je? `)
        .then(() => bot.say(`![](http://www.bieg.nl/beeld/woningen.jpg)`))
        .then(() => bot.say(`%[Starters Hypotheek](postback:hypotheektype_starter)`))
        .then(() => bot.say (`%[Nieuwe hypotheek](postback:hypotheektype_nieuw) `))
        .then(() => bot.say (`%[Hypotheek oversluiten](postback:hypotheektype_oversluiten)`))
        .then(() => 'selecteerHypotheek');
    }
},

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

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

                  /*  CREATE EXTRA JSON FILE FOR HYPO AND INCLUDE IT */
                  if (!_.has(scriptRules, upperText)) {
                      return bot.say('![](http://www.bieg.nl/beeld/speechbubble.gif)').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);
          }
},

selecteerHypotheek: {
    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(() => 'askName')
          break;
      case 'Starters Hypotheek':
          return bot.say(`Wat voor type woning zoek je? `)
          .then(() => bot.say(`%[🏬 Appartement](postback:hypotheekkeuze_appartement) %[🏠 Huis](postback:hypotheekkeuze_huis) %[📭 Vakantiewoning](postback:hypotheekkeuze_vakantiewoning)`))
          .then(() => 'woningType')
              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. %[💼 Zoek Hypotheek Adviseur](https://www.independer.nl/hypotheekadviseur/jelocatie.aspx)`))
            .then(() => 'finish')
          break;
        case 'Hypotheek oversluiten':
          return bot.say(`😟 Het spijt me maar op dit moment biedt Independer alleen  Starters een hypotheek.`)
          .then(()=> bot.say(`Als het allemaal wel zo ver is, wil je dan een update ontvangen? %[Ja, dat wil ik wel](postback:update_ja) %[Nee, dat hoeft niet](postback:update_nee)`))
            .then(() => 'updateOntvangen')
          break;
        default:
          return bot.say(`![](http://www.bieg.nl/beeld/speechbubble.gif)`)
            .then(() => 'processing')
          break;
      }
    }
},

updateOntvangen: {
    receive: (bot, message) => {
      switch(message.text) {
        case 'Ja, dat wil ik wel':
            return bot.say(`👍 Leuk, dan houd ik  je op de hoogte zodra er weer nieuws is.`)
            .then(() => 'update_ja');
          break;
          case 'Nee, dat hoeft niet':
              receive: () => 'bye'
              break;
          default:
            receive => 'processing'
            break;
      }
    }
},

update_ja: {
  prompt: (bot) => bot.say('Wat is je email adres?'),
      receive: (bot, message) => {
          const emailer=message.text;
          return bot.setProp('emailer', emailer)
              .then(()  => bot.say(`Ok - ✉  dan hou ik je via ${emailer} op de hoogte.`))
              .then(
                function() {
                        Smooch.updateUser({
                            givenName: 'New',
                            surname: 'Name',
                            email:'kk',
                            signedUpAt: 'pp'
                        })
                })
              .then(()  =>'lastCheck')
    }
},

update_nee: {
  receive: () => 'bye'
},

hypotheekStarter: {
    receive: () => 'askName'
},
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'
},

woningType: {
  receive: (bot, message) => {
    switch(message.text) {
        case '🏬 Appartement':
          return bot.say(`Nice!`)
          .then(() => 'vervolgVragen')
          break;
      case '🏠 Huis':
          return bot.say(`Leuk`)
          .then(() => 'vervolgVragen')
          break;
    case '📭 Vakantiewoning':
          return bot.say(`Gezellig`)
          .then(() => 'vervolgVragen')
          break;
      default:
        receive => 'processing'
        break;
        }
    }
},

vervolgVragen: {
  prompt: (bot) => bot.say('Hoe heet je eigelijk? 😋'),
          receive: (bot, message) => {
              const Name = message.text.trim().toUpperCase();
              return bot.setProp('Name', Name)
                  .then(() => bot.say('Hoi ${Name}. 📋 Ik heb nog wat vragen voor je om verder te kunnen.'))
                  .then(() => 'processing')
            }
},

lastCheck: {
    prompt: (bot) => bot.say(' Is er nog iets waar ik  je bij kan helpen?  🔶  %[Ik zoek meer informatie](postback:meerInfo) %[Nee hoor](postback:bye)'),
          receive: (bot, message) => {
            switch(message.text) {
              case 'Nee hoor':
                  receive: ()  => 'bye'
                  break;
             case 'Ik zoek meer informatie':
                  receive: () => 'speak'
                  break;
            case 'Nee':
                  receive: () => 'bye'
                  break;
            default:
              return bot.say('![](http://www.bieg.nl/beeld/speechbubble.gif)')
                .then(() => 'processing')
              break;
            }
        }
},

meerInfo: {
  return bot.say('%[Link 1](http://www.nu.nl)')
  .then(() => bot.say('%[Link 2](http://www.elle.nl)')),
   receive: () => 'processing'
},

bye: {
    prompt: (bot) => bot.say('Fijn je gesproken te hebben. Bedankt voor je tijd ⏲'),
    receive: ()  => 'finish'
},

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

finish: {
receive: () => 'finish'
}
});
<|endoftext|>


<commit_before>import { Component } from 'react';
import styles from './Pricing.module.css';
import apps from '../../lib/pro';

class Pricing extends Component {
  render() {
    let gumroadURL = 'https://gum.co/dracula-pro?wanted=true';

    if (this.props.queryParams.a) {
      gumroadURL = `https://gumroad.com/a/${this.props.queryParams.a}?wanted=true`;
    }

    return

Become a Vampire

Join 1,334+ developers using Dracula PRO every day.

Launch Promo

$99$79

one-time payment

                <svg className={styles.icon} fill="#50fa7b" width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><title>ionicons-v5-checkmark-circle</title><path d="M256,48C141.31,48,48,141.31,48,256s93.31,208,208,208,208-93.31,208-208S370.69,48,256,48ZM364.25,186.29l-134.4,160a16,16,0,0,1-12,5.71h-.27a16,16,0,0,1-11.89-5.3l-57.6-64a16,16,0,1,1,23.78-21.4l45.29,50.32L339.75,165.71a16,16,0,0,1,24.5,20.58Z"/></svg>
                {Object.keys(apps).length + 1} Themes

                <svg className={styles.icon} fill="#50fa7b" width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><title>ionicons-v5-checkmark-circle</title><path d="M256,48C141.31,48,48,141.31,48,256s93.31,208,208,208,208-93.31,208-208S370.69,48,256,48ZM364.25,186.29l-134.4,160a16,16,0,0,1-12,5.71h-.27a16,16,0,0,1-11.89-5.3l-57.6-64a16,16,0,1,1,23.78-21.4l45.29,50.32L339.75,165.71a16,16,0,0,1,24.5,20.58Z"/></svg>
                6 Variants

                <svg className={styles.icon} fill="#50fa7b" width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><title>ionicons-v5-checkmark-circle</title><path d="M256,48C141.31,48,48,141.31,48,256s93.31,208,208,208,208-93.31,208-208S370.69,48,256,48ZM364.25,186.29l-134.4,160a16,16,0,0,1-12,5.71h-.27a16,16,0,0,1-11.89-5.3l-57.6-64a16,16,0,1,1,23.78-21.4l45.29,50.32L339.75,165.71a16,16,0,0,1,24.5,20.58Z"/></svg>
                4 Hand-picked Fonts

                <svg className={styles.icon} fill="#50fa7b" width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><title>ionicons-v5-checkmark-circle</title><path d="M256,48C141.31,48,48,141.31,48,256s93.31,208,208,208,208-93.31,208-208S370.69,48,256,48ZM364.25,186.29l-134.4,160a16,16,0,0,1-12,5.71h-.27a16,16,0,0,1-11.89-5.3l-57.6-64a16,16,0,1,1,23.78-21.4l45.29,50.32L339.75,165.71a16,16,0,0,1,24.5,20.58Z"/></svg>
                1 Productivity E-book

                <svg className={styles.icon} fill="#50fa7b" width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><title>ionicons-v5-checkmark-circle</title><path d="M256,48C141.31,48,48,141.31,48,256s93.31,208,208,208,208-93.31,208-208S370.69,48,256,48ZM364.25,186.29l-134.4,160a16,16,0,0,1-12,5.71h-.27a16,16,0,0,1-11.89-5.3l-57.6-64a16,16,0,1,1,23.78-21.4l45.29,50.32L339.75,165.71a16,16,0,0,1,24.5,20.58Z"/></svg>
                1 Bonus Screencast

                <svg className={styles.icon} fill="#50fa7b" width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><title>ionicons-v5-checkmark-circle</title><path d="M256,48C141.31,48,48,141.31,48,256s93.31,208,208,208,208-93.31,208-208S370.69,48,256,48ZM364.25,186.29l-134.4,160a16,16,0,0,1-12,5.71h-.27a16,16,0,0,1-11.89-5.3l-57.6-64a16,16,0,1,1,23.78-21.4l45.29,50.32L339.75,165.71a16,16,0,0,1,24.5,20.58Z"/></svg>
                Design Files

                <svg className={styles.icon} fill="#50fa7b" width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><title>ionicons-v5-checkmark-circle</title><path d="M256,48C141.31,48,48,141.31,48,256s93.31,208,208,208,208-93.31,208-208S370.69,48,256,48ZM364.25,186.29l-134.4,160a16,16,0,0,1-12,5.71h-.27a16,16,0,0,1-11.89-5.3l-57.6-64a16,16,0,1,1,23.78-21.4l45.29,50.32L339.75,165.71a16,16,0,0,1,24.5,20.58Z"/></svg>
                Wallpapers

                <svg className={styles.icon} fill="#50fa7b" width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><title>ionicons-v5-checkmark-circle</title><path d="M256,48C141.31,48,48,141.31,48,256s93.31,208,208,208,208-93.31,208-208S370.69,48,256,48ZM364.25,186.29l-134.4,160a16,16,0,0,1-12,5.71h-.27a16,16,0,0,1-11.89-5.3l-57.6-64a16,16,0,1,1,23.78-21.4l45.29,50.32L339.75,165.71a16,16,0,0,1,24.5,20.58Z"/></svg>
                Constant updates

                <svg className={styles.icon} fill="#50fa7b" width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><title>ionicons-v5-checkmark-circle</title><path d="M256,48C141.31,48,48,141.31,48,256s93.31,208,208,208,208-93.31,208-208S370.69,48,256,48ZM364.25,186.29l-134.4,160a16,16,0,0,1-12,5.71h-.27a16,16,0,0,1-11.89-5.3l-57.6-64a16,16,0,1,1,23.78-21.4l45.29,50.32L339.75,165.71a16,16,0,0,1,24.5,20.58Z"/></svg>
                Support included

                <svg className={styles.icon} fill="#50fa7b" width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><title>ionicons-v5-checkmark-circle</title><path d="M256,48C141.31,48,48,141.31,48,256s93.31,208,208,208,208-93.31,208-208S370.69,48,256,48ZM364.25,186.29l-134.4,160a16,16,0,0,1-12,5.71h-.27a16,16,0,0,1-11.89-5.3l-57.6-64a16,16,0,1,1,23.78-21.4l45.29,50.32L339.75,165.71a16,16,0,0,1,24.5,20.58Z"/></svg>
                License for 3 computers

              Buy Dracula PRO

14 days refund (no Q/A)

Contact me to get a Team License to share with your team.

  }
}

export default Pricing;<commit_msg>Update number of Dracula PRO users<commit_after>import { Component } from 'react';
import styles from './Pricing.module.css';
import apps from '../../lib/pro';

class Pricing extends Component {
  render() {
    let gumroadURL = 'https://gum.co/dracula-pro?wanted=true';

    if (this.props.queryParams.a) {
      gumroadURL = `https://gumroad.com/a/${this.props.queryParams.a}?wanted=true`;
    }

    return

Become a Vampire

Join 1,588+ developers using Dracula PRO every day.

Launch Promo

$99$79

one-time payment

                <svg className={styles.icon} fill="#50fa7b" width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><title>ionicons-v5-checkmark-circle</title><path d="M256,48C141.31,48,48,141.31,48,256s93.31,208,208,208,208-93.31,208-208S370.69,48,256,48ZM364.25,186.29l-134.4,160a16,16,0,0,1-12,5.71h-.27a16,16,0,0,1-11.89-5.3l-57.6-64a16,16,0,1,1,23.78-21.4l45.29,50.32L339.75,165.71a16,16,0,0,1,24.5,20.58Z"/></svg>
                {Object.keys(apps).length + 1} Themes

                <svg className={styles.icon} fill="#50fa7b" width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><title>ionicons-v5-checkmark-circle</title><path d="M256,48C141.31,48,48,141.31,48,256s93.31,208,208,208,208-93.31,208-208S370.69,48,256,48ZM364.25,186.29l-134.4,160a16,16,0,0,1-12,5.71h-.27a16,16,0,0,1-11.89-5.3l-57.6-64a16,16,0,1,1,23.78-21.4l45.29,50.32L339.75,165.71a16,16,0,0,1,24.5,20.58Z"/></svg>
                6 Variants

                <svg className={styles.icon} fill="#50fa7b" width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><title>ionicons-v5-checkmark-circle</title><path d="M256,48C141.31,48,48,141.31,48,256s93.31,208,208,208,208-93.31,208-208S370.69,48,256,48ZM364.25,186.29l-134.4,160a16,16,0,0,1-12,5.71h-.27a16,16,0,0,1-11.89-5.3l-57.6-64a16,16,0,1,1,23.78-21.4l45.29,50.32L339.75,165.71a16,16,0,0,1,24.5,20.58Z"/></svg>
                4 Hand-picked Fonts

                <svg className={styles.icon} fill="#50fa7b" width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><title>ionicons-v5-checkmark-circle</title><path d="M256,48C141.31,48,48,141.31,48,256s93.31,208,208,208,208-93.31,208-208S370.69,48,256,48ZM364.25,186.29l-134.4,160a16,16,0,0,1-12,5.71h-.27a16,16,0,0,1-11.89-5.3l-57.6-64a16,16,0,1,1,23.78-21.4l45.29,50.32L339.75,165.71a16,16,0,0,1,24.5,20.58Z"/></svg>
                1 Productivity E-book

                <svg className={styles.icon} fill="#50fa7b" width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><title>ionicons-v5-checkmark-circle</title><path d="M256,48C141.31,48,48,141.31,48,256s93.31,208,208,208,208-93.31,208-208S370.69,48,256,48ZM364.25,186.29l-134.4,160a16,16,0,0,1-12,5.71h-.27a16,16,0,0,1-11.89-5.3l-57.6-64a16,16,0,1,1,23.78-21.4l45.29,50.32L339.75,165.71a16,16,0,0,1,24.5,20.58Z"/></svg>
                1 Bonus Screencast

                <svg className={styles.icon} fill="#50fa7b" width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><title>ionicons-v5-checkmark-circle</title><path d="M256,48C141.31,48,48,141.31,48,256s93.31,208,208,208,208-93.31,208-208S370.69,48,256,48ZM364.25,186.29l-134.4,160a16,16,0,0,1-12,5.71h-.27a16,16,0,0,1-11.89-5.3l-57.6-64a16,16,0,1,1,23.78-21.4l45.29,50.32L339.75,165.71a16,16,0,0,1,24.5,20.58Z"/></svg>
                Design Files

                <svg className={styles.icon} fill="#50fa7b" width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><title>ionicons-v5-checkmark-circle</title><path d="M256,48C141.31,48,48,141.31,48,256s93.31,208,208,208,208-93.31,208-208S370.69,48,256,48ZM364.25,186.29l-134.4,160a16,16,0,0,1-12,5.71h-.27a16,16,0,0,1-11.89-5.3l-57.6-64a16,16,0,1,1,23.78-21.4l45.29,50.32L339.75,165.71a16,16,0,0,1,24.5,20.58Z"/></svg>
                Wallpapers

                <svg className={styles.icon} fill="#50fa7b" width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><title>ionicons-v5-checkmark-circle</title><path d="M256,48C141.31,48,48,141.31,48,256s93.31,208,208,208,208-93.31,208-208S370.69,48,256,48ZM364.25,186.29l-134.4,160a16,16,0,0,1-12,5.71h-.27a16,16,0,0,1-11.89-5.3l-57.6-64a16,16,0,1,1,23.78-21.4l45.29,50.32L339.75,165.71a16,16,0,0,1,24.5,20.58Z"/></svg>
                Constant updates

                <svg className={styles.icon} fill="#50fa7b" width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><title>ionicons-v5-checkmark-circle</title><path d="M256,48C141.31,48,48,141.31,48,256s93.31,208,208,208,208-93.31,208-208S370.69,48,256,48ZM364.25,186.29l-134.4,160a16,16,0,0,1-12,5.71h-.27a16,16,0,0,1-11.89-5.3l-57.6-64a16,16,0,1,1,23.78-21.4l45.29,50.32L339.75,165.71a16,16,0,0,1,24.5,20.58Z"/></svg>
                Support included

                <svg className={styles.icon} fill="#50fa7b" width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><title>ionicons-v5-checkmark-circle</title><path d="M256,48C141.31,48,48,141.31,48,256s93.31,208,208,208,208-93.31,208-208S370.69,48,256,48ZM364.25,186.29l-134.4,160a16,16,0,0,1-12,5.71h-.27a16,16,0,0,1-11.89-5.3l-57.6-64a16,16,0,1,1,23.78-21.4l45.29,50.32L339.75,165.71a16,16,0,0,1,24.5,20.58Z"/></svg>
                License for 3 computers

              Buy Dracula PRO

14 days refund (no Q/A)

Contact me to get a Team License to share with your team.

  }
}

export default Pricing;<|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.trim().toUpperCase();
        return bot.say(`${groet}, wat voor soort hypotheek zoek je? `)
        .then(() => bot.say(`%[Starters hypotheek](postback:hypotheektype_starter) %[Nieuwe hypotheek](postback:hypotheektype_nieuw) %[Hypotheek oversluiten](postback:hypotheektype_oversluiten)`))
        .then(() => 'selecteerHypotheek');
    }
},

selecteerHypotheek: {
    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(() => 'askName')
          break;
      case 'Starters hypotheek':
      //  prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)
          return bot.say(`Wat voor type woning zoek je? `)
          .then(() => bot.say(`%[Appartement](postback:hypotheekkeuze_appartement) %[Huis](postback:hypotheekkeuze_huis) %[Vakantiewoning](postback:hypotheekkeuze_vakantiewoning)`))
          .then(() => 'hypotheek_starter')
              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(() => 'finish')
          break;
        case 'Hypotheek oversluiten':
          return bot.say(`Het spijt me maar op dit moment biedt Independer alleen  Starters een hypotheek.`)
          .then(()=> bot.say('Als het allemaal wel zo ver is, wil je dan een update ontvangen? %[Ja - graag](postback:update_ja) %[Nee, bedankt](postback:update_nee)'))
            .then(() => 'updateOntvangen')
          break;
        default:
          return bot.say(`...`)
            .then(() => 'processing')
          break;
      }
    }
},

updateOntvangen: {
    receive: (bot, message) => {
      switch(message.text) {
        case 'update_ja':
            return bot.say(`Laat je dan even je email achter? Dan houden we je op de hoogte...`)
            .then(() => 'update_ja')
          break;
          case 'update_nee':
              receive: () => 'bye')
              break;
          default:
            return bot.say(`...`)
              .then(() => 'processing')
            break;
}
}
},

update_ja: {
    receive: (bot, message) => {
      const emailVisitor : message.text;
      return bot.setProp('emailVisitor', emailVisitor)
      .then(()  => bot.say(`Ok - dan hou ik je via ${emailVisitor} op de hoogte.`))
      .then(() => 'bye');
    }
},

hypotheekkeuze_appartement: {
receive: (bot,message)  => {
    //  prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)
    receive: () => 'askName'
}
},
hypotheekkeuze_huis: {
//    prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)
  receive: () => 'askName'
},
hypotheekkeuze_vakantiewoning: {
//    prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)
    receive: () => 'askName'
},
hypotheektype_starter: {
    prompt: (bot) => bot.say('Pleasure meeting you - starter'),
    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'
},

askName: {
  receive: (bot, message) => {
    switch(message.text) {
        case 'Appartement':
          return bot.say(`Nice! Hoe heet je eigelijk? Dat maakt het praten een stuk makkelijker...`)
          .then(() => 'vervolgVragen')
          break;
      case 'Huis':
          return bot.say(`Leuk :) Hoe heet je eigelijk? Dat maakt het praten een stuk makkelijker...`)
          .then(() => 'vervolgVragen')
          break;
      default:
        return bot.say(`...`)
          .then(() => 'processing')
        break;
    }
    }
},

vervolgVragen: {
  receive: (bot, message) => {
        const name = message.text;
        return bot.setProp('name', name)
            .then(() => bot.say(`Hoi ${name}. Ik heb nog wat vragen voor je om verder te kunnen.`))
            .then(() => 'lastCheck');
    }
},

lastCheck: {
    // prompt: (bot) => bot.say('Is er nog iets waar ik  je bij kan helpen? %[JA](postback:nogietsanders) %[NEE](postback:bye) '),
    // .then(()  => 'processing');
},

bye: {
    prompt: (bot) => bot.say('Fijn je gesproken te hebben. Bedankt voor je tijd'),
    receive: ()  => 'finish'
},

// 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>dw<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.trim().toUpperCase();
        return bot.say(`${groet}, wat voor soort hypotheek zoek je? `)
        .then(() => bot.say(`%[Starters hypotheek](postback:hypotheektype_starter) %[Nieuwe hypotheek](postback:hypotheektype_nieuw) %[Hypotheek oversluiten](postback:hypotheektype_oversluiten)`))
        .then(() => 'selecteerHypotheek');
    }
},

selecteerHypotheek: {
    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(() => 'askName')
          break;
      case 'Starters hypotheek':
      //  prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)
          return bot.say(`Wat voor type woning zoek je? `)
          .then(() => bot.say(`%[Appartement](postback:hypotheekkeuze_appartement) %[Huis](postback:hypotheekkeuze_huis) %[Vakantiewoning](postback:hypotheekkeuze_vakantiewoning)`))
          .then(() => 'hypotheek_starter')
              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(() => 'finish')
          break;
        case 'Hypotheek oversluiten':
          return bot.say(`Het spijt me maar op dit moment biedt Independer alleen  Starters een hypotheek.`)
          .then(()=> bot.say('Als het allemaal wel zo ver is, wil je dan een update ontvangen? %[Ja - graag](postback:update_ja) %[Nee, bedankt](postback:update_nee)'))
            .then(() => 'updateOntvangen')
          break;
        default:
          return bot.say(`...`)
            .then(() => 'processing')
          break;
      }
    }
},

updateOntvangen: {
    receive: (bot, message) => {
      switch(message.text) {
        case 'update_ja':
            return bot.say(`Laat je dan even je email achter? Dan houden we je op de hoogte...`)
            .then(() => 'updateJa')
          break;
          case 'update_nee':
              receive: () => 'bye')
              break;
          default:
            return bot.say(`...`)
              .then(() => 'processing')
            break;
}
}
},

updateJa: {
    // receive: (bot, message) => {
    //   const emailVisitor : message.text;
    //   return bot.setProp('emailVisitor', emailVisitor)
    //   .then(()  => bot.say(`Ok - dan hou ik je via ${emailVisitor} op de hoogte.`))
    //   .then(() => 'bye');
    // }
    receive: () => 'processing'
},

hypotheekkeuze_appartement: {
receive: (bot,message)  => {
    //  prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)
    receive: () => 'askName'
}
},
hypotheekkeuze_huis: {
//    prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)
  receive: () => 'askName'
},
hypotheekkeuze_vakantiewoning: {
//    prompt: (bot) => bot.say(`![](http:www.bieg.nl/beeld/appartement.jpg)`)
    receive: () => 'askName'
},
hypotheektype_starter: {
    prompt: (bot) => bot.say('Pleasure meeting you - starter'),
    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'
},

askName: {
  receive: (bot, message) => {
    switch(message.text) {
        case 'Appartement':
          return bot.say(`Nice! Hoe heet je eigelijk? Dat maakt het praten een stuk makkelijker...`)
          .then(() => 'vervolgVragen')
          break;
      case 'Huis':
          return bot.say(`Leuk :) Hoe heet je eigelijk? Dat maakt het praten een stuk makkelijker...`)
          .then(() => 'vervolgVragen')
          break;
      default:
        return bot.say(`...`)
          .then(() => 'processing')
        break;
    }
    }
},

vervolgVragen: {
  receive: (bot, message) => {
        const name = message.text;
        return bot.setProp('name', name)
            .then(() => bot.say(`Hoi ${name}. Ik heb nog wat vragen voor je om verder te kunnen.`))
            .then(() => 'lastCheck');
    }
},

lastCheck: {
    // prompt: (bot) => bot.say('Is er nog iets waar ik  je bij kan helpen? %[JA](postback:nogietsanders) %[NEE](postback:bye) '),
    // .then(()  => 'processing');
},

bye: {
    prompt: (bot) => bot.say('Fijn je gesproken te hebben. Bedankt voor je tijd'),
    receive: ()  => 'finish'
},

// 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|>