This commit is contained in:
Victor Westerlund 2021-10-06 17:12:40 +02:00
parent 19fa7ed3af
commit 6991138f85
3 changed files with 102 additions and 26 deletions

View file

@ -4,13 +4,13 @@ export default class Monkeydo extends MonkeyWorker {
constructor(manifest = false) { constructor(manifest = false) {
super(); super();
this.monkeydo = { this.monkeydo = {
version: "0.1", version: "0.2.0",
debugLevel: 0, debugLevel: 0,
// Flag if debugging is enabled, regardless of level // Flag if debugging is enabled, regardless of level
get debug() { get debug() {
return this.debugLevel > 0 ? true : false; return this.debugLevel > 0 ? true : false;
}, },
// Set debug level. Non-verbose debugging by default // Set debug level. Non-verbose debugging if called without an argument
set debug(level = 1) { set debug(level = 1) {
this.debugLevel = level; this.debugLevel = level;
} }
@ -32,13 +32,29 @@ export default class Monkeydo extends MonkeyWorker {
} }
} }
debug(attachment = "DEBUG_EMPTY") { debug(...attachment) {
if(this.monkeydo.debug) { if(this.monkeydo.debug) {
console.warn("-- Monkeydo debug -->",attachment); console.warn("-- Monkeydo debug -->",attachment);
return; return;
} }
} }
play() {
this.worker.postMessage(["SET_PLAYING",true]);
this.worker.addEventListener("message",message => eval(message.data));
}
pause() {
this.worker.postMessage(["SET_PLAYING",false]);
}
loop(times) {
if(!times || times === "infinite") {
times = -1;
}
this.setFlag("loop",times);
}
// Load a Monkeydo manifest from JSON via string or URL // Load a Monkeydo manifest from JSON via string or URL
async load(manifest) { async load(manifest) {
const errorPrefix = "MANIFEST_IMPORT_FAILED: "; const errorPrefix = "MANIFEST_IMPORT_FAILED: ";

View file

@ -5,6 +5,12 @@ class Monkey {
this.data = manifest.body; this.data = manifest.body;
this.dataLength = this.data.length - 1; 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.i = 0;
this.queue = { this.queue = {
task: null, task: null,
@ -13,38 +19,66 @@ class Monkey {
Object.seal(this.queue); Object.seal(this.queue);
} }
// Parse task components and send them to main thread
run(data) { run(data) {
this.i++; this.i++; // Advance index
postMessage(data); postMessage(data);
console.log(this.i);
} }
queueNext() { // Interrupt timeout and put monkey to sleep
const data = this.data[this.i];
this.queue.task = setTimeout(() => this.run(data.do),data.wait);
// Schedule next task if it's not the last
if(this.i >= this.dataLength) {
this.i = 0;
return false;
}
this.queue.next = setTimeout(() => this.queueNext(),data.wait);
}
interrupt() { interrupt() {
clearTimeout(this.queue.task); clearTimeout(this.queue.task);
clearTimeout(this.queue.next); clearTimeout(this.queue.next);
this.queue.task = null; this.queue.task = null;
this.queue.next = 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 event handler for this worker // Global message event handler for this worker
onmessage = (message) => { onmessage = (message) => {
const type = message.data[0] ? message.data[0] : null; const type = message.data[0] ? message.data[0] : message.data;
const data = message.data[1]; const data = message.data[1];
switch(type) { switch(type) {
// Attempt to load manfiest provided by initiator thread
case "GIVE_MANIFEST": case "GIVE_MANIFEST":
try { try {
this.monkey = new Monkey(data); this.monkey = new Monkey(data);
@ -55,8 +89,24 @@ onmessage = (message) => {
} }
break; break;
case "PLAYING": // Set playstate
this.monkey.queueNext(); 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; break;
default: return; // No op default: return; // No op

View file

@ -11,13 +11,23 @@ export default class TaskManager {
this.worker = new Worker(location + "Monkey.js"); this.worker = new Worker(location + "Monkey.js");
} }
play() { // Get a status flag from the worker
this.worker.postMessage(["PLAYING",true]); async getFlag(flag) {
this.worker.addEventListener("message",message => eval(message.data)); this.worker.postMessage(["GET_FLAG",flag]);
const response = await new Promise((resolve) => {
this.worker.addEventListener("message",message => resolve(message.data));
});
return response;
} }
pause() { // Set a status flag for the worker
this.worker.postMessage(["PLAYING",false]); async setFlag(flag,value = 0) {
const flagExists = await this.getFlag(flag);
if(!flagExists) {
this.debug(flagExists);
throw new Error("Flag does not not exist");
}
this.worker.postMessage(["SET_FLAG",[flag,value]]);
} }
// Pass manifest to worker and await response // Pass manifest to worker and await response