Better despooler, still needs one fix

This commit is contained in:
Neale Pickett 2016-04-05 03:45:00 +00:00
parent 5191476b63
commit 03e9e9d91b
7 changed files with 206 additions and 61 deletions

View File

@ -23,7 +23,7 @@ for line in io.lines(koth.path("state/points.log")) do
end end
end end
local body = "<dl>\n" local body = "<dl id=\"puzzles\">\n"
for cat, biggest in pairs(max_by_cat) do for cat, biggest in pairs(max_by_cat) do
local points, dirname local points, dirname

View File

@ -1,11 +1,9 @@
var main_proc; var main_terminal;
function Main(element) { function Main(element) {
console.log(element);
var term = new Terminal(element); var term = new Terminal(element);
this.start = function() { this.start = function() {
console.log(element);
term.clear(); term.clear();
term.par("Main terminal.") term.par("Main terminal.")
term.par("This is the main terminal. In this terminal you will get your puzzle content and someplace to enter in possible answers. It's probably just going to pull the old URL, steal the body element, and submit it to a new Terminal method for slow-despooling of the content of text nodes.") term.par("This is the main terminal. In this terminal you will get your puzzle content and someplace to enter in possible answers. It's probably just going to pull the old URL, steal the body element, and submit it to a new Terminal method for slow-despooling of the content of text nodes.")
@ -17,8 +15,8 @@ function Main(element) {
function main_start() { function main_start() {
main_proc = new Main(document.getElementById("main")); main_terminal = new Main(document.getElementById("main"));
setTimeout(main_proc.start, 2500); setTimeout(main_terminal.start, 2500);
} }
window.addEventListener("load", main_start); window.addEventListener("load", main_start);

View File

@ -10,7 +10,7 @@
font-style: normal; font-style: normal;
} }
/* */
@font-face { @font-face {
font-family: 'Maven Pro'; font-family: 'Maven Pro';

View File

@ -1,4 +1,4 @@
var messages_proc; var messages_terminal;
function Messages(element) { function Messages(element) {
var term = new Terminal(element); var term = new Terminal(element);
@ -12,8 +12,8 @@ function Messages(element) {
function messages_start() { function messages_start() {
messages_proc = new Messages(document.getElementById("messages")); messages_terminal = new Messages(document.getElementById("messages"));
setTimeout(messages_proc.start, 500); setTimeout(messages_terminal.start, 500);
} }
window.addEventListener("load", messages_start); window.addEventListener("load", messages_start);

View File

@ -1,19 +1,47 @@
var puzzles_proc; var puzzles_terminal;
var puzzles_url = "hack/puzzles.html";
function Puzzles(element) { function Puzzles(element) {
var term = new Terminal(element); var term = new Terminal(element);
var refreshInterval;
function loaded() {
var doc = this.response;
var puzzles = doc.getElementById("puzzles");
var h1 = document.createElement("h1");
h1.textContent = "Puzzles";
this.start = function() {
term.clear(); term.clear();
term.par("Puzzles terminal"); term.append(h1);
term.par("This is going to show you the list of open puzzles. It should refresh itself periodically, since not refreshing was a source of major confusion in the last setup, at least for kids, who seem not to realize what the reload button in the browser does.") term.append(puzzles);
} }
function refresh() {
var myRequest = new XMLHttpRequest();
myRequest.responseType = "document";
myRequest.addEventListener("load", loaded);
myRequest.open("GET", puzzles_url);
myRequest.send();
}
function start() {
term.clear();
term.par("Loading...");
term.par("This is going to show you the list of open puzzles. It should refresh itself periodically, since not refreshing was a source of major confusion in the last setup, at least for kids, who seem not to realize what the reload button in the browser does.")
refreshInterval = setInterval(refresh, 20 * 1000);
refresh();
}
setTimeout(start, 3000);
} }
function puzzles_start() { function puzzles_start() {
puzzles_proc = new Puzzles(document.getElementById("puzzles")); puzzles_terminal = new Puzzles(document.getElementById("puzzles"));
setTimeout(puzzles_proc.start, 3000);
} }
window.addEventListener("load", puzzles_start); window.addEventListener("load", puzzles_start);

View File

@ -1,8 +1,13 @@
/* @import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic); */
/* @import "maven_pro.css"; */
@import "lato.css";
html { html {
background: rgba(61, 50, 44, 0) url(brown-lines.jpg) no-repeat center center fixed; background: rgba(61, 50, 44, 0) url(brown-lines.jpg) no-repeat center center fixed;
background-size: cover; background-size: cover;
color: #ccb; color: #ccb;
height: 100%; height: 100%;
font-family: Lato;
} }
body { body {
@ -15,7 +20,7 @@ body {
display: inline-block; display: inline-block;
margin: 1%; margin: 1%;
border: solid black 0.2em; border: solid black 0.2em;
border-radius: 1em 0.25em 1em 1em; border-radius: 1em 1em 0.5em 1em;
overflow: auto; overflow: auto;
} }
@ -38,8 +43,39 @@ body {
height: 70%; height: 70%;
} }
h1 {
text-align: center;
font-size: 120%;
}
a:link {
color: #13a5de;
}
#puzzles dl {
display: inline;
}
#puzzles dd {
margin: 0;
margin-left: 1em;
}
@media (max-width: 52em) { @media (max-width: 52em) {
#overview, #messages, #puzzles, #main { #overview, #messages, #puzzles, #main {
width: 96%; width: 96%;
} }
} }
::-webkit-scrollbar {
width: 0.7em;
}
::-webkit-scrollbar-track {
/* -webkit-box-shadow: inset 0 0 0.5em rgba(200, 200, 200, 0.3); */
background: rgba(0, 0, 0, 0.2);
}
::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.2);
border-radius: 1em;
}

View File

@ -1,29 +1,6 @@
function tx(element, text, bps) { // XXX: Hack for chrome not supporting an iterator method on HTMLCollection
var drawTimer; HTMLCollection.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];
var displayed = "";
var idx = 0;
function draw() {
displayed += text[idx];
element.textContent = displayed;
idx += 1;
if (element.parentNode.lastChild == element) {
element.scrollIntoView();
}
if (text.length == idx) {
clearInterval(drawTimer);
return;
}
}
// N81 uses 1 stop bit, and 1 parity bit.
// That works out to exactly 10 bits per byte.
msec = 10000 / bps;
drawTimer = setInterval(draw, msec);
draw();
}
function Terminal(target, bps) { function Terminal(target, bps) {
bps = bps || 1200; bps = bps || 1200;
@ -31,37 +8,143 @@ function Terminal(target, bps) {
var outq = []; var outq = [];
var outTimer; var outTimer;
function drawElement() { function tx(nodes, bps, scroll) {
var next = outq.shift(); var drawTimer;
var out = document.createElement(next[0]);
target.appendChild(out); // Looks like EMCAScript 6 has a yield statement. That'll be nice.
tx(out, next[1], bps); //
// for (var node of nodes) {
// var text = "";
// for (var c of node._text) {
// text += c;
// node.textContent = text;
// }
// }
if (outq.length == 0) { var nodeIndex = 0;
clearInterval(outTimer); var node = nodes[0];
var textIndex = 0;
var text = "";
function draw() {
var src = node._text;
var c = src[textIndex];
text += c;
node.textContent = text;
textIndex += 1;
if (textIndex == src.length) {
textIndex = 0;
text = "";
nodeIndex += 1;
if (nodeIndex == nodes.length) {
clearInterval(drawTimer);
return;
}
node = nodes[nodeIndex];
}
if (scroll) {
node.scrollIntoView();
}
} }
// N81 uses 1 stop bit, and 1 parity bit.
// That works out to exactly 10 bits per byte.
msec = 10000 / bps;
drawTimer = setInterval(draw, msec);
draw();
} }
this.clear = function() {
while (target.firstChild) {
target.removeChild(target.firstChild);
}
}
this.enqueue = function(tag, txt) { function start() {
outq.push([tag, txt]);
if (! outTimer) { if (! outTimer) {
outTimer = setInterval(drawElement, 150); outTimer = setInterval(drawElement, 150);
} }
} }
this.par = function(txt) {
this.enqueue("p", txt); function stop() {
if (outTimer) {
clearInterval(outTimer);
outTimer = null;
}
} }
function drawElement() {
var element = outq.shift();
console.log(element);
if (! element) {
stop();
return;
}
tx(element._terminalNodes, bps);
}
function prepare(element) {
var nodes = [];
walker = document.createTreeWalker(element, NodeFilter.SHOW_TEXT);
while (walker.nextNode()) {
var node = walker.currentNode;
var text = node.textContent;
node.textContent = "";
nodes.push(node);
}
element._terminalNodes = nodes;
}
// The main entry point: works like appendChild
this.append = function(element) {
prepare(element);
target.appendChild(element);
outq.push(element);
start();
}
// A cool effect where it despools children in parallel
this.appendShallow = function(element) {
for (var child of element.childNodes) {
prepare(child);
outq.push(child);
}
target.appendChild(element);
start();
}
this.clear = function() {
stop();
outq = [];
while (target.firstChild) {
target.removeChild(target.firstChild);
}
}
this.par = function(txt) {
var e = document.createElement("p");
e.textContent = txt;
this.append(e);
}
this.pre = function(txt) { this.pre = function(txt) {
this.enqueue("pre", txt); var e = document.createElement("pre");
e.textContent = txt;
this.append(e);
} }
} }