import type { Body } from "../calculations/constants"; import { extrapolateTrajectory, type OrbitalCoordinates } from "../calculations/orbit-calculations"; import type { ChangingStorageValue } from "../storage"; import { getCoordinatesFromParameters, getOrbitFromParameters, type OrbitalParameters } from "./common"; import { ManoeuvresGui } from "./manoeuvres"; import { OrbitalParametersGui } from "./orbit"; import type { FindBestTransferMessage, ProgressMessage } from "./worker"; export class TargetOrbitGui { currentTime: ChangingStorageValue; body: ChangingStorageValue; startingOrbitalParameters: ChangingStorageValue; targetOrbitalParameters: ChangingStorageValue; parentDiv: HTMLDivElement; orbitGui: OrbitalParametersGui; manoeuvresGui: ManoeuvresGui; worker: Worker | null; constructor(currentTime: ChangingStorageValue, body: ChangingStorageValue, startingOrbitalParameters: ChangingStorageValue, targetOrbitalParameters: ChangingStorageValue) { this.worker = null; this.currentTime = currentTime; this.body = body; this.startingOrbitalParameters = startingOrbitalParameters; this.targetOrbitalParameters = targetOrbitalParameters; this.orbitGui = new OrbitalParametersGui(this.targetOrbitalParameters, "orbit"); this.manoeuvresGui = new ManoeuvresGui(true); this.parentDiv = document.createElement("div"); let targetOrbitHeader = document.createElement("h3"); targetOrbitHeader.appendChild(document.createTextNode("Target orbit:")); this.parentDiv.appendChild(targetOrbitHeader); this.parentDiv.appendChild(this.orbitGui.parentDiv); let searchButton = document.createElement("button"); searchButton.appendChild(document.createTextNode("Search for cheapest transfer")); this.parentDiv.appendChild(searchButton); let foundTransferHeader = document.createElement("h3"); foundTransferHeader.appendChild(document.createTextNode("Found transfer:")); this.parentDiv.appendChild(foundTransferHeader); this.parentDiv.appendChild(this.manoeuvresGui.parentDiv); searchButton.addEventListener("click", () => { if (this.worker !== null) { this.worker.terminate(); this.worker = null; searchButton.innerHTML = "Search for cheapest transfer"; } else { searchButton.innerHTML = "Cancel search"; let currentTime = this.currentTime.getCurrentValue(); let startingOrbitalParameters = this.startingOrbitalParameters.getCurrentValue(); let targetOrbitalParameters = this.targetOrbitalParameters.getCurrentValue(); let body = this.body.getCurrentValue(); let startingCoordinates: OrbitalCoordinates | null = getCoordinatesFromParameters(startingOrbitalParameters, body); let targetOrbit = getOrbitFromParameters(targetOrbitalParameters, body.radius); let startingTime = Math.max(currentTime, startingOrbitalParameters.currentTimeAtReading); if (startingTime > startingOrbitalParameters.currentTimeAtReading) { let addedTime = startingTime - startingOrbitalParameters.currentTimeAtReading; startingCoordinates = extrapolateTrajectory(addedTime, startingCoordinates, body); } if (startingCoordinates) { this.worker = new Worker(new URL('./worker.ts', import.meta.url), {type: 'module'}); this.worker.addEventListener("message", event => { let transferResponse = event.data as ProgressMessage; if (transferResponse) { if (transferResponse.finished) { searchButton.innerHTML = "Search for cheapest transfer"; this.worker = null; } if (transferResponse.bestTransfer) { transferResponse.bestTransfer.firstManoeuvre.time += currentTime; transferResponse.bestTransfer.secondManoeuvre.time += currentTime; } this.manoeuvresGui.displayProgress(transferResponse); } }); let workerMessage: FindBestTransferMessage = { type: "FindBestTransfer", startingSituation: startingCoordinates, targetOrbit: targetOrbit, body: body }; this.worker.postMessage(workerMessage); } else { let progressMessage: ProgressMessage = { type: "ProgressMessage", percentDone: 100, finished: true, bestDeltaV: null, bestTransfer: null }; this.manoeuvresGui.displayProgress(progressMessage); } } }); } }