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, launchDateTime: string ): Promise => { // 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, }; }