162 lines
5.1 KiB
TypeScript
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,
|
|
};
|
|
}
|