monkeydo/worker/Monkey.js
2021-10-06 17:12:40 +02:00

114 lines
No EOL
2.4 KiB
JavaScript

// Task scheduler and iterator of Monkeydo manifests
class Monkey {
constructor(manifest) {
this.data = manifest.body;
this.dataLength = this.data.length - 1;
this.flags = {
playing: 0,
stacking: 0, // Subsequent calls to play() will build a queue (jQuery-style)
loop: 0, // Loop n times; <0 = infinite
}
this.i = 0;
this.queue = {
task: null,
next: null
}
Object.seal(this.queue);
}
// Parse task components and send them to main thread
run(data) {
this.i++; // Advance index
postMessage(data);
console.log(this.i);
}
// Interrupt timeout and put monkey to sleep
interrupt() {
clearTimeout(this.queue.task);
clearTimeout(this.queue.next);
this.queue.task = null;
this.queue.next = null;
this.flags.playing = 0;
}
play() {
if(this.flags.playing) {
if(this.flags.stacking) {
this.flags.loop++;
}
return;
}
this.queueNext();
}
// Schedule task for execution by index
queueNext() {
this.flags.playing = 1;
const data = this.data[this.i];
// Schedule the current task to run after the specified wait time
this.queue.task = setTimeout(() => this.run(data.do),data.wait);
// We're out of tasks to schedule..
if(this.i >= this.dataLength) {
this.i = -1;
// Exit if we're out of loops
if(this.flags.loop === 0) {
this.flags.playing = 0;
return false;
}
if(this.flags.loop <= -1) {
this.flags.loop = this.flags.loop - 1;
}
}
// Run this function again when the scheduled task will fire
this.queue.next = setTimeout(() => this.queueNext(),data.wait);
}
}
// Global message event handler for this worker
onmessage = (message) => {
const type = message.data[0] ? message.data[0] : message.data;
const data = message.data[1];
switch(type) {
// Attempt to load manfiest provided by initiator thread
case "GIVE_MANIFEST":
try {
this.monkey = new Monkey(data);
postMessage("OK");
}
catch(error) {
postMessage(["MANIFEST_ERROR",error]);
}
break;
// Set playstate
case "SET_PLAYING":
if(data === true) {
this.monkey.play();
return;
}
// Treat data that isn't a TRUE boolean as an interrupt
this.monkey.interrupt();
break;
case "GET_FLAG":
const flag = this.monkey.flags[data];
postMessage(parseInt(flag));
break;
case "SET_FLAG":
console.log(data);
this.monkey.flags[data[0]] = data[1];
break;
default: return; // No op
}
}