diff --git a/thrimbletrimmer/driveclock/db_dawn.png b/thrimbletrimmer/driveclock/db_dawn.png
deleted file mode 100644
index 552dc35..0000000
Binary files a/thrimbletrimmer/driveclock/db_dawn.png and /dev/null differ
diff --git a/thrimbletrimmer/driveclock/db_day.png b/thrimbletrimmer/driveclock/db_day.png
deleted file mode 100644
index 5cf7d3a..0000000
Binary files a/thrimbletrimmer/driveclock/db_day.png and /dev/null differ
diff --git a/thrimbletrimmer/driveclock/db_dusk.png b/thrimbletrimmer/driveclock/db_dusk.png
deleted file mode 100644
index b58fb45..0000000
Binary files a/thrimbletrimmer/driveclock/db_dusk.png and /dev/null differ
diff --git a/thrimbletrimmer/driveclock/db_night.png b/thrimbletrimmer/driveclock/db_night.png
deleted file mode 100644
index c444a53..0000000
Binary files a/thrimbletrimmer/driveclock/db_night.png and /dev/null differ
diff --git a/thrimbletrimmer/driveclock/db_stop.png b/thrimbletrimmer/driveclock/db_stop.png
new file mode 100644
index 0000000..6bc52e8
Binary files /dev/null and b/thrimbletrimmer/driveclock/db_stop.png differ
diff --git a/thrimbletrimmer/driveclock/drive.css b/thrimbletrimmer/driveclock/drive.css
new file mode 100644
index 0000000..e69de29
diff --git a/thrimbletrimmer/driveclock/drive.html b/thrimbletrimmer/driveclock/drive.html
index 6d79160..bdcd78f 100644
--- a/thrimbletrimmer/driveclock/drive.html
+++ b/thrimbletrimmer/driveclock/drive.html
@@ -1,54 +1,12 @@
-
-
-
-
-
-
-
-
-
-
-
+
+
+ Bus Progress
+
+
+
+
+
+
+
diff --git a/thrimbletrimmer/driveclock/drive.js b/thrimbletrimmer/driveclock/drive.js
index 788bde4..ab571cc 100644
--- a/thrimbletrimmer/driveclock/drive.js
+++ b/thrimbletrimmer/driveclock/drive.js
@@ -1,122 +1,198 @@
-
-const PAGE_WIDTH = 1920;
-const MINUTES_PER_PAGE = 60;
-const POINT_WIDTH = PAGE_WIDTH * 8 * 60 / MINUTES_PER_PAGE;
-const MILES_PER_PAGE = 45;
-const BUS_POSITION_X = 93;
-const BASE_ODO = 109.3;
-const UPDATE_INTERVAL_MS = 5000
-const WUBLOADER_URL = "";
-const SKY_URLS = {
- day: "db_day.png",
- dawn: "db_dawn.png",
- dusk: "db_dusk.png",
- night: "db_night.png",
-};
-const BUS_URLS = {
- day: "bus_day.png",
- dawn: "bus_day.png",
- dusk: "bus_day.png",
- night: "bus_night.png",
+const COLORS = {
+ day: {
+ sky: "#41cee2",
+ ground: "#e5931b",
+ surface: "#b77616",
+ },
+ dusk: {
+ sky: "#db92be",
+ ground: "#dd926a",
+ surface: "#b17555",
+ },
+ night: {
+ sky: "#121336",
+ ground: "#30201a",
+ surface: "#261a15",
+ },
+ dawn: {
+ sky: "#2b2f87",
+ ground: "#724d41",
+ surface: "#5b3e34",
+ },
};
-function setSkyElements(left, right, timeToTransition) {
- const leftElement = document.getElementById("timeofday-left");
- const rightElement = document.getElementById("timeofday-right");
- const busElement = document.getElementById("bus");
+// The width from the left side of the bus image to the front of the bus
+const BUS_FRONT_OFFSET = 73;
- leftElement.style.backgroundImage = `url(${SKY_URLS[left]})`;
- rightElement.style.backgroundImage = `url(${SKY_URLS[right]})`;
+// Start time of each day phase
+const DAY_START_MINUTES = 450;
+const DUSK_START_MINUTES = 1140;
+const NIGHT_START_MINUTES = 1200;
+const DAWN_START_MINUTES = 400;
- if (left === right) {
- leftElement.style.width = "100%";
- } else {
- const transitionPercent = timeToTransition / MINUTES_PER_PAGE;
- leftElement.style.width = `${transitionPercent * 100}%`
- }
+const BUS_STOP_OFFSET = 6;
+const POINT_OFFSET = 17;
- bus.style.backgroundImage = `url(${BUS_URLS[left]})`;
-}
+// Bus stop positions are recorded in miles with the 0 position
+// at route start. This array can be looped every point.
+const BUS_STOP_POSITIONS = [1, 55.2, 125.4, 166.3, 233.9, 295.2];
-function nextSkyTransition(timeofday, clock) {
- switch (timeofday) {
- case "dawn":
+// The default scaling factor is 20 seconds per pixel at max speed.
+// This gives us
+// - 3px per minute
+// - 4px per mile
+let scaleFactor = 1;
+
+function nextPhase(timeOfDay) {
+ switch (timeOfDay) {
case "day":
- return [19 * 60, "dusk"]; // 7pm
+ case "dawn":
+ return "dusk";
case "dusk":
- return [20 * 60, "night"]; // 8pm
+ return "night";
case "night":
- return [6 * 60 + 40, "dawn"]; // 6:40am
+ return "dawn";
}
}
-function setSky(timeofday, clock) {
- const [transition, newSky] = nextSkyTransition(timeofday, clock);
- // 1440 minutes in 24h, this code will return time remaining even if
- // the transition is in the morning and we're currently in the evening.
- const timeToTransition = (1440 + transition - clock) % 1440;
- if (timeToTransition < MINUTES_PER_PAGE) {
- // Transition on screen
- setSkyElements(timeofday, newSky, timeToTransition);
- } else {
- // No transition on screen
- setSkyElements(timeofday, timeofday, undefined);
+function phaseStartTime(timeOfDay) {
+ switch (timeOfDay) {
+ case "day":
+ return DAY_START_MINUTES;
+ case "dusk":
+ return DUSK_START_MINUTES;
+ case "night":
+ return NIGHT_START_MINUTES;
+ case "dawn":
+ return DAWN_START_MINUTES;
}
}
-function setOdo(odo) {
- const distancePixels = PAGE_WIDTH * (odo - BASE_ODO) / MILES_PER_PAGE;
- const offset = (BUS_POSITION_X - distancePixels) % POINT_WIDTH;
+function drawBackground(context, timeOfDay, leftX, width) {
+ const skyColor = COLORS[timeOfDay].sky;
+ const groundColor = COLORS[timeOfDay].ground;
+ const surfaceColor = COLORS[timeOfDay].surface;
- const stopsElement = document.getElementById("stops");
- stopsElement.style.backgroundPosition = `${offset}px 0px`;
+ context.fillStyle = COLORS[timeOfDay].sky;
+ context.fillRect(leftX, 0, width, 100);
+ context.fillStyle = COLORS[timeOfDay].surface;
+ context.fillRect(leftX, 80, width, 1);
+ context.fillStyle = COLORS[timeOfDay].ground;
+ context.fillRect(leftX, 81, width, 7);
+ context.fillRect(leftX, 89, width, 3);
+ context.fillRect(leftX, 94, width, 2);
+ context.fillRect(leftX, 99, width, 1);
}
-async function update() {
- const busDataResponse = await fetch(`${WUBLOADER_URL}/thrimshim/bus/buscam`);
- if (!busDataResponse.ok) {
- return;
- }
- const busData = await busDataResponse.json();
- console.log("Got data:", busData);
- setOdo(busData.odometer);
- setSky(busData.timeofday, busData.clock_minutes);
-}
+async function drawRoad() {
+ const busDataResponse = await fetch("/thrimshim/bus/buscam");
+ if (!busDataResponse.ok) {
+ return;
+ }
+ const busData = await busDataResponse.json();
+
+ const canvas = document.getElementById("road");
+ if (!canvas.getContext) {
+ return;
+ }
+ const context = canvas.getContext("2d");
+
+ // Clear the previous canvas before starting
+ context.clearRect(0, 0, 1920, 100);
+
+ const currentTime = busData.clock_minutes;
+ const distance = busData.odometer;
+ const timeOfDay = busData.timeofday;
+
+ drawBackground(context, timeOfDay, 0, BUS_FRONT_OFFSET);
-// Initial conditions, before the first refresh finishes
-setSky("day", 7 * 60);
-setOdo(BASE_ODO);
-
-// Testing mode. Set true to enable.
-const test = false;
-if (test) {
- let h = 0;
- // Set to how long 1h of in-game time should take in real time
- const hourTimeMs = 1 * 1000;
- // Set to how often to update the screen
- const interval = 30;
- setInterval(() => {
- h += interval / hourTimeMs;
- setOdo(BASE_ODO + 45 * h);
- if (h < 19) {
- setSky("day", 60 * h);
- } else {
- m = (h % 24) * 60;
- let tod;
- if (m < 6 * 60 + 40) {
- tod = "night";
- } else if (m < 19 * 60) {
- tod = "dawn";
- } else if (m < 20 * 60) {
- tod = "dusk";
- } else {
- tod = "night";
+ const maxWidth = 1920 - BUS_FRONT_OFFSET;
+
+ // TODO Figure out scaling factor
+ const startMinute = busData.clock_minutes;
+ const timeDuration = maxWidth / 3;
+
+ let previousTime = startMinute;
+ let previousTimeOfDay = timeOfDay;
+ let remainingDuration = timeDuration;
+ let x = BUS_FRONT_OFFSET;
+ while (remainingDuration > 0) {
+ const nextTimeOfDay = nextPhase(previousTimeOfDay);
+ const nextStartTime = phaseStartTime(nextTimeOfDay);
+
+ let thisDuration = nextStartTime - previousTime;
+ if (thisDuration < 0) {
+ thisDuration += 1440;
+ }
+
+ // TODO Figure out scaling factor
+ const pixelWidth = thisDuration * 3;
+ drawBackground(context, previousTimeOfDay, x, pixelWidth);
+
+ remainingDuration -= thisDuration;
+ previousTime = nextStartTime;
+ previousTimeOfDay = nextTimeOfDay;
+ x += pixelWidth;
+ }
+
+ x = BUS_FRONT_OFFSET;
+ const currentPointProgress = distance % 360;
+ let distanceToNextPoint;
+ if (currentPointProgress <= 109.3) {
+ distanceToNextPoint = 109.3 - currentPointProgress;
+ } else {
+ distanceToNextPoint = 469.3 - currentPointProgress;
+ }
+
+ // TODO Figure out scaling factor
+ x += distanceToNextPoint * 4;
+ const pointImage = new Image();
+ pointImage.src = "point.png";
+ context.drawImage(pointImage, x - POINT_OFFSET, 0);
+ while (x < maxWidth) {
+ // TODO Figure out scaling factor
+ x += 360 * 4;
+ context.drawImage(pointImage, x - POINT_OFFSET, 0);
+ }
+
+ const distanceOnRoute = (distance - 109.3) % 360;
+ const busStopImage = new Image();
+ busStopImage.src = "db_stop.png";
+ // TODO Figure out scaling factor
+ let distanceTracked = distanceOnRoute - BUS_FRONT_OFFSET / 4;
+ if (distanceTracked < 0) {
+ distanceTracked += 720;
+ }
+ x = 0;
+ while (x < 1920) {
+ const distanceTrackedOnRoute = distanceTracked % 360;
+ let nextBusStopPosition = null;
+ for (const busStopPosition of BUS_STOP_POSITIONS) {
+ if (busStopPosition >= distanceTrackedOnRoute + 1) {
+ nextBusStopPosition = busStopPosition;
+ break;
}
- setSky(tod, m);
}
- }, interval);
-} else {
- // Do first update immediately, then every UPDATE_INTERVAL_MS
- setInterval(update, UPDATE_INTERVAL_MS);
- update();
+ if (nextBusStopPosition === null) {
+ nextBusStopPosition = 360 + BUS_STOP_POSITIONS[0];
+ }
+ const nextBusStopDistance = nextBusStopPosition - distanceTrackedOnRoute;
+ distanceTracked += nextBusStopDistance;
+ // TODO Figure out scaling factor
+ x += nextBusStopDistance * 4;
+ context.drawImage(busStopImage, x - BUS_STOP_OFFSET, 0);
+ }
+
+ const busImage = new Image();
+ if (timeOfDay === "night") {
+ busImage.src = "bus_night.png";
+ } else {
+ busImage.src = "bus_day.png";
+ }
+ context.drawImage(busImage, 0, 0);
}
+
+window.addEventListener("DOMContentLoaded", (event) => {
+ drawRoad();
+ setInterval(drawRoad, 10000);
+});
diff --git a/thrimbletrimmer/driveclock/point.png b/thrimbletrimmer/driveclock/point.png
new file mode 100644
index 0000000..601c57a
Binary files /dev/null and b/thrimbletrimmer/driveclock/point.png differ
diff --git a/thrimbletrimmer/driveclock/stops.png b/thrimbletrimmer/driveclock/stops.png
deleted file mode 100644
index 552266e..0000000
Binary files a/thrimbletrimmer/driveclock/stops.png and /dev/null differ