Skip to content

Instantly share code, notes, and snippets.

@njvack
Last active December 21, 2016 21:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save njvack/920dac2791b2d100b25e477775bc50bf to your computer and use it in GitHub Desktop.
Save njvack/920dac2791b2d100b25e477775bc50bf to your computer and use it in GitHub Desktop.
Blinken
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<script type="text/javascript">
window.console = window.console || {}
window.console.log = window.console.log || function() {};
console.log("Hello");
// Standard sum function
function sum(ar) {
return ar.reduce(function(s, val) {
return s + val;
}, 0)
}
// Numerical mean
function mean(ar) {
return sum(ar) / ar.length;
}
function avg_square_diffs(ar) {
var m = mean(ar);
var sqdiffs = ar.map(function(e) {
var d = e - m;
return d * d;
});
return mean(sqdiffs);
}
// Yup, it's standard deviation
function stdev(ar) {
return Math.sqrt(avg_square_diffs(ar));
}
var blink_controller = function(cycle_ms, blink_ms, blink_element, record_blinks) {
var my = {};
my.cycle_ms = cycle_ms;
my.blink_ms = blink_ms;
my.blink_element = blink_element;
my.record_blinks = record_blinks;
my.blinks_recorded = 0;
my.event_list = [];
my.keep_blinking = false;
my.started = false;
my.finished = false;
function blink_on() {
my.blink_element.classList.add("on");
if (my.started) {
my.blinks_recorded += 1;
console.log(my.blinks_recorded);
}
}
function blink_off() {
my.blink_element.classList.remove("on");
if (my.blinks_recorded >= my.record_blinks) {
my.finished = true;
my.stop_blinking();
var evt = new Event('finish');
my.blink_element.dispatchEvent(evt);
}
}
function record_blink(timestamp) {
my.event_list.push({
"type": "blink_on",
"timestamp": timestamp,
});
}
var handle_frame = function(timestamp) {
// console.log("in handle_frame...")
if (my.keep_blinking) {
my.last_frame_time = my.last_frame_time || timestamp;
var elapsed = timestamp - my.last_frame_time;
// console.log([elapsed, my.blink_remaining, my.cycle_remaining].join("\t"));
if (isFinite(my.blink_remaining)) {
my.blink_remaining -= elapsed;
}
if (my.blink_remaining <= 0) {
blink_off();
my.blink_remaining = NaN;
//my.event_list.push(["blink_off", timestamp])
console.log("blink_off\t"+timestamp);
}
my.cycle_remaining -= elapsed;
if (my.cycle_remaining <= 0 ) {
blink_on();
my.blink_remaining = my.blink_ms;
my.cycle_remaining = my.cycle_ms;
my.event_list.push(
{
"type": "blink_on",
"timestamp": timestamp
});
console.log("blink_on\t"+timestamp);
}
my.last_frame_time = timestamp;
if (my.keep_blinking) {
window.requestAnimationFrame(handle_frame);
}
}
}
my.start_blinking = function() {
my.keep_blinking = true;
my.cycle_remaining = my.cycle_ms;
my.blink_remaining = my.blink_ms;
window.requestAnimationFrame(handle_frame);
}
my.stop_blinking = function() {
my.keep_blinking = false;
}
function make_sort_function(evt) {
return function(ke1, ke2) {
var dist1 = Math.abs(evt.timestamp - ke1.timestamp);
var dist2 = Math.abs(evt.timestamp - ke2.timestamp);
return dist1 - dist2;
};
}
function get_blink_events() {
return my.event_list.filter(function(e) { return e.type == 'blink_on'; });
}
function get_press_events() {
return my.event_list.filter(function(e) { return e.type == 'keypress'; });
}
my.match_blinks_and_presses = function() {
var blinks = get_blink_events();
var bs = blinks.slice();
var presses = get_press_events();
console.log(presses);
presses.forEach(function(p) {
console.log("Finding closest blink...");
console.log(p);
var sort_fx = make_sort_function(p);
bs.sort(sort_fx);
console.log(p);
var b = bs[0];
console.log("Closest match:");
console.log([p.timestamp, b.timestamp]);
b.press_candidate = b.press_candidate || p;
var old_diff = Math.abs(b.timestamp, b.press_candidate.timestamp);
var new_diff = Math.abs(b.timestamp, p.timestamp);
if (new_diff < old_diff) {
b.press_candidate = p;
}
});
console.log(blinks);
return blinks.filter(function(b) { return b.press_candidate; }).map(function(b) {
return {
"blink": b,
"press": b.press_candidate,
"diff": b.press_candidate.timestamp - b.timestamp
}
});
}
function record_press(timestamp) {
my.event_list.push({
"type": "keypress",
"timestamp": timestamp
});
}
my.handle_press = function(event) {
console.log(event);
if (my.finished) {
return;
}
if (!my.started) {
console.log("starting to record");
my.started = true;
}
record_press(window.performance.now());
}
return my;
}
window.addEventListener('load', function() {
console.log("Loaded");
var blink_elt = document.getElementById('blinker');
var record_blinks = 14;
var blinks_per_minute = 60;
var cycle_ms = (60 * 1000) / blinks_per_minute;
var blink_ms = (6/60) * 1000;
window.bc = blink_controller(cycle_ms, blink_ms, blink_elt, record_blinks);
document.addEventListener('keydown', bc.handle_press);
blink_elt.addEventListener('finish', function(e) {
var res = bc.match_blinks_and_presses();
var diffs = res.map(function(thing) { return thing.diff; });
document.getElementById("results").innerHTML = diffs.join("\n");
var m = mean(diffs);
var s = stdev(diffs);
document.getElementById("mean").innerHTML = "Mean: " + m;
document.getElementById("std").innerHTML = "Stdev: " + s;
});
bc.start_blinking();
});
</script>
<style type="text/css">
#blinker {
width: 200px;
height: 200px;
border-radius: 100px;
margin: 32px;
}
#blinker.on {
background-color: red;
}
</style>
</head>
<body>
<div id="blinker" class="on"> </div>
<p>Press space when it blinks!</p>
<pre><div id="results"></div></pre>
<h3 id="mean"></h3>
<h3 id="std"></h3>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment