leaflet_svelte/src/lib/prediction.ts
ThePetrovich 4bb7d214e8 cleanup
2025-07-06 19:16:17 +08:00

162 lines
5.1 KiB
TypeScript

import { writable } from "svelte/store";
import type { LatLngExpression } from "leaflet";
import L from "leaflet";
import { getCsrfToken } from "./auth";
import type { PredictionStage, RawPrediction, Prediction, Point } from "./types";
import { PredictionStore, RawPredictionStore, writeLocalStorage } from "./stores";
function getLatestDataset() {
const now = new Date();
const hours = now.getUTCHours();
const minutes = now.getUTCMinutes();
const seconds = now.getUTCSeconds();
// Round down to the nearest 6-hour interval
const roundedHours = Math.floor(hours / 6) * 6;
const roundedDate = new Date(now);
roundedDate.setUTCHours(roundedHours, 0, 0, 0);
// Subtract 6 hours to account for the lag
roundedDate.setUTCHours(roundedDate.getUTCHours() - 6);
return roundedDate.toISOString();
}
function formatLaunchDateTime(dateObj: string | Date, timeStr: string): string {
// Ensure date is a Date object
const date = new Date(dateObj);
// Extract date components
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");
// Format time (ensure it has seconds)
let formattedTime = timeStr;
if (timeStr.split(":").length === 2) {
formattedTime += ":00"; // Add seconds if missing
}
// Combine into ISO string
const isoString = new Date(`${year}-${month}-${day}T${formattedTime}Z`).toISOString();
return isoString;
}
export const getForecast = async (
flightParameters: Record<string, any>,
launchDateTime: string
): Promise<void> => {
// Create request object
flightParameters.dataset = getLatestDataset();
flightParameters.launch_datetime = launchDateTime;
if (flightParameters.start_point === -1) {
// remove start_point if it is -1
delete flightParameters.start_point;
}
console.log("Sending request:", flightParameters);
try {
// Example POST request - replace with your actual API endpoint
const csrfToken = await getCsrfToken();
if (!csrfToken) {
throw new Error("CSRF token not found");
}
const response = await fetch("http://localhost:8000/api/predictions/", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRFToken": csrfToken,
},
body: JSON.stringify(flightParameters),
credentials: "include",
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
console.log("Forecast response:", data);
RawPredictionStore.set(data.result as RawPrediction);
PredictionStore.set(parsePrediction(data.result.prediction) as Prediction);
writeLocalStorage("rawPrediction", data.result as RawPrediction);
writeLocalStorage("prediction", parsePrediction(data.result.prediction) as Prediction);
// Handle the response data as needed
} catch (error) {
console.error("Error sending forecast request:", error);
return Promise.reject(new Error(`${error}`));
}
};
export function parsePrediction(prediction: PredictionStage[]): Prediction {
const flight_path: LatLngExpression[] = [];
const launch: Point = {} as any;
const burst: Point = {} as any;
const landing: Point = {} as any;
const ascent = prediction[0].trajectory;
const descent = prediction[1].trajectory;
// Add the ascent track to the flight path array.
ascent.forEach((item) => {
let lon = item.longitude;
if (lon > 180.0) {
lon -= 360.0;
}
flight_path.push([item.latitude, lon, item.altitude]);
});
// Add the descent track to the flight path array.
descent.forEach((item) => {
let lon = item.longitude;
if (lon > 180.0) {
lon -= 360.0;
}
flight_path.push([item.latitude, lon, item.altitude]);
});
// Populate the launch, burst, and landing points
const launchObj = ascent[0];
let lon = launchObj.longitude;
if (lon > 180.0) {
lon -= 360.0;
}
launch.latlng = L.latLng([launchObj.latitude, lon, launchObj.altitude]);
launch.datetime = new Date(launchObj.datetime);
const burstObj = descent[0];
lon = burstObj.longitude;
if (lon > 180.0) {
lon -= 360.0;
}
burst.latlng = L.latLng([burstObj.latitude, lon, burstObj.altitude]);
burst.datetime = new Date(burstObj.datetime);
const landingObj = descent[descent.length - 1];
lon = landingObj.longitude;
if (lon > 180.0) {
lon -= 360.0;
}
landing.latlng = L.latLng([landingObj.latitude, lon, landingObj.altitude]);
landing.datetime = new Date(landingObj.datetime);
const profile = prediction[1].stage === "descent" ? "standard_profile" : "float_profile";
const flight_time = (new Date(landing.datetime).getTime() - new Date(launch.datetime).getTime()) / 1000;
return {
flight_path,
launch,
burst,
landing,
profile,
flight_time,
};
}