02cdfc98dd
Changes: - If an out of range update is received, set the current progress to zero or max to avoid getting stuck on the default value when the page is loaded after exceeding the goal.
304 lines
8.0 KiB
JavaScript
304 lines
8.0 KiB
JavaScript
window.addEventListener("DOMContentLoaded", () => {
|
|
//Create progress bar
|
|
const book_bar = new ProgressBar();
|
|
|
|
//Pat Lilac
|
|
const websocket = new ReconnectingWebSocket("wss://lilac.thewisewolf.dev/tracker/timer/ws");
|
|
communicate(websocket, book_bar);
|
|
|
|
});
|
|
|
|
|
|
class ProgressBar {
|
|
constructor() {
|
|
this.current_progress = 25;
|
|
this.max_progress = 45;
|
|
this.anim_progress = 0;
|
|
this.animating = false;
|
|
this.simming = false;
|
|
this.target_element = document.getElementById("progressBar");
|
|
this.bar_back = document.getElementById("barBack");
|
|
this.bar_front = document.getElementById("barFront");
|
|
//Pre-load and hold background images
|
|
let image_cache = [];
|
|
for (let i = 0; i < 46; i++) {
|
|
const img_fetcher = new Image();
|
|
let index_string = i.toString();
|
|
if (index_string.length < 2) {
|
|
index_string = "0" + index_string;
|
|
}
|
|
img_fetcher.src = "src/Books/BookBar_f00" + index_string + ".png";
|
|
image_cache.push(img_fetcher);
|
|
};
|
|
}
|
|
|
|
//SET NUMBER OF COLORED BOOKS
|
|
|
|
//Set current campaign progress
|
|
setProgress(val) {
|
|
if (Number.isInteger(val)
|
|
&& (val >= 0)
|
|
&& (val <= this.max_progress)
|
|
&& (val != this.current_progress)) {
|
|
this.current_progress = val;
|
|
this.anim_progress = 0;
|
|
} else {
|
|
if (Number.isInteger(val)
|
|
&& (val >= this.max_progress)
|
|
&& (val != this.current_progress)) {
|
|
this.current_progress = this.max_progress;
|
|
this.anim_progress = 0;
|
|
console.warn("Progress update: Goal Exceeded.")
|
|
}
|
|
if (Number.isInteger(val)
|
|
&& (val <= 0)
|
|
&& (val != this.current_progress)) {
|
|
this.current_progress = 0;
|
|
this.anim_progress = 0;
|
|
console.warn("Progress update: Goal Subceeded.")
|
|
}
|
|
console.warn("Progress update failed.")
|
|
}
|
|
}
|
|
|
|
//Render current animation state to the screen
|
|
renderProgress(val) {
|
|
if (Number.isInteger(val)
|
|
&& (this.target_element != null)
|
|
&& (this.bar_back != null)
|
|
&& (this.bar_front != null)
|
|
&& (val >= 0)
|
|
&& (val <= this.current_progress)
|
|
&& (val <= this.max_progress)) {
|
|
let val_string = val.toString();
|
|
if (val_string.length < 2) {
|
|
val_string = "0" + val_string;
|
|
}
|
|
this.bar_back.style.backgroundImage = "url(src/Books/BookBar_f00" + val_string + ".png)";
|
|
setTimeout(this.antiFlash.bind(this), 150, val_string, val);
|
|
} else {
|
|
console.warn("Progress render failed.")
|
|
}
|
|
}
|
|
|
|
//Prevent image flicker by pre-loading a version of the image then rendering the top image with a delay
|
|
antiFlash(val_string, new_val) {
|
|
this.bar_front.style.backgroundImage = "url(src/Books/BookBar_f00" + val_string + ".png)";
|
|
//Increment the animation ticker (plus an extra round of safety checks)
|
|
if ((new_val >= 0)
|
|
&& (new_val <= this.current_progress)
|
|
&& (this.anim_progress <= this.max_progress)
|
|
&& (new_val <= this.max_progress)) {
|
|
this.anim_progress = new_val;
|
|
}
|
|
else {
|
|
console.warn("Anim antiFlash render is out of range.");
|
|
}
|
|
}
|
|
|
|
//Progress Animation
|
|
animProgress() {
|
|
//animate
|
|
if (this.animating == true) {
|
|
if ((this.anim_progress >= 0)
|
|
&& (this.anim_progress < this.current_progress)
|
|
&& (this.anim_progress < this.max_progress)) {
|
|
this.renderProgress(this.anim_progress + 1);
|
|
setTimeout(this.animProgress.bind(this), 500);
|
|
}
|
|
//loop
|
|
if (this.anim_progress == this.current_progress) {
|
|
setTimeout(this.renderProgress.bind(this, 0), 5000);
|
|
setTimeout(this.animProgress.bind(this), 5500);
|
|
}
|
|
}
|
|
}
|
|
|
|
//Toggle animation on
|
|
animStart() {
|
|
if (this.animating != true){
|
|
this.animating = true;
|
|
this.animProgress();
|
|
} else {
|
|
console.warn("Animation already running");
|
|
}
|
|
}
|
|
|
|
//Toggle animation off
|
|
animEnd() {
|
|
this.animating = false;
|
|
}
|
|
|
|
//TEST SIMULATION
|
|
simProgress() {
|
|
//sim
|
|
if (this.simming == true) {
|
|
if (this.current_progress < this.max_progress) {
|
|
this.setProgress(this.current_progress + 1);
|
|
setTimeout(this.simProgress.bind(this), 38500);
|
|
}
|
|
//loop
|
|
if (this.current_progress == this.max_progress) {
|
|
setTimeout(() => this.setProgress(0), 10000);
|
|
setTimeout(this.simProgress.bind(this), 95500);
|
|
}
|
|
}
|
|
}
|
|
|
|
simStart() {
|
|
console.log("starting");
|
|
this.simming = true;
|
|
this.simProgress();
|
|
console.log("started");
|
|
}
|
|
|
|
simEnd() {
|
|
console.log("ending");
|
|
this.simming = false;
|
|
}
|
|
|
|
}
|
|
|
|
class ReconnectingWebSocket {
|
|
constructor(url) {
|
|
this.url = url;
|
|
this.ws = null;
|
|
this.attempt = 0;
|
|
this.connect();
|
|
|
|
this.closing = false;
|
|
this.onopen = null;
|
|
this.onmessage = null;
|
|
this.onclose = null;
|
|
this.onerror = null;
|
|
}
|
|
|
|
connect() {
|
|
this.ws = new WebSocket(this.url);
|
|
|
|
this.ws.onopen = () => {
|
|
console.log('WebSocket connecting');
|
|
this.attempt = 0;
|
|
if (this.onopen != null) {
|
|
this.onopen();
|
|
}
|
|
};
|
|
|
|
this.ws.onmessage = (msg) => {
|
|
console.log('Received:', msg.data);
|
|
if (this.onmessage != null) {
|
|
this.onmessage(msg);
|
|
}
|
|
};
|
|
|
|
this.ws.onclose = () => {
|
|
if (this.closing) {
|
|
console.log('Closing Websocket.')
|
|
} {
|
|
console.warn('WebSocket closed. Reconnecting...');
|
|
this.reconnect();
|
|
}
|
|
};
|
|
|
|
this.ws.onerror = (err) => {
|
|
console.error('WebSocket error:', err);
|
|
if (this.onerror != null) {
|
|
this.onerror();
|
|
}
|
|
this.close();
|
|
};
|
|
}
|
|
|
|
reconnect() {
|
|
const delay = this.getBackoffDelay(this.attempt);
|
|
console.log(`Reconnecting in ${delay}ms`);
|
|
|
|
setTimeout(() => {
|
|
this.attempt++;
|
|
this.connect();
|
|
}, delay);
|
|
}
|
|
|
|
close() {
|
|
this.closing = true;
|
|
this.ws.close();
|
|
if (this.onclose != null) {
|
|
this.onclose();
|
|
}
|
|
}
|
|
|
|
getBackoffDelay(attempt) {
|
|
const base = 500; // 0.5 second
|
|
const max = 30000; // 30 seconds
|
|
const jitter = Math.random() * 1000;
|
|
return Math.min(base * 2 ** attempt + jitter, max);
|
|
}
|
|
|
|
send(data) {
|
|
if (this.ws.readyState === WebSocket.OPEN) {
|
|
this.ws.send(data);
|
|
} else {
|
|
console.warn('WebSocket not connected');
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
function communicate(websocket, book_bar) {
|
|
console.log("Communicating");
|
|
const params = new URLSearchParams(window.location.search);
|
|
// INITIALIZE CLASS HERE
|
|
//queue animation start after a few seconds to allow for initial status from server
|
|
setTimeout(book_bar.animStart.bind(book_bar),5000);
|
|
|
|
websocket.onopen = () => {
|
|
websocket.send(
|
|
JSON.stringify(
|
|
{
|
|
type: "init",
|
|
channel: "CampaignRewards",
|
|
community: params.get('community')
|
|
}
|
|
)
|
|
);
|
|
};
|
|
|
|
websocket.onmessage = ({ data }) => {
|
|
console.log("messaged");
|
|
const event = JSON.parse(data);
|
|
switch (event.type) {
|
|
case "DO":
|
|
let args = event.args;
|
|
|
|
// Call the specified method
|
|
switch (event.method) {
|
|
case "setTimer":
|
|
//do something with the new data
|
|
console.log("set timer: " + args.reward_progress);
|
|
book_bar.setProgress(args.reward_progress);
|
|
//animEnd();
|
|
//setTimeout(book_bar.setProgress(args.reward_progress), 7500);
|
|
//setTimeout(book_bar.animStart, 7800);
|
|
break;
|
|
case "noTimer":
|
|
//do something default
|
|
console.log("no timer: " + args);
|
|
break;
|
|
case "endTimer":
|
|
//do something for the final time
|
|
console.log("end timer: " + args);
|
|
//book_bar.renderProgress(args.reward_progress);
|
|
//book_bar.animEnd();
|
|
//setTimeout(book_bar.renderProgress(args.reward_progress), 7500);
|
|
//setTimeout(book_bar.animStart, 7800);
|
|
break
|
|
default:
|
|
throw new Error(`Unsupported method requested: ${event.method}.`)
|
|
}
|
|
break;
|
|
default:
|
|
throw new Error(`Unsupported event type: ${event.type}.`);
|
|
}
|
|
};
|
|
}
|