2024-11-26 15:35:25 -07:00
|
|
|
import {Tank} from "./tank.mjs"
|
|
|
|
|
|
|
|
Math.TAU = Math.PI * 2
|
|
|
|
const Millisecond = 1
|
|
|
|
const Second = 1000 * Millisecond
|
|
|
|
const Minute = 60 * Second
|
|
|
|
const TankRPM = 1
|
|
|
|
const TurretRPM = 4
|
2024-11-26 17:52:30 -07:00
|
|
|
const FPS = 12
|
2024-11-26 15:35:25 -07:00
|
|
|
|
|
|
|
function deg2rad(angle) {
|
|
|
|
return angle*Math.TAU/360;
|
|
|
|
}
|
|
|
|
|
|
|
|
function update(ctx) {
|
|
|
|
let color = document.querySelector("[name=color]").value
|
|
|
|
let sensors = []
|
|
|
|
|
|
|
|
for (let i = 0; i < 10; i += 1) {
|
|
|
|
let range = document.querySelector(`[name=s${i}r]`).value
|
|
|
|
let angle = document.querySelector(`[name=s${i}a]`).value
|
|
|
|
let width = document.querySelector(`[name=s${i}w]`).value
|
|
|
|
let turret = document.querySelector(`[name=s${i}t]`).checked
|
|
|
|
|
2024-11-26 17:52:30 -07:00
|
|
|
sensors[i] = {
|
|
|
|
range: Math.min(range, 100),
|
|
|
|
angle: deg2rad(angle % 360),
|
|
|
|
width: deg2rad(width % 360),
|
|
|
|
turret: turret,
|
|
|
|
}
|
2024-11-26 15:35:25 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
let tankRevs = -TankRPM * (Date.now() / Minute)
|
|
|
|
let turretRevs = TurretRPM * (Date.now() / Minute)
|
|
|
|
let tank = new Tank(ctx, color, sensors);
|
|
|
|
tank.set_state(
|
|
|
|
100, 100,
|
|
|
|
(tankRevs * Math.TAU) % Math.TAU,
|
|
|
|
(turretRevs * Math.TAU) % Math.TAU,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
)
|
|
|
|
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height)
|
|
|
|
tank.draw_sensors()
|
|
|
|
tank.draw_tank()
|
|
|
|
}
|
|
|
|
|
|
|
|
function formSubmit(event) {
|
|
|
|
event.preventDefault()
|
|
|
|
|
|
|
|
let formData = new FormData(event.target)
|
|
|
|
for (let [k, v] of formData.entries()) {
|
|
|
|
localStorage.setItem(k, v)
|
|
|
|
}
|
|
|
|
|
|
|
|
let files = {
|
|
|
|
name: formData.get("name"),
|
|
|
|
color: formData.get("color"),
|
|
|
|
author: formData.get("author"),
|
|
|
|
program: formData.get("program"),
|
|
|
|
}
|
|
|
|
for (let i = 0; i < 10; i++) {
|
|
|
|
let r = formData.get(`s${i}r`) || 0
|
|
|
|
let a = formData.get(`s${i}a`) || 0
|
|
|
|
let w = formData.get(`s${i}w`) || 0
|
|
|
|
let t = (formData.get(`s${i}t`) == "on") ? 1 : 0
|
|
|
|
files[`sensor${i}`] = `${r} ${a} ${w} ${t}`
|
|
|
|
}
|
|
|
|
|
|
|
|
let id = formData.get("id")
|
|
|
|
let apiURL = new URL(`tanks/${id}/`, location)
|
|
|
|
|
|
|
|
// Fill slots
|
|
|
|
for (let k in files) {
|
|
|
|
let v = files[k]
|
|
|
|
for (let e of document.querySelectorAll(`slot[name="${k}"]`)) {
|
|
|
|
e.textContent = v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (let e of document.querySelectorAll("slot[name=apiurl]")) {
|
|
|
|
e.textContent = apiURL
|
|
|
|
}
|
|
|
|
|
|
|
|
// Upload files
|
2024-11-26 17:52:30 -07:00
|
|
|
let pending = 0
|
|
|
|
let errors = 0
|
|
|
|
let begin = performance.now()
|
2024-11-26 15:35:25 -07:00
|
|
|
for (let k in files) {
|
|
|
|
let url = new URL(k, apiURL)
|
|
|
|
let opts = {
|
|
|
|
method: "PUT",
|
|
|
|
body: files[k],
|
|
|
|
}
|
2024-11-26 17:52:30 -07:00
|
|
|
pending += 1
|
2024-11-26 15:35:25 -07:00
|
|
|
fetch(url, opts)
|
|
|
|
.then(resp => {
|
2024-11-26 17:52:30 -07:00
|
|
|
pending -= 1
|
2024-11-26 15:35:25 -07:00
|
|
|
if (!resp.ok) {
|
2024-11-26 17:52:30 -07:00
|
|
|
errors += 1
|
|
|
|
}
|
|
|
|
if (pending == 0) {
|
|
|
|
let duration = (performance.now() - begin).toPrecision(2)
|
|
|
|
let debug = document.querySelector("#debug")
|
|
|
|
if (debug) {
|
|
|
|
let msg = `tank uploaded in ${duration}ms`
|
|
|
|
if (errors > 0) {
|
|
|
|
msg = msg + `; ${errors} errors`
|
|
|
|
}
|
|
|
|
debug.textContent = msg
|
|
|
|
|
|
|
|
setTimeout(() => debug.textContent = "", 2 * Second)
|
|
|
|
}
|
2024-11-26 15:35:25 -07:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function init() {
|
|
|
|
let canvas = document.querySelector("#design")
|
|
|
|
let ctx = canvas.getContext("2d")
|
|
|
|
canvas.width = 200
|
|
|
|
canvas.height = 200
|
|
|
|
|
|
|
|
let form = document.querySelector("form#upload")
|
|
|
|
form.addEventListener("submit", formSubmit)
|
|
|
|
|
|
|
|
let tbody = document.querySelector("#sensors tbody")
|
|
|
|
for (let i = 0; i < 10; i++) {
|
|
|
|
let tr = tbody.appendChild(document.createElement("tr"))
|
|
|
|
|
|
|
|
tr.appendChild(document.createElement("td")).textContent = i
|
|
|
|
|
|
|
|
let range = tr.appendChild(document.createElement("td")).appendChild(document.createElement("input"))
|
|
|
|
range.name = `s${i}r`
|
|
|
|
range.type = "number"
|
|
|
|
range.min = 0
|
|
|
|
range.max = 100
|
|
|
|
range.value = 0
|
|
|
|
|
|
|
|
let angle = tr.appendChild(document.createElement("td")).appendChild(document.createElement("input"))
|
|
|
|
angle.name = `s${i}a`
|
|
|
|
angle.type = "number"
|
|
|
|
angle.min = -360
|
|
|
|
angle.max = 360
|
|
|
|
|
|
|
|
let width = tr.appendChild(document.createElement("td")).appendChild(document.createElement("input"))
|
|
|
|
width.name = `s${i}w`
|
|
|
|
width.type = "number"
|
|
|
|
width.min = -360
|
|
|
|
width.max = 360
|
|
|
|
|
|
|
|
let turret = tr.appendChild(document.createElement("td")).appendChild(document.createElement("input"))
|
|
|
|
turret.name = `s${i}t`
|
|
|
|
turret.type = "checkbox"
|
|
|
|
}
|
|
|
|
|
|
|
|
// Load in previous values
|
|
|
|
for (let e of form.querySelectorAll("[name]")) {
|
|
|
|
let v = localStorage.getItem(e.name)
|
|
|
|
if (v !== undefined) {
|
|
|
|
e.checked = (v == "on")
|
|
|
|
e.value = v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
update(ctx)
|
2024-11-26 17:52:30 -07:00
|
|
|
setInterval(() => update(ctx), Second / FPS)
|
2024-11-26 15:35:25 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
init()
|