tanks/www/designer.mjs

171 lines
4.8 KiB
JavaScript

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
const FPS = 12
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
sensors[i] = {
range: Math.min(range, 100),
angle: deg2rad(angle % 360),
width: deg2rad(width % 360),
turret: turret,
}
}
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
let pending = 0
let errors = 0
let begin = performance.now()
for (let k in files) {
let url = new URL(k, apiURL)
let opts = {
method: "PUT",
body: files[k],
}
pending += 1
fetch(url, opts)
.then(resp => {
pending -= 1
if (!resp.ok) {
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)
}
}
})
}
}
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)
setInterval(() => update(ctx), Second / FPS)
}
init()