<commit_before>
(function() {

var slideSpeed = 20;
var slideInterval = 0;

var currentPage = null;
var currentDialog = null;
var currentWidth = 0;
var currentHash = location.hash;
var hashPrefix = "#_";
var pageHistory = [];
var newPageCount = 0;
var checkTimer;

// *************************************************************************************************

window.iui =
{
    showPage: function(page, backwards)
    {
        if (page)
        {
            if (currentDialog)
            {
                currentDialog.removeAttribute("selected");
                currentDialog = null;
            }

            if (hasClass(page, "dialog"))
                showDialog(page);
            else
            {
                var fromPage = currentPage;
                currentPage = page;

                if (fromPage)
                    setTimeout(slidePages, 0, fromPage, page, backwards);
                else
                    updatePage(page, fromPage);
            }
        }
    },

    showPageById: function(pageId)
    {
        var page = $(pageId);
        if (page)
        {
            var index = pageHistory.indexOf(pageId);
            var backwards = index != -1;
            if (backwards)
                pageHistory.splice(index, pageHistory.length);

            iui.showPage(page, backwards);
        }
    },

    showPageByHref: function(href, args, method, replace, cb)
    {
        var req = new XMLHttpRequest();
        req.onerror = function()
        {
            if (cb)
                cb(false);
        };

        req.onreadystatechange = function()
        {
            if (req.readyState == 4)
            {
                if (replace)
                    replaceElementWithSource(replace, req.responseText);
                else
                {
                    var frag = document.createElement("div");
                    frag.innerHTML = req.responseText;
                    iui.insertPages(frag.childNodes);
                }
                if (cb)
                    setTimeout(cb, 1000, true);
            }
        };

        if (args)
        {
            req.open(method || "GET", href, true);
            req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
            req.setRequestHeader("Content-Length", args.length);
            req.send(args.join("&"));
        }
        else
        {
            req.open(method || "GET", href, true);
            req.send(null);
        }
    },

    insertPages: function(nodes)
    {
        var targetPage;
        for (var i = 0; i < nodes.length; ++i)
        {
            var child = nodes[i];
            if (child.nodeType == 1)
            {
                if (!child.id)
                    child.id = "__" + (++newPageCount) + "__";

                var clone = $(child.id);
                if (clone)
                    clone.parentNode.replaceChild(child, clone);
                else
                    document.body.appendChild(child);

                if (child.getAttribute("selected") == "true" || !targetPage)
                    targetPage = child;

                --i;
            }
        }

        if (targetPage)
            iui.showPage(targetPage);
    },

    getSelectedPage: function()
    {
        for (var child = document.body.firstChild; child; child = child.nextSibling)
        {
            if (child.nodeType == 1 && child.getAttribute("selected") == "true")
                return child;
        }
    }
};

// *************************************************************************************************

addEventListener("load", function(event)
{
    var page = iui.getSelectedPage();
    if (page)
        iui.showPage(page);

    setTimeout(preloadImages, 0);
    setTimeout(checkOrientAndLocation, 0);
    checkTimer = setInterval(checkOrientAndLocation, 300);
}, false);

addEventListener("click", function(event)
{
    var link = findParent(event.target, "a");
    if (link)
    {
        function unselect() { link.removeAttribute("selected"); }

        if (link.href && link.hash && link.hash != "#")
        {
            link.setAttribute("selected", "true");
            iui.showPage($(link.hash.substr(1)));
            setTimeout(unselect, 500);
        }
        else if (link == $("backButton"))
            history.back();
        else if (link.getAttribute("type") == "submit")
            submitForm(findParent(link, "form"));
        else if (link.getAttribute("type") == "cancel")
            cancelDialog(findParent(link, "form"));
        else if (link.target == "_replace")
        {
            link.setAttribute("selected", "progress");
            iui.showPageByHref(link.href, null, null, link, unselect);
        }
        else if (!link.target)
        {
            link.setAttribute("selected", "progress");
            iui.showPageByHref(link.href, null, null, null, unselect);
        }
        else
            return;

        event.preventDefault();
    }
}, true);

addEventListener("click", function(event)
{
    var div = findParent(event.target, "div");
    if (div && hasClass(div, "toggle"))
    {
        div.setAttribute("toggled", div.getAttribute("toggled") != "true");
        event.preventDefault();
    }
}, true);

function checkOrientAndLocation()
{
    if (window.innerWidth != currentWidth)
    {
        currentWidth = window.innerWidth;
        var orient = currentWidth == 320 ? "profile" : "landscape";
        document.body.setAttribute("orient", orient);
        setTimeout(scrollTo, 100, 0, 1);
    }

    if (location.hash != currentHash)
    {
        var pageId = location.hash.substr(hashPrefix.length)
        iui.showPageById(pageId);
    }
}

function showDialog(page)
{
    currentDialog = page;
    page.setAttribute("selected", "true");

    if (hasClass(page, "dialog") && !page.target)
        showForm(page);
}

function showForm(form)
{
    form.onsubmit = function(event)
    {
        event.preventDefault();
        submitForm(form);
    };

    form.onclick = function(event)
    {
        if (event.target == form && hasClass(form, "dialog"))
            cancelDialog(form);
    };
}

function cancelDialog(form)
{
    form.removeAttribute("selected");
}

function updatePage(page, fromPage)
{
    if (!page.id)
        page.id = "__" + (++newPageCount) + "__";

    location.href = currentHash = hashPrefix + page.id;
    pageHistory.push(page.id);

    var pageTitle = $("pageTitle");
    if (page.title)
        pageTitle.innerHTML = page.title;

    if (page.localName.toLowerCase() == "form" && !page.target)
        showForm(page);

    var backButton = $("backButton");
    if (backButton)
    {
        var prevPage = $(pageHistory[pageHistory.length-2]);
        if (prevPage && !page.getAttribute("hideBackButton"))
        {
            backButton.style.display = "inline";
            backButton.innerHTML = prevPage.title ? prevPage.title : "Back";
        }
        else
            backButton.style.display = "none";
    }
}

function slidePages(fromPage, toPage, backwards)
{
    var axis = (backwards ? fromPage : toPage).getAttribute("axis");
    if (axis == "y")
        (backwards ? fromPage : toPage).style.top = "100%";
    else
        toPage.style.left = "100%";

    toPage.setAttribute("selected", "true");
    scrollTo(0, 1);
    clearInterval(checkTimer);

    var percent = 100;
    slide();
    var timer = setInterval(slide, slideInterval);

    function slide()
    {
        percent -= slideSpeed;
        if (percent <= 0)
        {
            percent = 0;
            if (!hasClass(toPage, "dialog"))
                fromPage.removeAttribute("selected");
            clearInterval(timer);
            checkTimer = setInterval(checkOrientAndLocation, 300);
            setTimeout(updatePage, 0, toPage, fromPage);
        }

        if (axis == "y")
        {
            backwards
                ? fromPage.style.top = (100-percent) + "%"
                : toPage.style.top = percent + "%";
        }
        else
        {
            fromPage.style.left = (backwards ? (100-percent) : (percent-100)) + "%";
            toPage.style.left = (backwards ? -percent : percent) + "%";
        }
    }
}

function preloadImages()
{
    var preloader = document.createElement("div");
    preloader.id = "preloader";
    document.body.appendChild(preloader);
}

function submitForm(form)
{
    iui.showPageByHref(form.action || "POST", encodeForm(form), form.method);
}

function encodeForm(form)
{
    function encode(inputs)
    {
        for (var i = 0; i < inputs.length; ++i)
        {
            if (inputs[i].name)
                args.push(inputs[i].name + "=" + escape(inputs[i].value));
        }
    }

    var args = [];
    encode(form.getElementsByTagName("input"));
    encode(form.getElementsByTagName("select"));
    return args;
}

function findParent(node, localName)
{
    while (node && (node.nodeType != 1 || node.localName.toLowerCase() != localName))
        node = node.parentNode;
    return node;
}

function hasClass(self, name)
{
    var re = new RegExp("(^|\\s)"+name+"($|\\s)");
    return re.exec(self.getAttribute("class")) != null;
}

function replaceElementWithSource(replace, source)
{
    var page = replace.parentNode;
    var parent = replace;
    while (page.parentNode != document.body)
    {
        page = page.parentNode;
        parent = parent.parentNode;
    }

    var frag = document.createElement(parent.localName);
    frag.innerHTML = source;

    page.removeChild(parent);

    while (frag.firstChild)
        page.appendChild(frag.firstChild);
}

function $(id) { return document.getElementById(id); }
function ddd() { console.log.apply(console, arguments); }

})();
<commit_msg>Add copyright<commit_after>/*
 	 Copyright (c) 2007, iUI Project Members
	 See LICENSE.txt for licensing terms
 */

(function() {

var slideSpeed = 20;
var slideInterval = 0;

var currentPage = null;
var currentDialog = null;
var currentWidth = 0;
var currentHash = location.hash;
var hashPrefix = "#_";
var pageHistory = [];
var newPageCount = 0;
var checkTimer;

// *************************************************************************************************

window.iui =
{
    showPage: function(page, backwards)
    {
        if (page)
        {
            if (currentDialog)
            {
                currentDialog.removeAttribute("selected");
                currentDialog = null;
            }

            if (hasClass(page, "dialog"))
                showDialog(page);
            else
            {
                var fromPage = currentPage;
                currentPage = page;

                if (fromPage)
                    setTimeout(slidePages, 0, fromPage, page, backwards);
                else
                    updatePage(page, fromPage);
            }
        }
    },

    showPageById: function(pageId)
    {
        var page = $(pageId);
        if (page)
        {
            var index = pageHistory.indexOf(pageId);
            var backwards = index != -1;
            if (backwards)
                pageHistory.splice(index, pageHistory.length);

            iui.showPage(page, backwards);
        }
    },

    showPageByHref: function(href, args, method, replace, cb)
    {
        var req = new XMLHttpRequest();
        req.onerror = function()
        {
            if (cb)
                cb(false);
        };

        req.onreadystatechange = function()
        {
            if (req.readyState == 4)
            {
                if (replace)
                    replaceElementWithSource(replace, req.responseText);
                else
                {
                    var frag = document.createElement("div");
                    frag.innerHTML = req.responseText;
                    iui.insertPages(frag.childNodes);
                }
                if (cb)
                    setTimeout(cb, 1000, true);
            }
        };

        if (args)
        {
            req.open(method || "GET", href, true);
            req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
            req.setRequestHeader("Content-Length", args.length);
            req.send(args.join("&"));
        }
        else
        {
            req.open(method || "GET", href, true);
            req.send(null);
        }
    },

    insertPages: function(nodes)
    {
        var targetPage;
        for (var i = 0; i < nodes.length; ++i)
        {
            var child = nodes[i];
            if (child.nodeType == 1)
            {
                if (!child.id)
                    child.id = "__" + (++newPageCount) + "__";

                var clone = $(child.id);
                if (clone)
                    clone.parentNode.replaceChild(child, clone);
                else
                    document.body.appendChild(child);

                if (child.getAttribute("selected") == "true" || !targetPage)
                    targetPage = child;

                --i;
            }
        }

        if (targetPage)
            iui.showPage(targetPage);
    },

    getSelectedPage: function()
    {
        for (var child = document.body.firstChild; child; child = child.nextSibling)
        {
            if (child.nodeType == 1 && child.getAttribute("selected") == "true")
                return child;
        }
    }
};

// *************************************************************************************************

addEventListener("load", function(event)
{
    var page = iui.getSelectedPage();
    if (page)
        iui.showPage(page);

    setTimeout(preloadImages, 0);
    setTimeout(checkOrientAndLocation, 0);
    checkTimer = setInterval(checkOrientAndLocation, 300);
}, false);

addEventListener("click", function(event)
{
    var link = findParent(event.target, "a");
    if (link)
    {
        function unselect() { link.removeAttribute("selected"); }

        if (link.href && link.hash && link.hash != "#")
        {
            link.setAttribute("selected", "true");
            iui.showPage($(link.hash.substr(1)));
            setTimeout(unselect, 500);
        }
        else if (link == $("backButton"))
            history.back();
        else if (link.getAttribute("type") == "submit")
            submitForm(findParent(link, "form"));
        else if (link.getAttribute("type") == "cancel")
            cancelDialog(findParent(link, "form"));
        else if (link.target == "_replace")
        {
            link.setAttribute("selected", "progress");
            iui.showPageByHref(link.href, null, null, link, unselect);
        }
        else if (!link.target)
        {
            link.setAttribute("selected", "progress");
            iui.showPageByHref(link.href, null, null, null, unselect);
        }
        else
            return;

        event.preventDefault();
    }
}, true);

addEventListener("click", function(event)
{
    var div = findParent(event.target, "div");
    if (div && hasClass(div, "toggle"))
    {
        div.setAttribute("toggled", div.getAttribute("toggled") != "true");
        event.preventDefault();
    }
}, true);

function checkOrientAndLocation()
{
    if (window.innerWidth != currentWidth)
    {
        currentWidth = window.innerWidth;
        var orient = currentWidth == 320 ? "profile" : "landscape";
        document.body.setAttribute("orient", orient);
        setTimeout(scrollTo, 100, 0, 1);
    }

    if (location.hash != currentHash)
    {
        var pageId = location.hash.substr(hashPrefix.length)
        iui.showPageById(pageId);
    }
}

function showDialog(page)
{
    currentDialog = page;
    page.setAttribute("selected", "true");

    if (hasClass(page, "dialog") && !page.target)
        showForm(page);
}

function showForm(form)
{
    form.onsubmit = function(event)
    {
        event.preventDefault();
        submitForm(form);
    };

    form.onclick = function(event)
    {
        if (event.target == form && hasClass(form, "dialog"))
            cancelDialog(form);
    };
}

function cancelDialog(form)
{
    form.removeAttribute("selected");
}

function updatePage(page, fromPage)
{
    if (!page.id)
        page.id = "__" + (++newPageCount) + "__";

    location.href = currentHash = hashPrefix + page.id;
    pageHistory.push(page.id);

    var pageTitle = $("pageTitle");
    if (page.title)
        pageTitle.innerHTML = page.title;

    if (page.localName.toLowerCase() == "form" && !page.target)
        showForm(page);

    var backButton = $("backButton");
    if (backButton)
    {
        var prevPage = $(pageHistory[pageHistory.length-2]);
        if (prevPage && !page.getAttribute("hideBackButton"))
        {
            backButton.style.display = "inline";
            backButton.innerHTML = prevPage.title ? prevPage.title : "Back";
        }
        else
            backButton.style.display = "none";
    }
}

function slidePages(fromPage, toPage, backwards)
{
    var axis = (backwards ? fromPage : toPage).getAttribute("axis");
    if (axis == "y")
        (backwards ? fromPage : toPage).style.top = "100%";
    else
        toPage.style.left = "100%";

    toPage.setAttribute("selected", "true");
    scrollTo(0, 1);
    clearInterval(checkTimer);

    var percent = 100;
    slide();
    var timer = setInterval(slide, slideInterval);

    function slide()
    {
        percent -= slideSpeed;
        if (percent <= 0)
        {
            percent = 0;
            if (!hasClass(toPage, "dialog"))
                fromPage.removeAttribute("selected");
            clearInterval(timer);
            checkTimer = setInterval(checkOrientAndLocation, 300);
            setTimeout(updatePage, 0, toPage, fromPage);
        }

        if (axis == "y")
        {
            backwards
                ? fromPage.style.top = (100-percent) + "%"
                : toPage.style.top = percent + "%";
        }
        else
        {
            fromPage.style.left = (backwards ? (100-percent) : (percent-100)) + "%";
            toPage.style.left = (backwards ? -percent : percent) + "%";
        }
    }
}

function preloadImages()
{
    var preloader = document.createElement("div");
    preloader.id = "preloader";
    document.body.appendChild(preloader);
}

function submitForm(form)
{
    iui.showPageByHref(form.action || "POST", encodeForm(form), form.method);
}

function encodeForm(form)
{
    function encode(inputs)
    {
        for (var i = 0; i < inputs.length; ++i)
        {
            if (inputs[i].name)
                args.push(inputs[i].name + "=" + escape(inputs[i].value));
        }
    }

    var args = [];
    encode(form.getElementsByTagName("input"));
    encode(form.getElementsByTagName("select"));
    return args;
}

function findParent(node, localName)
{
    while (node && (node.nodeType != 1 || node.localName.toLowerCase() != localName))
        node = node.parentNode;
    return node;
}

function hasClass(self, name)
{
    var re = new RegExp("(^|\\s)"+name+"($|\\s)");
    return re.exec(self.getAttribute("class")) != null;
}

function replaceElementWithSource(replace, source)
{
    var page = replace.parentNode;
    var parent = replace;
    while (page.parentNode != document.body)
    {
        page = page.parentNode;
        parent = parent.parentNode;
    }

    var frag = document.createElement(parent.localName);
    frag.innerHTML = source;

    page.removeChild(parent);

    while (frag.firstChild)
        page.appendChild(frag.firstChild);
}

function $(id) { return document.getElementById(id); }
function ddd() { console.log.apply(console, arguments); }

})();
<|endoftext|>


<commit_before>////
// reply tweet entry-content

var jsdom = require('jsdom');
var fs = require('fs');
var jQueryPath = LIBRARY_PATH + 'jquery-1.6.1.min.js';
var jQuery = fs.readFileSync(jQueryPath).toString();

exports.replyPattern = /https?:\/\/twitter.com(\/#!)?(\/([^\/]+)\/status(es)?\/\d+)/;

exports.reply = function(client, nick, to, result) {
  jsdom.env({
    html: "https://mobile.twitter.com" + result[2],
    src: [jQuery],
    done: function(error, window) {
      var screenName = result[3];
      var tweet = window.$("div#main-content div.tweet-text").text();
      var lines = tweet.split("\n");
      if (lines.length > 1) {
          client.notice(to, screenName + ":");
          lines.forEach(function(line){
              if (line == '') line = ' ';
              client.notice(to, line);
          });
      }
      else {
          client.notice(to, screenName + ": " + tweet);
      }
    }
  });
}
<commit_msg>jsdom + jQuery をやめて cheerio をつかうようにした<commit_after>////
// reply tweet entry-content

var request = require('request');
var cheerio = require('cheerio');

exports.replyPattern = /https?:\/\/twitter.com(\/#!)?(\/([^\/]+)\/status(es)?\/\d+)/;

exports.reply = function(client, nick, to, result) {
  var pageURL = "https://mobile.twitter.com" + result[2];

  request.get({url : pageURL, encoding : null, headers : {"User-Agent" : "gobou"}}, function(err, response, body){
    if (err) {
      client.notice(to, 'ページ取得失敗…');
      return;
    }

    $ = cheerio.load(body, {lowerCaseTags:true, xmlMode:true});

    var screenName = result[3];
    var tweet = $("div#main-content div.tweet-text").text();
    var lines = tweet.split("\n");

    if (lines.length > 1) {
        client.notice(to, screenName + ":");
        lines.forEach(function(line){
            if (line == '') line = ' ';
            client.notice(to, line);
        });
    }
    else {
        client.notice(to, screenName + ": " + tweet);
    }
  });
}
<|endoftext|>


<commit_before>
console.log('Starting monitor...');

var request = require('request');

var requestOptions = {
    url: 'https://prairielearn2.engr.illinois.edu:/questions/Cart2Polar/2342/client.js',
    timeout: 10000
};

var testInterval = 60 * 1000; // ms
var nFailuresBeforeSend = 2;
var errorRateLimit = 10 * 60 * 1000; // ms
var heartbeatHourOfDay = 9;
var heartbeatRateLimit = 12 * 60 * 60 * 1000; // ms

var nCurrentFails = 0;
var errorLastTime = 0;
var heartbeatLastTime = 0;

var config = {};

// Twilio Credentials
config.accountSid = 'FILL_IN_THIS_ACCOUNT_SID'; // override in config.json
config.authToken = 'FILL_IN_THIS_AUTH_TOKEN';
config.toNumber = "+19998887777";
config.fromNumber = "+12223334444";

if (fs.existsSync('config.json')) {
    try {
        fileConfig = JSON.parse(fs.readFileSync('config.json', {encoding: 'utf8'}));
        _.defaults(fileConfig, config);
        config = fileConfig;
    } catch (e) {
        console.log("Error reading config.json:", e);
        process.exit(1);
    }
} else {
    console.log("config.json not found, using default configuration...");
}

//require the Twilio module and create a REST client
var twilioClient = require('twilio')(accountSid, authToken);

var sendSMS = function(msg, callback) {
    console.log("Sending SMS:", msg);
    twilioClient.messages.create({
	to: config.toNumber,
	from: config.fromNumber,
	body: msg,
    }, function(err, message) {
        if (err) {
	    console.log("Error sending SMS", err, message);
        } else {
            console.log("Successfully sent SMS");
            callback();
        }
    });
};

var doTest = function() {
    request(requestOptions, function(error, response, body) {
        // heartbeat
        if ((new Date()).getHours() === heartbeatHourOfDay)
            if (Date.now() - heartbeatLastTime > heartbeatRateLimit)
                sendSMS("heartbeat", function() {
                    heartbeatLastTime = Date.now();
                });

        // monitor
        var msg = null;
        if (!error && response.statusCode === 200) {
            if (!/SimpleClient/.test(body))
                msg = "incorrect body";
        } else {
            msg = (error ? error : ("statusCode = " + response.statusCode));
        }

        // no error
        if (msg === null) {
            console.log((new Date()).toISOString(), "ok");
            nCurrentFails = 0;
            return;
        }

        // error detected
        nCurrentFails++;
        console.log((new Date()).toISOString(), "error", msg, nCurrentFails);
        if (nCurrentFails >= nFailuresBeforeSend) {
            if (Date.now() - errorLastTime > errorRateLimit) {
                sendSMS("error: " + msg, function() {
                    errorLastTime = Date.now();
                });
            } else {
                console.log((new Date()).toISOString(), "SMS rate limit exceeded, no further action");
            }
        } else {
            console.log((new Date()).toISOString(), "number of successive failures " + nCurrentFails + " is less than " + nFailuresBeforeSend + ", no futher action");
        }
    });
};

doTest();
setInterval(doTest, testInterval);
<commit_msg>fix monitor script<commit_after>
console.log('Starting monitor...');

var request = require('request');
var fs = require('fs');

var requestOptions = {
    url: 'https://prairielearn2.engr.illinois.edu:/questions/Cart2Polar/2342/client.js',
    timeout: 10000
};

var testInterval = 60 * 1000; // ms
var nFailuresBeforeSend = 2;
var errorRateLimit = 10 * 60 * 1000; // ms
var heartbeatHourOfDay = 9;
var heartbeatRateLimit = 12 * 60 * 60 * 1000; // ms

var nCurrentFails = 0;
var errorLastTime = 0;
var heartbeatLastTime = 0;

var config = {};

// Twilio Credentials
config.accountSid = 'FILL_IN_THIS_ACCOUNT_SID'; // override in config.json
config.authToken = 'FILL_IN_THIS_AUTH_TOKEN';
config.toNumber = "+19998887777";
config.fromNumber = "+12223334444";

if (fs.existsSync('config.json')) {
    try {
        fileConfig = JSON.parse(fs.readFileSync('config.json', {encoding: 'utf8'}));
        _.defaults(fileConfig, config);
        config = fileConfig;
    } catch (e) {
        console.log("Error reading config.json:", e);
        process.exit(1);
    }
} else {
    console.log("config.json not found, using default configuration...");
}

//require the Twilio module and create a REST client
var twilioClient = require('twilio')(accountSid, authToken);

var sendSMS = function(msg, callback) {
    console.log("Sending SMS:", msg);
    twilioClient.messages.create({
	to: config.toNumber,
	from: config.fromNumber,
	body: msg,
    }, function(err, message) {
        if (err) {
	    console.log("Error sending SMS", err, message);
        } else {
            console.log("Successfully sent SMS");
            callback();
        }
    });
};

var doTest = function() {
    request(requestOptions, function(error, response, body) {
        // heartbeat
        if ((new Date()).getHours() === heartbeatHourOfDay)
            if (Date.now() - heartbeatLastTime > heartbeatRateLimit)
                sendSMS("heartbeat", function() {
                    heartbeatLastTime = Date.now();
                });

        // monitor
        var msg = null;
        if (!error && response.statusCode === 200) {
            if (!/SimpleClient/.test(body))
                msg = "incorrect body";
        } else {
            msg = (error ? error : ("statusCode = " + response.statusCode));
        }

        // no error
        if (msg === null) {
            console.log((new Date()).toISOString(), "ok");
            nCurrentFails = 0;
            return;
        }

        // error detected
        nCurrentFails++;
        console.log((new Date()).toISOString(), "error", msg, nCurrentFails);
        if (nCurrentFails >= nFailuresBeforeSend) {
            if (Date.now() - errorLastTime > errorRateLimit) {
                sendSMS("error: " + msg, function() {
                    errorLastTime = Date.now();
                });
            } else {
                console.log((new Date()).toISOString(), "SMS rate limit exceeded, no further action");
            }
        } else {
            console.log((new Date()).toISOString(), "number of successive failures " + nCurrentFails + " is less than " + nFailuresBeforeSend + ", no futher action");
        }
    });
};

doTest();
setInterval(doTest, testInterval);
<|endoftext|>


<commit_before>//Start Program
<commit_msg>Second commit<commit_after>var greenColor = '#4fc14e';
var redColor = '#FF5454';
var yellowColor = '#FFAA54';
var blueColor = '#3498DB';

var redIndicator = "https://rawgithub.com/ccux/airsense/master/status-red.svg";
var yellowIndicator = "https://rawgithub.com/ccux/airsense/master/status-yellow.svg";
var blueIndicator = "https://rawgithub.com/ccux/airsense/master/status-blue.svg";
var greenIndicator = "https://rawgithub.com/ccux/airsense/master/status-green.svg";

var status = 0;

var numberOfRooms = 5;
var rooms = [];

var roomNames = ["Living Room",
				"Kitchen",
				"Bedroom",
				"Kids Room",
				"Room"];

var roomIcons = [
				"https://raw.githubusercontent.com/ccux/airsense/master/Living%20room%402x.png",
				"https://raw.githubusercontent.com/ccux/airsense/master/Kitchen%402x.png",
				"https://raw.githubusercontent.com/ccux/airsense/master/Bedroom%402x.png",
				"https://raw.githubusercontent.com/ccux/airsense/master/Children%20Room%402x.png",
				"https://raw.githubusercontent.com/ccux/airsense/master/Office%402x.png"];

function greenStatus () {
//Green status
		document.getElementById("Status-Back-Div").style.backgroundColor = greenColor;
    document.getElementById("Status-Image").src = "https://daks2k3a4ib2z.cloudfront.net/58dab8fd2bebde920b1f3557/58ea9d944361b51e6cff8d01_Status-4.svg";
    document.getElementById("Status-Heading").innerHTML = "RIGTIG GODT INDEKLIMA";
    document.getElementById("Status-Heading").style.color = greenColor;
    document.getElementById("Status-Heading-Text").innerHTML = "Din bolig har et rigtig godt og sundt indeklima.";
}

function blueStatus () {
	document.getElementById("Status-Back-Div").style.backgroundColor = blueColor;
    document.getElementById("Status-Image").src = "https://daks2k3a4ib2z.cloudfront.net/58dab8fd2bebde920b1f3557/58ea9d9424c32e23eb60554c_Status-3.svg"
    document.getElementById("Status-Heading").innerHTML = "SUNDT INDEKLIMA";
    document.getElementById("Status-Heading").style.color = blueColor;
    document.getElementById("Status-Heading-Text").innerHTML = "Din bolig trænger til udluftning i *RUM*, og der er høj luftfugtighed i *RUM*";
}

function yellowStatus () {
		document.getElementById("Status-Back-Div").style.backgroundColor = yellowColor;
    document.getElementById("Status-Image").src = "https://daks2k3a4ib2z.cloudfront.net/58dab8fd2bebde920b1f3557/58ea9d9455b628679c1a1a38_Status-2.svg"
    document.getElementById("Status-Heading").innerHTML = "KAN FORBEDRES";
    document.getElementById("Status-Heading").style.color = yellowColor;
    document.getElementById("Status-Heading-Text").innerHTML = "Din bolig kunne trænge til udluftning i *RUM*, og der er høj luftfugtighed i *RUM*";
}

function redStatus () {
		document.getElementById("Status-Back-Div").style.backgroundColor = redColor;
    document.getElementById("Status-Image").src = "https://daks2k3a4ib2z.cloudfront.net/58dab8fd2bebde920b1f3557/58ea9d94b543ae4fe7653865_Status-1.svg"
    document.getElementById("Status-Heading").innerHTML = "CRITICAL INDOOR CLIMATE";
    document.getElementById("Status-Heading").style.color = redColor;
    document.getElementById("Status-Heading-Text").innerHTML = "Your home needs ventilation in *ROOM*, and the air humidity is too high in *ROOM*.";
}

//Create a new Room object
function Room() {
	this.name = "";
	this.sensorID = "";
	this.icon = "";
	this.temp = "";
	this.humidity = "";
	this.airqual = "";
	this.sensorDetected = false;
	//Create Room
	//var room = new Room;
}

//Create a random number between 2 parameter values
function randomize (min, max) {
	var result = (Math.floor((Math.random() * (max-min+1) + min)));
	return result;
}

//Create a random temperature between 2 values
function randomizeTemperature () {
	var min = 18;
	var max = 26;
	return (randomize(min, max));
}

//Create a random humidity between 2 values
function randomizeHumidity () {
	var min = 30;
	var max = 80;
	return (randomize(min, max));
}

//Create a random AirQuality between 2 values
function randomizeAirQual () {
	var min = 400;
	var max = 1600;
	return (randomize(min, max));
}

//Create a random Sensor ID
function sensorID()
{
    var text = "";
    var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

    for( var i=0; i < 12; i++ )
        text += possible.charAt(Math.floor(Math.random() * possible.length));

    return text;
}

//Create the rooms and add the to the rooms array
function createRooms () {
for (var i = 0; i < numberOfRooms; i++) {
var myRoom = new Room;

if (i <= 3) {
	myRoom.icon = roomIcons[i];
	myRoom.name = roomNames[i];

}
else {
	myRoom.icon = roomIcons[4];
	myRoom.name = "" + roomNames[4] + " " + (i - 3);
}

	myRoom.sensorID = sensorID();
	myRoom.temp = randomizeTemperature();
	myRoom.humidity = randomizeHumidity();

  /*DEMO*/
  if (returnHumidityStatus(myRoom.humidity) > 2)
  {
  myRoom.humidity = randomizeHumidity();
  }

	myRoom.airqual = randomizeAirQual();

  /*DEMO*/
  if (returnAirQualStatus(myRoom.airqual) > 2)
  {
  myRoom.airqual = randomizeAirQual();
  }

	myRoom.sensorDetected = true;

//Add the room to the rooms array
rooms.push(myRoom);
//console.log(rooms);
}
//Sort room array based on
rooms.sort(function(a, b){return getRoomStatus(b)-getRoomStatus(a)});

//Print array
console.log("1 " + getRoomStatus(rooms[0]));
console.log("2 " + getRoomStatus(rooms[1]));
console.log("3 " + getRoomStatus(rooms[2]));
console.log("4 " + getRoomStatus(rooms[3]));
}

function getRoomStatus (room) {

    var midResult = 0;
    var hum = returnHumidityStatus(room.humidity);
    var air = returnAirQualStatus(room.airqual)
    midResult += hum + air;

    return midResult;
}

function calculateOverallStatus () {
//First calculate the individual status of each room based on the three factors
status = 0;

console.log("Status 0: " + status);

var midResult = 0;

for (var i = rooms.length - 1; i >= 0; i--) {

var hum = returnHumidityStatus(rooms[i].humidity);
var air = returnAirQualStatus(rooms[i].airqual)

console.log("Hum status: " + hum);
console.log("Air status: " + air);

midResult += hum + air;

console.log("Status " + i + " " + midResult);
}

status += midResult;

console.log("Status pre /: " + status);

status /= (rooms.length/* * 2*/);

console.log("Total status: " + status);

var color = "";

//If the status is 3 or above
if (status >= 3) {
	redStatus();
}
//Else If the status is above 2
else if (status > 2) {
  yellowStatus();

}
//Else If the status is above 1.5
else if (status >= 1.5) {
  blueStatus();

}
//Else If the status is lass or equal to 1.5
else if (status < 1.5) {
	greenStatus();
}
}

function returnHumidityStatus (value) {

var greenColorMin = 41;
var greenColorMax = 59;
var yellowColorMin = 0;
var yellowColorMax = 40;
var redColorMin = 60;
var redColorMax = 100;

if (value > redColorMin)
{
//console.log('RedColor ', value);
return 3;
}
else if (value > yellowColorMax && value < redColorMin) {
//console.log('GreenColor ', value);
return 0;
}
else {
//console.log('YellowColor ', value);
return 2;
}

}

function returnAirQualStatus (value) {

var greenColorMin = 0;
var greenColorMax = 999;
var yellowColorMin = 1000;
var yellowColorMax = 1299;
var redColorMin = 1300;
var redColorMax = 1600;

if (value > redColorMin)
{
//console.log('RedColor ', value);
return 3;
}
else if (value > greenColorMax && value < redColorMin) {
//console.log('YellowColor ', value);
return 2;
}
else {
//console.log('GreenColor ', value);
return 0;
}
}

function humidityColor (value) {
var colorStatus = returnHumidityStatus(value);

console.log('The Color Value is: ' + value + " - And the Color Status is " + colorStatus);

if (colorStatus >= 3)
{
//console.log('RedColor ', value);
return redColor;
}
else if (colorStatus === 0) {
//console.log('GreenColor ', value);
return greenColor;
}
else if (colorStatus === 2){
//console.log('YellowColor ', value);
return yellowColor;
}
else {
return greenColor;
}
}

function airQualColor (value) {
var colorStatus = returnAirQualStatus(value);
if (colorStatus >= 3)
{
//console.log('RedColor ', value);
return redColor;
}
else if (colorStatus === 0) {
//console.log('GreenColor ', value);
return greenColor;
}
else if (colorStatus === 2){
//console.log('YellowColor ', value);
return yellowColor;
}
else {
return greenColor;
}
}

function returnAirQualStatusImage (value) {
	if (value === redColor) {
		return redIndicator;
	}
	else if (value === yellowColor) {
		return yellowIndicator;
	}
	else {
		return greenIndicator;
	}
}

function setRoomDetailsOnDom () {

//Loop trough the rooms and set the corresponding values
for (var i = rooms.length - 1; i >= 0; i--) {

//Set the name
var roomTitle = document.getElementsByClassName('room-block-title')[i];
//console.log(roomTitle);
roomTitle.innerHTML = rooms[i].name.toUpperCase();

//Set the temperature
var temperature = document.getElementsByClassName('temperature-number')[i];
temperature.innerHTML = rooms[i].temp;

//Set Humidity color
var humidity = document.getElementsByClassName('room-block-humidity')[i];
humidity.innerHTML = rooms[i].humidity + "%";
var statusColor = humidityColor(rooms[i].humidity);
humidity.style.color = statusColor;
console.log("Color is: ", statusColor);
//console.log("TEST " + document.getElementsByClassName('room-block-humidity')[0]);

var roomIcon = document.getElementsByClassName('room-block-icon')[i];
roomIcon.src = rooms[i].icon;

var airQualIcon = document.getElementsByClassName('room-block-airquality-status-image')[i];
var airQualIconSrc = returnAirQualStatusImage(airQualColor(rooms[i].airqual))
airQualIcon.src = airQualIconSrc;
}
}

// ################################ RUN PROGRAM ##################################################
createRooms();
calculateOverallStatus();

$('document').ready(function(){
         // your code
  console.log("The Dom has loaded");
	setRoomDetailsOnDom();
   });
<|endoftext|>


<commit_before>var cluster  = require('cluster')
var cpuCount = require('os').cpus().length
var fs       = require('fs')
// var op       = require('object-path')
var path     = require('path')
var debug    = require('debug')('app:' + path.basename(__filename).replace('.js', ''))
var random   = require('randomstring')
var raven    = require('raven')

APP_ROOT_REFRESH_MS = 30 * 60 * 1000
APP_COOKIE_SECRET   = process.env.COOKIE_SECRET || random.generate(16)
APP_DEPLOYMENT      = process.env.DEPLOYMENT
APP_VERSION         = process.env.VERSION || require('./package').version

if (!process.env.ENTU_USER) {
    throw '"ENTU_USER" missing in environment'
}
if (!process.env.ENTU_KEY) {
    throw '"ENTU_KEY" missing in environment'
}

APP_ENTU_OPTIONS    = {
    entuUrl: process.env.ENTU_URL || 'https://saal.entu.ee',
    user: process.env.ENTU_USER,
    key: process.env.ENTU_KEY
}

// Site data cache
APP_ENTU_ROOT       = 1 // institution
APP_CACHE_DIR       = __dirname + '/pagecache'
if (!fs.existsSync(APP_CACHE_DIR)) { fs.mkdirSync(APP_CACHE_DIR) }

// initialize getsentry.com client
var ravenClient = new raven.Client({ release: APP_VERSION })

var workers = []

// debug(APP_ENTU_OPTIONS)
var cache = require('./helpers/cache')
cache.sync(
    function report(message, options) {
        options = options || { level: 'info' }
        ravenClient.captureMessage(message, options)
    },
    function cacheSyncCB() {
        for (var i in workers) {
            if (workers.hasOwnProperty(i)) {
                var worker = workers[i]
                if (worker) {
                    console.log('cacheSyncCB: Reload worker ' + worker.id)
                    worker.send({ cmd: 'reload', dir: APP_CACHE_DIR })
                }
            }
        }
    }
)

debug('Check if PL sync', APP_DEPLOYMENT)
if (APP_DEPLOYMENT === 'live' || APP_DEPLOYMENT === 'dev') {
    debug('Initialising PL sync')
    var plSync = require('./helpers/pl-sync')
    function startPLSync() {
        if (plSync.state === undefined) {
            debug('PLSync not ready, try in a sec')
            setTimeout(function () {
                startPLSync()
            }, 1000)
        } else if (plSync.state === 'idle') {
            plSync.routine(function plSyncCB(err, message) {
                if (err) {
                    console.log(err)
                    console.log(message)
                    throw 'PL sync totally messed up'
                }
                console.log(message + ' at ' + Date().toString())
            })
        }
    }
    startPLSync()
}

// Broadcast a message to all other workers
function broadcast(data, workerId) {
    if (!workerId) {
        workerId = -1
    }
    console.log('Broadcast from ' + workerId + '.')
    for (var i in workers) {
        if (workers.hasOwnProperty(i)) {
            var worker = workers[i]
            if (worker && worker.id !== workerId) {
                worker.send({ cmd: 'data', data: data, from: workerId, chat: 'broadcast to ' + worker.id + ' initiated by ' + workerId })
            }
        }
    }
}

function createWorker() {
    var worker = cluster.fork()
    worker.on('message', function(msg) {
        if (msg.cmd) {
            switch (msg.cmd) {
                case 'log':
                    console.log(new Date().toString() + ' W-' + this.id + ': ' + msg.log)
                break
                case 'broadcast':
                    console.log('W-' + this.id + ' broadcasting...')
                    broadcast(msg.data, this.id)
                break
            }
        }
        if (msg.err) {
            console.log(JSON.stringify({worker: this.id, error: err}, null, 2))
        }
    })
    // Add the worker to an array of known workers
    workers[worker.id] = worker
}

cluster.setupMaster({ exec: path.join(__dirname, 'worker.js') })

if (cluster.isMaster) {
    // Create a worker for each CPU
    cpuCount = 1
    for (var i = 0; i < cpuCount; i += 1) {
        createWorker()
    }

    // Listen for new workers
    cluster.on('online', function(worker) {
        console.log(new Date().toString() + ' worker ' + worker.id + ' started')
        worker.send({ cmd: 'APP_COOKIE_SECRET', APP_COOKIE_SECRET: APP_COOKIE_SECRET })
        worker.send({ cmd: 'reload', dir: APP_CACHE_DIR })
    })

    // Listen for dying workers nad replace the dead worker, we're not sentimental
    cluster.on('exit', function(worker, code, signal) {
        workers[worker.id] = false
        if(signal) {
            console.error('Worker #' + worker.id + ' was killed by signal: ' + signal)
        } else if(code !== 0) {
            console.error('Worker #' + worker.id + ' exited with error code: ' + code)
        } else {
            console.error('Worker #' + worker.id + ' success!')
        }
        createWorker()
    })
}
<commit_msg>decluster<commit_after>if(process.env.NEW_RELIC_LICENSE_KEY) { require('newrelic') }

var async    = require('async')
var bparser  = require('body-parser')
var cookie   = require('cookie-parser')
var express  = require('express')
var fs       = require('fs')
var i18n     = require('./helpers/i18n')
var moment   = require('moment')
var op       = require('object-path')
var path     = require('path')
var debug    = require('debug')('app:' + path.basename(__filename).replace('.js', ''))
var random   = require('randomstring')
var raven    = require('raven')

APP_ROOT_REFRESH_MS = 30 * 60 * 1000
APP_COOKIE_SECRET   = random.generate(16)
APP_DEPLOYMENT      = process.env.DEPLOYMENT
APP_VERSION         = require('./package').version
APP_DEBUG           = process.env.DEBUG
APP_PORT            = process.env.PORT || 3000

if (!process.env.ENTU_USER) {
    throw '"ENTU_USER" missing in environment'
}
if (!process.env.ENTU_KEY) {
    throw '"ENTU_KEY" missing in environment'
}

APP_ENTU_OPTIONS    = {
    entuUrl: process.env.ENTU_URL || 'https://saal.entu.ee',
    user: process.env.ENTU_USER,
    key: process.env.ENTU_KEY
}

// Site data cache
APP_ENTU_ROOT       = 1 // institution
APP_CACHE_DIR       = __dirname + '/pagecache'
if (!fs.existsSync(APP_CACHE_DIR)) { fs.mkdirSync(APP_CACHE_DIR) }

// initialize getsentry.com client
var ravenClient = new raven.Client({ release: APP_VERSION })

// debug(APP_ENTU_OPTIONS)

debug('Loading Entu web ...')

SDC = op({})

var prepareControllersFa = []

prepareControllersFa.push(function loadCache(callback) {
    var filenames = fs.readdirSync(APP_CACHE_DIR).map(function(filename) {
        return filename.split('.json')[0]
    })

    async.each(filenames, function(filename, callback) {
        // debug({ cmd: 'log', log: 'Loading cache from ' + filename })
        // debug(filename)
        // debug('Loading: ', path.join(APP_CACHE_DIR, filename))
        fs.readFile(path.join(APP_CACHE_DIR, filename + '.json'), function(err, data) {
            if (err) {
                debug('Not loaded: ', path.join(APP_CACHE_DIR, filename), err)
                return callback(err)
            }
            debug('filename', filename)
            try {
                SDC.set(filename, JSON.parse(data))
            } catch (e) {
                console.log('e', e)
                SDC.set(filename, data)
            }
            // debug('Loaded: ', path.join(APP_CACHE_DIR, filename))
            callback()
        })
    }, function(err) {
        if (err) {
            debug('Failed to load local cache.', err)
            debug({ cmd: 'log', log: 'Failed to load local cache.', err: err })
            callback(err)
            return
        }
        // debug({ cmd: 'log', log: 'Cache loaded.' })
        // debug('Cache loaded.')
        callback()
    })
})

prepareControllersFa.push(function prepareControllers(prepareControllersCB) {
    // debug({ cmd: 'log', log: 'Preparing data for controllers.' })
    // debug('Preparing data for controllers.')
    var controllers = fs.readdirSync(path.join(__dirname, 'routes')).map(function(filename) {
        return filename.split('.js')[0]
    })
    async.eachSeries(controllers, function(controller, callback) {
        // debug('controller:', controller)
        var cntrl = require(path.join(__dirname, 'routes', controller))
        if (cntrl.prepare !== undefined) {
            // debug({ cmd: 'log', log: 'Preparing ' + controller })
            cntrl.prepare(function() {
                // debug({ cmd: 'log', log: 'Callback from ' + controller })
                callback()
            })
        } else {
            // debug({ cmd: 'log', log: 'Not preparing ' + controller })
            callback()
        }
    }, function(err) {
        if (err) {
            // debug('Failed to prepare controllers.', err)
            debug({ cmd: 'log', log: 'Failed to prepare controllers.', err: err })
            prepareControllersCB(err)
            return
        }
        // debug({ cmd: 'log', log: 'Controllers prepared.' })
        debug('Controllers prepared.')
        prepareControllersCB()
    })
})

// Configure i18n
i18n.configure({
    locales: ['en', 'et'],
    defaultLocale: 'et',
    redirectWrongLocale: true,
    file: path.join(__dirname, 'localization', 'locales.yaml'),
    updateFile: true
})

// initialize getsentry.com client
var ravenClient = new raven.Client({
    release: APP_VERSION,
    dataCallback: function(data) {
        debug(JSON.stringify({data:data}, null, 4))
        // delete data.request.env
        return data
    }
})

var app     = express()
debug('Start jade engine')
app
    // jade view engine
    .set('views', path.join(__dirname, 'views'))
    .set('view engine', 'jade')

debug('Start getsentry logs')
app
    // logs to getsentry.com - start
    .use(raven.middleware.express.requestHandler(ravenClient))

debug('Cookies')
app
    // cookies
    .use(cookie(APP_COOKIE_SECRET))

debug('Body parser')
app
    // parse POST requests
    .use(bparser.json())
    .use(bparser.urlencoded({extended: true}))

debug('Static and favicon')
app
    // static files path & favicon
    .use(express.static(path.join(__dirname, 'public')))
    // .use(favicon(path.join(__dirname, 'public', 'images', 'kgs-logo.ico')))

    // set defaults for views
    .use(function(req, res, next) {
        if(req.path === '/') { return res.redirect('/et/') }
        // debug(JSON.stringify(req.path, null, '    '))
        // res.locals.lang = 'et'
        res.locals.moment = moment
        res.locals.op = op
        res.locals.SAAL = SDC.get('root')
        var p = req.path.split('/')
        p.shift()
        p.shift()
        res.locals.path = p.join('/')
        res.locals.route = p[0]
        if(req.signedCookies.auth_id && req.signedCookies.auth_token) {
            res.locals.user = {
                id: req.signedCookies.auth_id,
                token: req.signedCookies.auth_token
            }
        }
        next(null)
    })

    //Initiate i18n
    .use(i18n.init)

app
    // routes mapping
    .use('/:lang',               require('./routes/index'))
    .use('/:lang/about/',        require('./routes/about'))
    .use('/:lang/performance/',  require('./routes/performance'))
    .use('/:lang/tours/',        require('./routes/tours'))
    .use('/:lang/program/',      require('./routes/program'))
    .use('/:lang/co_productions/',      require('./routes/co_productions'))
    .use('/:lang/residency/',    require('./routes/residency'))
    .use('/:lang/resident/',     require('./routes/resident'))
    .use('/:lang/projects/',     require('./routes/projects'))
    .use('/:lang/contact/',      require('./routes/contact'))
    .use('/:lang/magazine/',     require('./routes/magazine'))
    .use('/:lang/search',        require('./routes/search'))
    // .use('/:lang/signin',        require('./routes/signin'))
    .use('/:lang/festival',      require('./routes/festival'))
    .use('/:lang/calendar_json', require('./routes/calendar_json'))

    // logs to getsentry.com - error
    .use(raven.middleware.express.errorHandler(ravenClient))

    // 404
    .use(function(req, res, next) {
        console.log(new Date(), '404:' + req.path)
        return res.redirect('/')

        // var err = new Error('Not Found')
        // err.status = 404
        // next(err)
    })

    // error
    .use(function(err, req, res) {
        var status = parseInt(err.status, 10) || 500

        res.status(status)
        res.render('error', {
            title: status,
            message: res.locals.t('error.' + err.message),
            error: APP_DEBUG ? err : {}
        })

        if(err.status !== 404) { debug(err) }
    })

    // start server
    .listen(APP_PORT)

debug('Started at port %s', APP_PORT)

var cache = require('./helpers/cache')
cache.sync(
    function report(message, options) {
        options = options || { level: 'info' }
        ravenClient.captureMessage(message, options)
    },
    function reloadCache() {
        if (SDC.get(['lastPollTs'])) {
            debug({ cmd: 'log', log: 'Loading local cache from ' + new Date(SDC.get(['lastPollTs'])*1e3) })
        } else {
            debug({ cmd: 'log', log: 'Waiting for cache...' })
        }

        debug(280, prepareControllersFa)
        async.series(prepareControllersFa, function routineFinally(err) {
            if (err) {
                debug({ cmd: 'log', log: 'Reload failed', err: err })
                return
            }
            if (SDC.get(['lastPollTs'])) {
                debug({ cmd: 'log', log: 'Worker reloaded with cache from ' + new Date(SDC.get(['lastPollTs'])*1e3) })
            } else {
                debug({ cmd: 'log', log: 'Worker reloaded with no cache.' })
            }
        })
    }
)

debug('Check if PL sync', APP_DEPLOYMENT)
if (APP_DEPLOYMENT === 'live' || APP_DEPLOYMENT === 'dev') {
    debug('Initialising PL sync')
    var plSync = require('./helpers/pl-sync')
    function startPLSync() {
        if (plSync.state === undefined) {
            debug('PLSync not ready, try in a sec')
            setTimeout(function () {
                startPLSync()
            }, 1000)
        } else if (plSync.state === 'idle') {
            plSync.routine(function plSyncCB(err, message) {
                if (err) {
                    console.log(err)
                    console.log(message)
                    throw 'PL sync totally messed up'
                }
                console.log(message + ' at ' + Date().toString())
            })
        }
    }
    startPLSync()
}
<|endoftext|>


<commit_before>window.InputController = (() => {
  return {
    init: () => {
      const token = window.sessionStorage.getItem('userInfo-token');
      $.getScript('js/caseFieldFunctionality.js', () => {
        function submitVictimForm(existingVictimInput) {
          if (!existingVictimInput) {
            return $.ajax({
              url: 'http://localhost:3000/victims',
              type: 'POST',
              headers: {
                'x-access-token': token
              },
              data: {
                victName: {
                  first: caseUI.fields['victFirstName']['input'].val(),
                  middle: caseUI.fields['victMiddleName']['input'].val(),
                  last: caseUI.fields['victLastName']['input'].val()
                },
                victSex: caseUI.fields['victSex']['input'].val(),
                victDesc: caseUI.fields['victDesc']['input'].val(),
                victAge: caseUI.fields['victAge']['input'].val()
              },
              statusCode: {
                400: (err) => {
                  didAPICallFail = true;
                  $('#victimFormSmall').text(err['responseJSON']['errors']['message']);
                  $('#victimFormLabel').addClass('text-danger');
                  console.log('Victim submission failed:');
                  console.log(err);
                },
                201: (victim) => {
                  victimJSON = victim;
                  $('#victimFormSmall').text('');
                  $('#victimFormLabel').removeClass('text-danger');
                }
              }
            });
          }
          return existingVictimInput; // TODO: change?
        }

        function submitSuspectForm(existingSuspectInput) {
          if (!existingSuspectInput) {
            return $.ajax({
              url: 'http://localhost:3000/suspects',
              type: 'POST',
              headers: {
                'x-access-token': token
              },
              data: {
                suspName: {
                  first: caseUI.fields['suspFirstName']['input'].val(),
                  middle: caseUI.fields['suspMiddleName']['input'].val(),
                  last: caseUI.fields['suspLastName']['input'].val()
                },
                suspSex: caseUI.fields['suspSex']['input'].val(),
                supervisedReleaseStatus: caseUI.fields['suspSupervisedReleaseStatus']['input'].val(),
                suspDesc: caseUI.fields['suspDesc']['input'].val(),
                suspAge: caseUI.fields['suspAge']['input'].val(),
                juvenileTriedAsAdult: caseUI.fields['juvenileTriedAsAdult']['input'].val()
              },
              statusCode: {
                400: (err) => {
                  // TODO: commented out?
                  // didAPICallFail = true;
                  $('#suspectFormSmall').text(err['responseJSON']['errors']['message']);
                  $('#suspectFormLabel').addClass('text-danger');
                  console.log('Suspect submission failed:');
                  console.log(err);
                },
                201: (suspect) => {
                  // TODO: commented out?
                  // suspectJSON = suspect;
                  $('#suspectFormSmall').text('');
                  $('#suspectFormLabel').removeClass('text-danger');
                }
              }
            });
          }
          return existingSuspectInput; // TODO: change?
        }

        function submitCaseForm(victimId, suspectIds) {
          return $.ajax({
            url: 'http://localhost:3000/cases',
            type: 'POST',
            headers: {
              'x-access-token': token
            },
            data: {
              drNumber: caseUI.fields['drNum']['input'].val(),
              masterDrNumber: caseUI.fields['masterDrNum']['input'].val(),
              division: caseUI.fields['division']['input'].val(),
              bureau: caseUI.fields['bureau']['input'].val(),
              notes: caseUI.fields['notes']['input'].val(),
              dateOccured: (new Date(caseUI.fields['dateOccured']['input'].val())).toISOString(),
              dateReported: (new Date(caseUI.fields['dateReported']['input'].val())).toISOString(),
              reportingDistrict: caseUI.fields['reportingDistrict']['input'].val(),
              caseStatus: caseUI.fields['caseStatus']['input'].val(),
              caseStatusDate: (new Date(caseUI.fields['caseStatusDate']['input'].val())).toISOString(),
              solvabilityFactor: caseUI.fields['solvabilityFactor']['input'].val(),
              weaponUsed: (function getWeaponsUsed() {
                const weaponsList = [];
                const weaponInputs = Object.keys(caseUI.fields['weapon']['inputs']);
                weaponInputs.forEach((weaponCheckbox) => {
                  if (caseUI.fields['weapon']['inputs'][weaponCheckbox].prop('checked')) {
                    weaponsList.push(caseUI.fields['weapon']['inputs'][weaponCheckbox].attr('name'));
                  }
                });
                return weaponsList;
              }()),
              motive: (function getMotives() {
                const motivesList = [];
                const motiveInputs = Object.keys(caseUI.fields['motive']['inputs']);
                motiveInputs.forEach((motiveCheckbox) => {
                  if (caseUI.fields['motive']['inputs'][motiveCheckbox].prop('checked')) {
                    motivesList.push(caseUI.fields['motive']['inputs'][motiveCheckbox].attr('name'));
                  }
                });
                return motivesList;
              }()),
              lastModifiedDate: (new Date()).toISOString(),
              lastModifiedBy: '5a07dcad41156921c81b70e4', // TODO: Get userId of user logged in
              victim: victimId,
              address: {
                streetNumber: caseUI.fields['streetNumber']['input'].val(),
                streetName: caseUI.fields['streetName']['input'].val(),
                city: caseUI.fields['city']['input'].val(),
                zipCode: caseUI.fields['zipCode']['input'].val()
              },
              suspects: [suspectIds]
            },
            statusCode: {
              400: (err) => {
                console.log('Case submission failed:');
                console.log(caseJSON);
                didAPICallFail = true;
                $('#submitFormSmall').removeClass('text-success');
                $('#submitFormSmall').addClass('text-danger');
                $('#submitFormSmall').text('Oops! Could not submit form due to the following database errors. ' + err['responseJSON']['errors']['message']);
              },
              404: (err) => {
                console.log('Case submission failed:');
                console.log(err);
                didAPICallFail = true;
                $('#submitFormSmall').removeClass('text-success');
                $('#submitFormSmall').addClass('text-danger');
                $('#submitFormSmall').text('Oops! Could not submit form due to the following database error. ' + err['responseJSON']['text'] + ': ' + err['responseJSON']['value'] + '.');
              },
              201: (caseJSON) => {
                console.log('Case submission results:');
                console.log(caseJSON);
                $('#submitFormSmall').removeClass('text-danger');
                $('#submitFormSmall').addClass('text-success');
                $('#submitFormSmall').text('Case submission succeeded with DR# ' + caseUI.fields['drNum']['input'].val() + '.');
                clearAllInputs();
              }
            }
          });
        }

        function attemptMasterFormSubmission() {
          if (caseUI.checkFormValidityAndAnnotate()) {
            const existingVictimID = caseUI.fields['newOrExistingVictim']['input'].val() === 'old' ?
              caseUI.fields['victId']['input'].val() : null; // pass in an existing ID or null.
            const existingSuspectID = caseUI.fields['newOrExistingSuspect']['input'].val() === 'old' ?
              caseUI.fields['suspId']['input'].val() : null; // pass in an existing ID or null.

            Promise.all([submitVictimForm(existingVictimID), submitSuspectForm(existingSuspectID)])
              .then((values) => {
                const victim = values[0]['_id'] || values[0];
                const suspect = values[1]['_id'] || values[1];
                console.log('victim: ', victim);
                submitCaseForm(victim, suspect);
              }).catch((err) => {
                console.log(err);
              });
          }
        }

        $('#button-submit-forms').on('click', () => {
          attemptMasterFormSubmission();
        });

        function clearAllInputs() {
          for (field in caseUI.fields) {
            if (caseUI.fields[field]['input'] === undefined) {
              for (input in caseUI.fields[field]['inputs']) {
                caseUI.fields[field]['inputs'][input].prop('checked', false);
              }
            } else {
              caseUI.fields[field]['input'].val('');
            }
          }
          caseUI.newOrExistingSuspectInput.val('default');
          updateSuspectInputsVisibility();
          caseUI.newOrExistingVictimInput.val('default');
          updateVictimInputsVisibility();
        }

        function updateVictimInputsVisibility() {
          const val = caseUI.newOrExistingVictimInput.val();
          if (val === 'default') {
            caseUI.newVictimForm.hide();
            caseUI.existingVictimForm.hide();
          } else if (val === 'new') {
            caseUI.newVictimForm.show();
            caseUI.existingVictimForm.hide();
          } else if (val === 'old') {
            caseUI.newVictimForm.hide();
            caseUI.existingVictimForm.show();
          }
        }
        updateVictimInputsVisibility();

        function updateSuspectInputsVisibility() {
          const val = caseUI.newOrExistingSuspectInput.val();
          if (val === 'default') {
            caseUI.newSuspectForm.hide();
            caseUI.existingSuspectForm.hide();
          } else if (val === 'new') {
            caseUI.newSuspectForm.show();
            caseUI.existingSuspectForm.hide();
<<<<<<< HEAD
          } else if (val === 'old') { // g?
=======
          } else if (val == 'old') {
>>>>>>> beta
            caseUI.newSuspectForm.hide();
            caseUI.existingSuspectForm.show();
          }
        }
        updateSuspectInputsVisibility();

        caseUI.newOrExistingVictimInput.change(() => {
          updateVictimInputsVisibility();
        });

        caseUI.newOrExistingSuspectInput.change(() => {
          updateSuspectInputsVisibility();
        });
      });
    }
  };
})();
<commit_msg>Linting errors<commit_after>window.InputController = (() => {
  return {
    init: () => {
      const token = window.sessionStorage.getItem('userInfo-token');
      $.getScript('js/caseFieldFunctionality.js', () => {
        function submitVictimForm(existingVictimInput) {
          if (!existingVictimInput) {
            return $.ajax({
              url: 'http://localhost:3000/victims',
              type: 'POST',
              headers: {
                'x-access-token': token
              },
              data: {
                victName: {
                  first: caseUI.fields['victFirstName']['input'].val(),
                  middle: caseUI.fields['victMiddleName']['input'].val(),
                  last: caseUI.fields['victLastName']['input'].val()
                },
                victSex: caseUI.fields['victSex']['input'].val(),
                victDesc: caseUI.fields['victDesc']['input'].val(),
                victAge: caseUI.fields['victAge']['input'].val()
              },
              statusCode: {
                400: (err) => {
                  didAPICallFail = true;
                  $('#victimFormSmall').text(err['responseJSON']['errors']['message']);
                  $('#victimFormLabel').addClass('text-danger');
                  console.log('Victim submission failed:');
                  console.log(err);
                },
                201: (victim) => {
                  victimJSON = victim;
                  $('#victimFormSmall').text('');
                  $('#victimFormLabel').removeClass('text-danger');
                }
              }
            });
          }
          return existingVictimInput; // TODO: change?
        }

        function submitSuspectForm(existingSuspectInput) {
          if (!existingSuspectInput) {
            return $.ajax({
              url: 'http://localhost:3000/suspects',
              type: 'POST',
              headers: {
                'x-access-token': token
              },
              data: {
                suspName: {
                  first: caseUI.fields['suspFirstName']['input'].val(),
                  middle: caseUI.fields['suspMiddleName']['input'].val(),
                  last: caseUI.fields['suspLastName']['input'].val()
                },
                suspSex: caseUI.fields['suspSex']['input'].val(),
                supervisedReleaseStatus: caseUI.fields['suspSupervisedReleaseStatus']['input'].val(),
                suspDesc: caseUI.fields['suspDesc']['input'].val(),
                suspAge: caseUI.fields['suspAge']['input'].val(),
                juvenileTriedAsAdult: caseUI.fields['juvenileTriedAsAdult']['input'].val()
              },
              statusCode: {
                400: (err) => {
                  // TODO: commented out?
                  // didAPICallFail = true;
                  $('#suspectFormSmall').text(err['responseJSON']['errors']['message']);
                  $('#suspectFormLabel').addClass('text-danger');
                  console.log('Suspect submission failed:');
                  console.log(err);
                },
                201: (suspect) => {
                  // TODO: commented out?
                  // suspectJSON = suspect;
                  $('#suspectFormSmall').text('');
                  $('#suspectFormLabel').removeClass('text-danger');
                }
              }
            });
          }
          return existingSuspectInput; // TODO: change?
        }

        function submitCaseForm(victimId, suspectIds) {
          return $.ajax({
            url: 'http://localhost:3000/cases',
            type: 'POST',
            headers: {
              'x-access-token': token
            },
            data: {
              drNumber: caseUI.fields['drNum']['input'].val(),
              masterDrNumber: caseUI.fields['masterDrNum']['input'].val(),
              division: caseUI.fields['division']['input'].val(),
              bureau: caseUI.fields['bureau']['input'].val(),
              notes: caseUI.fields['notes']['input'].val(),
              dateOccured: (new Date(caseUI.fields['dateOccured']['input'].val())).toISOString(),
              dateReported: (new Date(caseUI.fields['dateReported']['input'].val())).toISOString(),
              reportingDistrict: caseUI.fields['reportingDistrict']['input'].val(),
              caseStatus: caseUI.fields['caseStatus']['input'].val(),
              caseStatusDate: (new Date(caseUI.fields['caseStatusDate']['input'].val())).toISOString(),
              solvabilityFactor: caseUI.fields['solvabilityFactor']['input'].val(),
              weaponUsed: (function getWeaponsUsed() {
                const weaponsList = [];
                const weaponInputs = Object.keys(caseUI.fields['weapon']['inputs']);
                weaponInputs.forEach((weaponCheckbox) => {
                  if (caseUI.fields['weapon']['inputs'][weaponCheckbox].prop('checked')) {
                    weaponsList.push(caseUI.fields['weapon']['inputs'][weaponCheckbox].attr('name'));
                  }
                });
                return weaponsList;
              }()),
              motive: (function getMotives() {
                const motivesList = [];
                const motiveInputs = Object.keys(caseUI.fields['motive']['inputs']);
                motiveInputs.forEach((motiveCheckbox) => {
                  if (caseUI.fields['motive']['inputs'][motiveCheckbox].prop('checked')) {
                    motivesList.push(caseUI.fields['motive']['inputs'][motiveCheckbox].attr('name'));
                  }
                });
                return motivesList;
              }()),
              lastModifiedDate: (new Date()).toISOString(),
              lastModifiedBy: '5a07dcad41156921c81b70e4', // TODO: Get userId of user logged in
              victim: victimId,
              address: {
                streetNumber: caseUI.fields['streetNumber']['input'].val(),
                streetName: caseUI.fields['streetName']['input'].val(),
                city: caseUI.fields['city']['input'].val(),
                zipCode: caseUI.fields['zipCode']['input'].val()
              },
              suspects: [suspectIds]
            },
            statusCode: {
              400: (err) => {
                console.log('Case submission failed:');
                console.log(caseJSON);
                didAPICallFail = true;
                $('#submitFormSmall').removeClass('text-success');
                $('#submitFormSmall').addClass('text-danger');
                $('#submitFormSmall').text(`Oops! Could not submit form due to the following database errors. ${err['responseJSON']['errors']['message']}`);
              },
              404: (err) => {
                console.log('Case submission failed:');
                console.log(err);
                didAPICallFail = true;
                $('#submitFormSmall').removeClass('text-success');
                $('#submitFormSmall').addClass('text-danger');
                $('#submitFormSmall').text(`Oops! Could not submit form due to the following database error. ${err['responseJSON']['text']}: ${err['responseJSON']['value']}.`);
              },
              201: (caseJSON) => {
                console.log('Case submission results:');
                console.log(caseJSON);
                $('#submitFormSmall').removeClass('text-danger');
                $('#submitFormSmall').addClass('text-success');
                $('#submitFormSmall').text(`Case submission succeeded with DR# ${caseUI.fields['drNum']['input'].val()}.`);
                clearAllInputs();
              }
            }
          });
        }

        function attemptMasterFormSubmission() {
          if (caseUI.checkFormValidityAndAnnotate()) {
            const existingVictimID = caseUI.fields['newOrExistingVictim']['input'].val() === 'old' ?
              caseUI.fields['victId']['input'].val() : null; // pass in an existing ID or null.
            const existingSuspectID = caseUI.fields['newOrExistingSuspect']['input'].val() === 'old' ?
              caseUI.fields['suspId']['input'].val() : null; // pass in an existing ID or null.

            Promise.all([submitVictimForm(existingVictimID), submitSuspectForm(existingSuspectID)])
              .then((values) => {
                const victim = values[0]['_id'] || values[0];
                const suspect = values[1]['_id'] || values[1];
                console.log('victim: ', victim);
                submitCaseForm(victim, suspect);
              }).catch((err) => {
                console.log(err);
              });
          }
        }

        $('#button-submit-forms').on('click', () => {
          attemptMasterFormSubmission();
        });

        function clearAllInputs() {
          for (field in caseUI.fields) {
            if (caseUI.fields[field]['input'] === undefined) {
              for (input in caseUI.fields[field]['inputs']) {
                caseUI.fields[field]['inputs'][input].prop('checked', false);
              }
            } else {
              caseUI.fields[field]['input'].val('');
            }
          }
          caseUI.newOrExistingSuspectInput.val('default');
          updateSuspectInputsVisibility();
          caseUI.newOrExistingVictimInput.val('default');
          updateVictimInputsVisibility();
        }

        function updateVictimInputsVisibility() {
          const val = caseUI.newOrExistingVictimInput.val();
          if (val === 'default') {
            caseUI.newVictimForm.hide();
            caseUI.existingVictimForm.hide();
          } else if (val === 'new') {
            caseUI.newVictimForm.show();
            caseUI.existingVictimForm.hide();
          } else if (val === 'old') {
            caseUI.newVictimForm.hide();
            caseUI.existingVictimForm.show();
          }
        }
        updateVictimInputsVisibility();

        function updateSuspectInputsVisibility() {
          const val = caseUI.newOrExistingSuspectInput.val();
          if (val === 'default') {
            caseUI.newSuspectForm.hide();
            caseUI.existingSuspectForm.hide();
          } else if (val === 'new') {
            caseUI.newSuspectForm.show();
            caseUI.existingSuspectForm.hide();
          } else if (val === 'old') {
            caseUI.newSuspectForm.hide();
            caseUI.existingSuspectForm.show();
          }
        }
        updateSuspectInputsVisibility();

        caseUI.newOrExistingVictimInput.change(() => {
          updateVictimInputsVisibility();
        });

        caseUI.newOrExistingSuspectInput.change(() => {
          updateSuspectInputsVisibility();
        });
      });
    }
  };
})();
<|endoftext|>


<commit_before>function new_session()
{
    if ($("#session_name").val() !== "")
    {
        $.ajax({
            url: "/backend/session/new?sessionName=" + $("#session_name").val() + "&noquestions=" + $("#noquestions").val(),
            success: function(data)
            {
                if (data["status"] == 0)
                {
                    window.location = "/10ft/joining.html?sessionName=" + $("#session_name").val();
                }
            }
        });
    }
};

function get_player_list()
{
    $.ajax({
        url: "/backend/session/playerlist?sessionName=" + sessionname + "&" + $.now(),
        success: function(data)
        {
            data.sort();
            if (data != playerlist)
            {
                playerlist = data;
                out = "";
                for (player in data)
                {
                    out += "

" + playerlist[player] + "

";
                }
                $("#playerdisplay").html(out);
            }
        }
    });
};

function get_question() {
    $.ajax({
        "url": "/backend/question/new?sessionName=" + sessionname,
        success: function(data) {
            if (status == 0)
            {
                if (data["question"]["type"] == "list")
                {
                    question_count = data["questionCount"];
                    current_question = data["currentQuestion"];
                    question = data["question"];

                    $("body").html('

');

                    $("#question-text").text(question["question"]);
                    for (var i = question["states"] - 1; i >= 0; i--) {
                        $("#list-item-" + i).text(question["list"][i]);
                    }

                    $("#answer-1").text(question["answer1"]);
                    $("#answer-2").text(question["answer2"]);
                    $("#answer-3").text(question["answer3"]);
                    $("#answer-4").text(question["answer4"]);

                    reveal_list(0);
                    setTimeout(get_results, 30000);
                }
            }
        }
    })
}

function get_results() {
    $.ajax({
        "url": "/backend/question/results?sessionName=" + sessionname,
        success: function(data) {
            if (data["status"] == 0)
            {
                $("body").html('

' + question["question"] + '

Correct answer: ' + question["answer" + question["solution"]] + '

' + data["results"][0]["player"] + '
Fastest Player

' + data["results"][1]["player"] + '
Second Fastest Player

' + data["results"][2]["player"] + '
Third Fastest Player

');
            }
        }
    });
}

function reveal_list(listitem) {
    if ($("#list-item-" + listitem).text() !== "")
    {
        $("#list-item-" + listitem).removeClass("indigo-text");
        setTimeout(function(){ reveal_list(listitem + 1); }, 3000);
    }
}

$(document).ready(function() {
    $('select').material_select();
    $("#data-title-sessionname").text(sessionname);
    $("#data-info-sessionname").text(sessionname);
});<commit_msg>Results screen only displays players that answers correctly<commit_after>function new_session()
{
    if ($("#session_name").val() !== "")
    {
        $.ajax({
            url: "/backend/session/new?sessionName=" + $("#session_name").val() + "&noquestions=" + $("#noquestions").val(),
            success: function(data)
            {
                if (data["status"] == 0)
                {
                    window.location = "/10ft/joining.html?sessionName=" + $("#session_name").val();
                }
            }
        });
    }
};

function get_player_list()
{
    $.ajax({
        url: "/backend/session/playerlist?sessionName=" + sessionname + "&" + $.now(),
        success: function(data)
        {
            data.sort();
            if (data != playerlist)
            {
                playerlist = data;
                out = "";
                for (player in data)
                {
                    out += "

" + playerlist[player] + "

";
                }
                $("#playerdisplay").html(out);
            }
        }
    });
};

function get_question() {
    $.ajax({
        "url": "/backend/question/new?sessionName=" + sessionname,
        success: function(data) {
            if (status == 0)
            {
                if (data["question"]["type"] == "list")
                {
                    question_count = data["questionCount"];
                    current_question = data["currentQuestion"];
                    question = data["question"];

                    $("body").html('

');

                    $("#question-text").text(question["question"]);
                    for (var i = question["states"] - 1; i >= 0; i--) {
                        $("#list-item-" + i).text(question["list"][i]);
                    }

                    $("#answer-1").text(question["answer1"]);
                    $("#answer-2").text(question["answer2"]);
                    $("#answer-3").text(question["answer3"]);
                    $("#answer-4").text(question["answer4"]);

                    reveal_list(0);
                    setTimeout(get_results, 30000);
                }
            }
            else if (status == 2)
            {

            }
        }
    })
}

function get_results() {
    $.ajax({
        "url": "/backend/question/results?sessionName=" + sessionname,
        success: function(data) {
            if (data["status"] == 0)
            {
                out = '

' + question["question"] + '

Correct answer: ' + question["answer" + question["solution"]] + '

'
                if (data["results"][0]["result"] > 0)
                {
                    out += '
' + data["results"][0]["player"] + '
Fastest Player

'
                    if (data["results"][1]["result"] > 0)
                    {
                        out += '
' + data["results"][1]["player"] + '
Second Fastest Player

'
                        if (data["results"][2]["result"] > 0)
                        {
                            out += '
' + data["results"][2]["player"] + '
Third Fastest Player

'
                        }
                    }
                }
                out += '
'
                $("body").html(out);
            }
        }
    });
}

function reveal_list(listitem) {
    if ($("#list-item-" + listitem).text() !== "")
    {
        $("#list-item-" + listitem).removeClass("indigo-text");
        setTimeout(function(){ reveal_list(listitem + 1); }, 3000);
    }
}

$(document).ready(function() {
    $('select').material_select();
    $("#data-title-sessionname").text(sessionname);
    $("#data-info-sessionname").text(sessionname);
});<|endoftext|>


<commit_before>'use strict'
const Vec2 = require('pex-math/Vec2')
const Vec3 = require('pex-math/Vec3')
const Mat4 = require('pex-math/Mat4')
const Quat = require('pex-math/Quat')
const Ray = require('pex-geom/Ray')
const clamp = require('pex-math/Utils').clamp

function getViewRay (camera, x, y, windowWidth, windowHeight) {
  const hNear = 2 * Math.tan(camera.fov / 2) * camera.near
  const wNear = hNear * camera.aspect
  let px = (x - windowWidth / 2) / (windowWidth / 2)
  let py = -(y - windowHeight / 2) / (windowHeight / 2)
  px *= wNear / 2
  py *= hNear / 2
  const origin = [0, 0, 0]
  const direction = Vec3.normalize([px, py, -camera.near])
  return [origin, direction]
}

// TOOD: issues to consider
// - using canvas element instead of window for events
// = should arcball update Camera aspect ratio?
// - window resizing
// - fullscreen vs local canvas
// - scroll prevention
// - retina display
// - touch events
// - event priority
// - setting current arcball orientation by setting camera position
// - camera position change detection
function createArcball (opts) {
  const distance = Vec3.distance(opts.camera.position, opts.camera.target)

  // TODO: split into internal state and public state
  const state = {
    camera: opts.camera,
    invViewMatrix: Mat4.create(),
    dragging: false,
    elem: window,
    width: window.innerWidth,
    height: window.innerHeight,
    radius: Math.min(window.innerWidth / 2, window.innerHeight / 2),
    center: [window.innerWidth / 2, window.innerHeight / 2],
    currRot: Quat.fromMat4(Quat.create(), opts.camera.viewMatrix),
    clickRot: [0, 0, 0, 1],
    dragRot: [0, 0, 0, 1],
    clickPos: [0, 0, 0],
    clickPosWindow: [0, 0],
    dragPos: [0, 0, 0],
    dragPosWindow: [0, 0],
    rotAxis: [0, 0, 0],
    distance: distance,
    minDistance: distance / 2,
    maxDistance: distance * 2,
    zoom: true,
    enabled: true,
    clickTarget: [0, 0, 0],
    clickPosPlane: [0, 0, 0],
    dragPosPlane: [0, 0, 0],
    clickPosWorld: [0, 0, 0],
    dragPosWorld: [0, 0, 0]
  }

  Object.assign(state, opts)

  function arcball (opts) {
    // TODO recompute on state change
    return Object.assign(arcball, state, opts)
  }

  function updateWindowSize () {
    if (window.innerWidth !== state.width) {
      state.width = window.innerWidth
      state.height = window.innerHeight
      state.radius = Math.min(state.width / 2, state.height / 2)
      state.center = [state.width / 2, state.height / 2]
    }
  }

  function updateCamera () {
    // instad of rotating the object we want to move camera around it
    state.currRot[3] *= -1

    const position = state.camera.position
    const target = state.camera.target
    const up = state.camera.up
    const distance = state.distance

    // set new camera position according to the current
    // rotation at distance relative to target
    Vec3.set3(position, 0, 0, distance)
    Vec3.multQuat(position, state.currRot)
    Vec3.add(position, target)

    Vec3.set3(up, 0, 1, 0)
    Vec3.multQuat(up, state.currRot)

    state.camera({
      position: position,
      target: target,
      up: up
    })

    // roll back rotation flip
    state.currRot[3] *= -1
  }

  function mouseToSphere (x, y, out) {
    y = state.height - y
    out[0] = (x - state.center[0]) / state.radius
    out[1] = (y - state.center[1]) / state.radius
    const dist = out[0] * out[0] + out[1] * out[1]
    if (dist > 1) {
      Vec3.normalize(out)
    } else {
      out[2] = Math.sqrt(1 - dist)
    }
    return out
  }

  function down (x, y, shift) {
    state.dragging = true
    mouseToSphere(x, y, state.clickPos)
    Quat.set(state.clickRot, state.currRot)
    updateCamera()
    if (shift) {
      Vec2.set2(state.clickPosWindow, x, y)
      Vec3.set(state.clickTarget, state.camera.target)
      const targetInViewSpace = Vec3.multMat4(Vec3.copy(state.clickTarget), state.camera.viewMatrix)
      state.panPlane = [targetInViewSpace, [0, 0, 1]]
      Ray.hitTestPlane(
        getViewRay(state.camera, state.clickPosWindow[0], state.clickPosWindow[1], state.width, state.height),
        state.panPlane[0],
        state.panPlane[1],
        state.clickPosPlane
      )
      Ray.hitTestPlane(
        getViewRay(state.camera, state.dragPosWindow[0], state.dragPosWindow[1], state.width, state.height),
        state.panPlane[0],
        state.panPlane[1],
        state.dragPosPlane
      )
    } else {
      state.panPlane = null
    }
  }

  function move (x, y, shift) {
    if (!state.dragging) {
      return
    }
    if (shift && state.panPlane) {
      Vec2.set2(state.dragPosWindow, x, y)
      Ray.hitTestPlane(
        getViewRay(state.camera, state.clickPosWindow[0], state.clickPosWindow[1], state.width, state.height),
        state.panPlane[0],
        state.panPlane[1],
        state.clickPosPlane
      )
      Ray.hitTestPlane(
        getViewRay(state.camera, state.dragPosWindow[0], state.dragPosWindow[1], state.width, state.height),
        state.panPlane[0],
        state.panPlane[1],
        state.dragPosPlane
      )
      Mat4.set(state.invViewMatrix, state.camera.viewMatrix)
      Mat4.invert(state.invViewMatrix)
      Vec3.multMat4(Vec3.set(state.clickPosWorld, state.clickPosPlane), state.invViewMatrix)
      Vec3.multMat4(Vec3.set(state.dragPosWorld, state.dragPosPlane), state.invViewMatrix)
      const diffWorld = Vec3.sub(Vec3.copy(state.dragPosWorld), state.clickPosWorld)
      const target = Vec3.sub(Vec3.copy(state.clickTarget), diffWorld)
      state.camera({ target: target })
    } else {
      mouseToSphere(x, y, state.dragPos)
      Vec3.set(state.rotAxis, state.clickPos)
      Vec3.cross(state.rotAxis, state.dragPos)
      const theta = Vec3.dot(state.clickPos, state.dragPos)
      Quat.set4(state.dragRot, state.rotAxis[0], state.rotAxis[1], state.rotAxis[2], theta)
      Quat.set(state.currRot, state.dragRot)
      Quat.mult(state.currRot, state.clickRot)
      updateCamera()
    }
  }

  function up () {
    state.dragging = false
    state.panPlane = null
  }

  function scroll (dy) {
    if (!state.zoom) {
      return
    }
    state.distance = state.distance + dy / 100
    state.distance = clamp(state.distance, state.minDistance, state.maxDistance)
    updateCamera()
  }

  function onMouseDown (e) {
    updateWindowSize()
    down(e.offsetX, e.offsetY, e.shiftKey)
  }

  function onMouseMove (e) {
    move(e.offsetX, e.offsetY, e.shiftKey)
  }

  function onMouseUp (e) {
    up()
  }

  function onMouseScroll (e) {
    const dy = -e.wheelDelta / 10 || e.detail / 10
    scroll(dy)
    e.preventDefault()
  }

  const mouseWheelEvent = /Firefox/i.test(navigator.userAgent) ? 'DOMMouseScroll' : 'mousewheel'
  window.addEventListener('mousedown', onMouseDown)
  window.addEventListener('mousemove', onMouseMove)
  window.addEventListener('mouseup', onMouseUp)
  window.addEventListener(mouseWheelEvent, onMouseScroll)

  return arcball(opts)
}

module.exports = createArcball
<commit_msg>Update mouse wheel support <commit_after>'use strict'
const Vec2 = require('pex-math/Vec2')
const Vec3 = require('pex-math/Vec3')
const Mat4 = require('pex-math/Mat4')
const Quat = require('pex-math/Quat')
const Ray = require('pex-geom/Ray')
const clamp = require('pex-math/Utils').clamp

function getViewRay (camera, x, y, windowWidth, windowHeight) {
  const hNear = 2 * Math.tan(camera.fov / 2) * camera.near
  const wNear = hNear * camera.aspect
  let px = (x - windowWidth / 2) / (windowWidth / 2)
  let py = -(y - windowHeight / 2) / (windowHeight / 2)
  px *= wNear / 2
  py *= hNear / 2
  const origin = [0, 0, 0]
  const direction = Vec3.normalize([px, py, -camera.near])
  return [origin, direction]
}

// TOOD: issues to consider
// - using canvas element instead of window for events
// = should arcball update Camera aspect ratio?
// - window resizing
// - fullscreen vs local canvas
// - scroll prevention
// - retina display
// - touch events
// - event priority
// - setting current arcball orientation by setting camera position
// - camera position change detection
function createArcball (opts) {
  const distance = Vec3.distance(opts.camera.position, opts.camera.target)

  // TODO: split into internal state and public state
  const state = {
    camera: opts.camera,
    invViewMatrix: Mat4.create(),
    dragging: false,
    elem: window,
    width: window.innerWidth,
    height: window.innerHeight,
    radius: Math.min(window.innerWidth / 2, window.innerHeight / 2),
    center: [window.innerWidth / 2, window.innerHeight / 2],
    currRot: Quat.fromMat4(Quat.create(), opts.camera.viewMatrix),
    clickRot: [0, 0, 0, 1],
    dragRot: [0, 0, 0, 1],
    clickPos: [0, 0, 0],
    clickPosWindow: [0, 0],
    dragPos: [0, 0, 0],
    dragPosWindow: [0, 0],
    rotAxis: [0, 0, 0],
    distance: distance,
    minDistance: distance / 2,
    maxDistance: distance * 2,
    zoom: true,
    enabled: true,
    clickTarget: [0, 0, 0],
    clickPosPlane: [0, 0, 0],
    dragPosPlane: [0, 0, 0],
    clickPosWorld: [0, 0, 0],
    dragPosWorld: [0, 0, 0]
  }

  Object.assign(state, opts)

  function arcball (opts) {
    // TODO recompute on state change
    return Object.assign(arcball, state, opts)
  }

  function updateWindowSize () {
    if (window.innerWidth !== state.width) {
      state.width = window.innerWidth
      state.height = window.innerHeight
      state.radius = Math.min(state.width / 2, state.height / 2)
      state.center = [state.width / 2, state.height / 2]
    }
  }

  function updateCamera () {
    // instad of rotating the object we want to move camera around it
    state.currRot[3] *= -1

    const position = state.camera.position
    const target = state.camera.target
    const up = state.camera.up
    const distance = state.distance

    // set new camera position according to the current
    // rotation at distance relative to target
    Vec3.set3(position, 0, 0, distance)
    Vec3.multQuat(position, state.currRot)
    Vec3.add(position, target)

    Vec3.set3(up, 0, 1, 0)
    Vec3.multQuat(up, state.currRot)

    state.camera({
      position: position,
      target: target,
      up: up
    })

    // roll back rotation flip
    state.currRot[3] *= -1
  }

  function mouseToSphere (x, y, out) {
    y = state.height - y
    out[0] = (x - state.center[0]) / state.radius
    out[1] = (y - state.center[1]) / state.radius
    const dist = out[0] * out[0] + out[1] * out[1]
    if (dist > 1) {
      Vec3.normalize(out)
    } else {
      out[2] = Math.sqrt(1 - dist)
    }
    return out
  }

  function down (x, y, shift) {
    state.dragging = true
    mouseToSphere(x, y, state.clickPos)
    Quat.set(state.clickRot, state.currRot)
    updateCamera()
    if (shift) {
      Vec2.set2(state.clickPosWindow, x, y)
      Vec3.set(state.clickTarget, state.camera.target)
      const targetInViewSpace = Vec3.multMat4(Vec3.copy(state.clickTarget), state.camera.viewMatrix)
      state.panPlane = [targetInViewSpace, [0, 0, 1]]
      Ray.hitTestPlane(
        getViewRay(state.camera, state.clickPosWindow[0], state.clickPosWindow[1], state.width, state.height),
        state.panPlane[0],
        state.panPlane[1],
        state.clickPosPlane
      )
      Ray.hitTestPlane(
        getViewRay(state.camera, state.dragPosWindow[0], state.dragPosWindow[1], state.width, state.height),
        state.panPlane[0],
        state.panPlane[1],
        state.dragPosPlane
      )
    } else {
      state.panPlane = null
    }
  }

  function move (x, y, shift) {
    if (!state.dragging) {
      return
    }
    if (shift && state.panPlane) {
      Vec2.set2(state.dragPosWindow, x, y)
      Ray.hitTestPlane(
        getViewRay(state.camera, state.clickPosWindow[0], state.clickPosWindow[1], state.width, state.height),
        state.panPlane[0],
        state.panPlane[1],
        state.clickPosPlane
      )
      Ray.hitTestPlane(
        getViewRay(state.camera, state.dragPosWindow[0], state.dragPosWindow[1], state.width, state.height),
        state.panPlane[0],
        state.panPlane[1],
        state.dragPosPlane
      )
      Mat4.set(state.invViewMatrix, state.camera.viewMatrix)
      Mat4.invert(state.invViewMatrix)
      Vec3.multMat4(Vec3.set(state.clickPosWorld, state.clickPosPlane), state.invViewMatrix)
      Vec3.multMat4(Vec3.set(state.dragPosWorld, state.dragPosPlane), state.invViewMatrix)
      const diffWorld = Vec3.sub(Vec3.copy(state.dragPosWorld), state.clickPosWorld)
      const target = Vec3.sub(Vec3.copy(state.clickTarget), diffWorld)
      state.camera({ target: target })
    } else {
      mouseToSphere(x, y, state.dragPos)
      Vec3.set(state.rotAxis, state.clickPos)
      Vec3.cross(state.rotAxis, state.dragPos)
      const theta = Vec3.dot(state.clickPos, state.dragPos)
      Quat.set4(state.dragRot, state.rotAxis[0], state.rotAxis[1], state.rotAxis[2], theta)
      Quat.set(state.currRot, state.dragRot)
      Quat.mult(state.currRot, state.clickRot)
      updateCamera()
    }
  }

  function up () {
    state.dragging = false
    state.panPlane = null
  }

  function scroll (dy) {
    if (!state.zoom) {
      return
    }
    state.distance = state.distance + dy / 100
    state.distance = clamp(state.distance, state.minDistance, state.maxDistance)
    updateCamera()
  }

  function onMouseDown (e) {
    updateWindowSize()
    down(e.offsetX, e.offsetY, e.shiftKey)
  }

  function onMouseMove (e) {
    move(e.offsetX, e.offsetY, e.shiftKey)
  }

  function onMouseUp (e) {
    up()
  }

  function onWheel (e) {
    scroll(e.deltaY * 10)
    // e.preventDefault()
  }

  window.addEventListener('mousedown', onMouseDown)
  window.addEventListener('mousemove', onMouseMove)
  window.addEventListener('mouseup', onMouseUp)
  window.addEventListener('wheel', onWheel)

  return arcball(opts)
}

module.exports = createArcball
<|endoftext|>


<commit_before>let script = {
    "url": "*://play.google.com/store/(movies|tv)/details/*",

    "init": (ready) => {
        let _title, _year, _image, R = RegExp;

        let type   = script.getType(),
            title  = $('h1').first,
            year   = $(`h1 ~ div span:${ type == 'movie'? 'first': 'last' }-of-type`).first,
            image  = $('img[alt="cover art" i]').first;

        title = title.textContent.replace(/\(\s*(\d{4})\s*\).*?$/, '').trim();
        year = (R.$1 || year.textContent).replace(/^.*?(\d+)/, '$1').trim();
        image = (image || {}).src;

        return { type, title, year, image };
    },

    "getType": () => (
        location.pathname.startsWith('store/movies/')?
            'movie':
        'show'
    ),
};

addEventListener('popstate', script.init);
addEventListener('pushstate-changed', script.init);
<commit_msg>Delete play.google.js<commit_after><|endoftext|>


<commit_before>webpackJsonp([0],[]);<commit_msg>remove bundle file<commit_after><|endoftext|>