Continue messing with stores
This commit is contained in:
parent
c7df38e6ce
commit
52558ed3b2
7 changed files with 148 additions and 83 deletions
|
|
@ -3,8 +3,8 @@ import type { LatLngExpression } from "leaflet";
|
|||
import L from "leaflet";
|
||||
|
||||
import { getCsrfToken } from "./auth";
|
||||
import type { PredictionStage, Prediction, ParsedPrediction } from "./types";
|
||||
import { latestPrediction, latestPredictionParsed } from "./stores";
|
||||
import type { PredictionStage, RawPrediction, Prediction } from "./types";
|
||||
import { PredictionStore, RawPredictionStore, writeLocalStorage } from "./stores";
|
||||
|
||||
function getLatestDataset() {
|
||||
const now = new Date();
|
||||
|
|
@ -76,8 +76,10 @@ export const getForecast = async (
|
|||
const data = await response.json();
|
||||
console.log("Forecast response:", data);
|
||||
|
||||
latestPrediction.set(data.result);
|
||||
latestPredictionParsed.set(parsePrediction(data.result.prediction));
|
||||
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);
|
||||
|
||||
alert("Forecast request successful!");
|
||||
// Handle the response data as needed
|
||||
|
|
@ -87,7 +89,7 @@ export const getForecast = async (
|
|||
}
|
||||
};
|
||||
|
||||
export function parsePrediction(prediction: PredictionStage[]): ParsedPrediction {
|
||||
export function parsePrediction(prediction: PredictionStage[]): Prediction {
|
||||
const flight_path: [number, number, number][] = [];
|
||||
const launch: { latlng: LatLngExpression; datetime: Date } = {} as any;
|
||||
const burst: { latlng: LatLngExpression; datetime: Date } = {} as any;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,40 @@
|
|||
import { writable } from "svelte/store";
|
||||
import type { FlightParameters, Telemetry, ParsedTelemetry } from "./types";
|
||||
import type { Prediction, ParsedPrediction } from "./types";
|
||||
import type { FlightParameters, RawTelemetry, Telemetry } from "./types";
|
||||
import type { RawPrediction, Prediction } from "./types";
|
||||
|
||||
export const flightParametersStore = writable<FlightParameters>({
|
||||
export const readLocalStorage = <T>(key: string, defaultValue: T): T => {
|
||||
const item = localStorage.getItem(key);
|
||||
if (item) {
|
||||
try {
|
||||
const parsed = JSON.parse(item);
|
||||
if (typeof parsed === "object" && parsed !== null) {
|
||||
return parsed as T;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error parsing ${key} from localStorage:`, error);
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
};
|
||||
|
||||
export const writeLocalStorage = <T>(key: string, value: T): void => {
|
||||
try {
|
||||
localStorage.setItem(key, JSON.stringify(value));
|
||||
} catch (error) {
|
||||
console.error(`Error writing ${key} to localStorage:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
export const clearLocalStorage = (key: string): void => {
|
||||
try {
|
||||
localStorage.removeItem(key);
|
||||
}
|
||||
catch (error) {
|
||||
console.error(`Error clearing ${key} from localStorage:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
const flightParametersDefaults: FlightParameters = {
|
||||
ascent_rate: 5.0,
|
||||
burst_altitude: 30000.0,
|
||||
dataset: "",
|
||||
|
|
@ -14,10 +46,24 @@ export const flightParametersStore = writable<FlightParameters>({
|
|||
launch_longitude: 129.1234,
|
||||
profile: "standard_profile",
|
||||
version: 2,
|
||||
});
|
||||
};
|
||||
|
||||
export const latestTelemetry = writable({} as Telemetry);
|
||||
export const latestTelemetryParsed = writable({} as ParsedTelemetry);
|
||||
export const FlightParametersStore = writable<FlightParameters>(
|
||||
readLocalStorage<FlightParameters>("flightParameters", flightParametersDefaults)
|
||||
);
|
||||
|
||||
export const latestPrediction = writable({} as Prediction);
|
||||
export const latestPredictionParsed = writable({} as ParsedPrediction);
|
||||
export const RawTelemetryStore = writable<RawTelemetry>(
|
||||
readLocalStorage<RawTelemetry>("rawTelemetry", {} as RawTelemetry)
|
||||
);
|
||||
|
||||
export const TelemetryStore = writable<Telemetry>(
|
||||
readLocalStorage<Telemetry>("telemetry", {} as Telemetry)
|
||||
);
|
||||
|
||||
export const RawPredictionStore = writable<RawPrediction>(
|
||||
readLocalStorage<RawPrediction>("rawPrediction", {} as RawPrediction)
|
||||
);
|
||||
|
||||
export const PredictionStore = writable<Prediction>(
|
||||
readLocalStorage<Prediction>("prediction", {} as Prediction)
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { writable } from "svelte/store"
|
||||
import L from "leaflet";
|
||||
|
||||
import type { TelemetryPoint, ParsedTelemetry } from "./types";
|
||||
import type { TelemetryPoint, Telemetry } from "./types";
|
||||
|
||||
export function parseTelemetry(telemetry: TelemetryPoint[]): ParsedTelemetry {
|
||||
export function parseTelemetry(telemetry: TelemetryPoint[]): Telemetry {
|
||||
const flight_path: [number, number, number][] = telemetry.map((point) => [
|
||||
point.latitude,
|
||||
point.longitude,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { LatLngExpression } from "leaflet";
|
||||
import type { LatLngExpression, LatLngLiteral } from "leaflet";
|
||||
|
||||
export const PROFILE_MAP = {
|
||||
Normal: "standard_profile",
|
||||
|
|
@ -31,7 +31,17 @@ export interface TelemetryPoint {
|
|||
payload: string;
|
||||
}
|
||||
|
||||
export interface ParsedTelemetry {
|
||||
export interface TelemetryMetadata {
|
||||
complete_datetime: string;
|
||||
start_datetime: string;
|
||||
}
|
||||
|
||||
export interface RawTelemetry {
|
||||
metadata: TelemetryMetadata;
|
||||
telemetry: TelemetryPoint[];
|
||||
}
|
||||
|
||||
export interface Telemetry {
|
||||
flight_path: [number, number, number][];
|
||||
launch: {
|
||||
latlng: LatLngExpression;
|
||||
|
|
@ -40,15 +50,6 @@ export interface ParsedTelemetry {
|
|||
datapoints: TelemetryPoint[];
|
||||
}
|
||||
|
||||
export interface ParsedTelemetryMetadata {
|
||||
complete_datetime: string;
|
||||
start_datetime: string;
|
||||
}
|
||||
|
||||
export interface Telemetry {
|
||||
metadata: ParsedTelemetryMetadata;
|
||||
telemetry: TelemetryPoint[];
|
||||
}
|
||||
|
||||
export interface TrajectoryPoint {
|
||||
altitude: number;
|
||||
|
|
@ -62,7 +63,17 @@ export interface PredictionStage {
|
|||
trajectory: TrajectoryPoint[];
|
||||
}
|
||||
|
||||
export interface ParsedPrediction {
|
||||
export interface PredictionMetadata {
|
||||
complete_datetime: string;
|
||||
start_datetime: string;
|
||||
}
|
||||
|
||||
export interface RawPrediction {
|
||||
metadata: PredictionMetadata;
|
||||
prediction: PredictionStage[];
|
||||
}
|
||||
|
||||
export interface Prediction {
|
||||
flight_path: [number, number, number][];
|
||||
launch: {
|
||||
latlng: LatLngExpression;
|
||||
|
|
@ -80,12 +91,21 @@ export interface ParsedPrediction {
|
|||
flight_time: number;
|
||||
}
|
||||
|
||||
export interface ParsedPredictionMetadata {
|
||||
complete_datetime: string;
|
||||
start_datetime: string;
|
||||
export interface Point {
|
||||
latlng: LatLngLiteral & { alt: number };
|
||||
datetime: Date;
|
||||
}
|
||||
|
||||
export interface Prediction {
|
||||
metadata: ParsedPredictionMetadata;
|
||||
prediction: PredictionStage[];
|
||||
export interface PredictionData {
|
||||
launch: Point;
|
||||
landing: Point;
|
||||
burst: Point;
|
||||
flight_path: LatLngExpression[];
|
||||
flight_time: number;
|
||||
}
|
||||
|
||||
export interface TelemetryData {
|
||||
launch: Point;
|
||||
datapoints: TelemetryPoint[];
|
||||
flight_path: LatLngExpression[];
|
||||
}
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
import { getForecast } from "$lib/prediction";
|
||||
import type { FlightParameters, ProfileName } from "$lib/types";
|
||||
import { PROFILE_MAP } from "$lib/types";
|
||||
import { flightParametersStore } from '$lib/stores';
|
||||
import { FlightParametersStore, writeLocalStorage } from '$lib/stores';
|
||||
|
||||
let isCollapsed = false;
|
||||
let selectedProfile: ProfileName = "Normal";
|
||||
|
|
@ -24,19 +24,20 @@
|
|||
let startDate = now.toISOString().split("T")[0]; // YYYY-MM-DD
|
||||
let startTime = now.toISOString().split("T")[1].split(".")[0]; // HH:MM:SS
|
||||
|
||||
let inputLat = $flightParametersStore.launch_latitude.toString();
|
||||
let inputLng = $flightParametersStore.launch_longitude.toString();
|
||||
let inputLat = $FlightParametersStore.launch_latitude.toString();
|
||||
let inputLng = $FlightParametersStore.launch_longitude.toString();
|
||||
|
||||
$: $flightParametersStore.profile = PROFILE_MAP[selectedProfile];
|
||||
$: $FlightParametersStore.profile = PROFILE_MAP[selectedProfile];
|
||||
|
||||
const handleGetPrediction = async () => {
|
||||
console.log("Fetching prediction with parameters:", $flightParametersStore);
|
||||
console.log("Fetching prediction with parameters:", $FlightParametersStore);
|
||||
console.log(startDate, startTime);
|
||||
|
||||
$flightParametersStore.launch_datetime = `${startDate}T${startTime}Z`;
|
||||
$FlightParametersStore.launch_datetime = `${startDate}T${startTime}Z`;
|
||||
writeLocalStorage<FlightParameters>("flightParameters", $FlightParametersStore);
|
||||
|
||||
try {
|
||||
const response = await getForecast($flightParametersStore);
|
||||
const response = await getForecast($FlightParametersStore);
|
||||
console.log(response);
|
||||
// TODO: Notify other components of the new prediction.
|
||||
// const dispatch = createEventDispatcher();
|
||||
|
|
@ -52,9 +53,9 @@
|
|||
const lng = parseFloat(inputLng);
|
||||
|
||||
if (!isNaN(lat) && !isNaN(lng)) {
|
||||
$flightParametersStore.launch_latitude = lat;
|
||||
$flightParametersStore.launch_longitude = lng;
|
||||
console.log("Updated position:", $flightParametersStore.launch_latitude, $flightParametersStore.launch_longitude);
|
||||
$FlightParametersStore.launch_latitude = lat;
|
||||
$FlightParametersStore.launch_longitude = lng;
|
||||
console.log("Updated position:", $FlightParametersStore.launch_latitude, $FlightParametersStore.launch_longitude);
|
||||
} else {
|
||||
console.error("Invalid coordinate input");
|
||||
// TODO: Show a validation error to the user.
|
||||
|
|
@ -67,8 +68,8 @@
|
|||
* @param {number} lng The new longitude.
|
||||
*/
|
||||
export const updateLaunchPosition = (lat: number, lng: number) => {
|
||||
$flightParametersStore.launch_latitude = lat;
|
||||
$flightParametersStore.launch_longitude = lng;
|
||||
$FlightParametersStore.launch_latitude = lat;
|
||||
$FlightParametersStore.launch_longitude = lng;
|
||||
console.log("Launch position updated:", lat, lng);
|
||||
inputLat = lat.toString();
|
||||
inputLng = lng.toString();
|
||||
|
|
@ -214,7 +215,7 @@
|
|||
type="number"
|
||||
id="startHeight"
|
||||
class="form-control-sm"
|
||||
bind:value={$flightParametersStore.launch_altitude}
|
||||
bind:value={$FlightParametersStore.launch_altitude}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
|
|
@ -236,7 +237,7 @@
|
|||
type="number"
|
||||
id="ascentRate"
|
||||
class="form-control-sm"
|
||||
bind:value={$flightParametersStore.ascent_rate}
|
||||
bind:value={$FlightParametersStore.ascent_rate}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup class="flex-fill" spacing="mb-0">
|
||||
|
|
@ -245,7 +246,7 @@
|
|||
type="number"
|
||||
id="descentRate"
|
||||
class="form-control-sm"
|
||||
bind:value={$flightParametersStore.descent_rate}
|
||||
bind:value={$FlightParametersStore.descent_rate}
|
||||
/>
|
||||
</FormGroup>
|
||||
</div>
|
||||
|
|
@ -256,7 +257,7 @@
|
|||
type="number"
|
||||
id="burstAltitude"
|
||||
class="form-control-sm"
|
||||
bind:value={$flightParametersStore.burst_altitude}
|
||||
bind:value={$FlightParametersStore.burst_altitude}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -2,37 +2,12 @@
|
|||
import { onMount, createEventDispatcher } from "svelte";
|
||||
import * as L from "leaflet";
|
||||
import type { Map as LeafletMap, LayerGroup } from "leaflet";
|
||||
type LatLngExpression = [number, number] | { lat: number; lng: number };
|
||||
type LatLngLiteral = { lat: number; lng: number };
|
||||
import "leaflet/dist/leaflet.css";
|
||||
import VelocityLayer from "./velocity.svelte";
|
||||
import { distHaversine } from "../lib/mathutil.ts";
|
||||
import type { PredictionData, TelemetryData } from "../lib/types.ts";
|
||||
|
||||
interface Point {
|
||||
latlng: LatLngLiteral & { alt: number };
|
||||
datetime: Date;
|
||||
}
|
||||
|
||||
interface PredictionData {
|
||||
launch: Point;
|
||||
landing: Point;
|
||||
burst: Point;
|
||||
flight_path: LatLngExpression[];
|
||||
flight_time: number;
|
||||
}
|
||||
|
||||
interface TelemetryPoint {
|
||||
altitude: number;
|
||||
datetime: string;
|
||||
latitude: number;
|
||||
longitude: number;
|
||||
}
|
||||
|
||||
interface TelemetryData {
|
||||
launch: Point;
|
||||
datapoints: TelemetryPoint[];
|
||||
flight_path: LatLngExpression[];
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {'prediction' | 'telemetry'}
|
||||
|
|
@ -151,6 +126,22 @@
|
|||
|
||||
map?.fitBounds(L.latLngBounds(telemetry.flight_path));
|
||||
};
|
||||
|
||||
export const panTo = (lat: number, lng: number) => {
|
||||
if (map) {
|
||||
map.setView([lat, lng], map.getZoom());
|
||||
}
|
||||
};
|
||||
|
||||
export const zoomTo = (lat: number, lng: number, zoomLevel: number) => {
|
||||
if (map) {
|
||||
map.setView([lat, lng], zoomLevel);
|
||||
}
|
||||
};
|
||||
|
||||
export const getMap = () => {
|
||||
return map;
|
||||
};
|
||||
</script>
|
||||
|
||||
<div class="map-container" bind:this={mapContainer}>
|
||||
|
|
|
|||
|
|
@ -3,24 +3,29 @@
|
|||
import ControlPanel from '../ControlPanel.svelte';
|
||||
import Navbar from '../Navbar.svelte';
|
||||
import { onMount } from 'svelte';
|
||||
import { latestPredictionParsed } from '$lib/stores';
|
||||
import { PredictionStore } from '$lib/stores';
|
||||
import { Modal } from '@sveltestrap/sveltestrap';
|
||||
import L from 'leaflet';
|
||||
|
||||
let map: { plotData?: (prediction: any) => void } | null = null;
|
||||
|
||||
let map: Map | null = null;
|
||||
let panel: ControlPanel | null = null;
|
||||
|
||||
onMount(() => {
|
||||
latestPredictionParsed.subscribe((prediction) => {
|
||||
if (prediction && map) {
|
||||
map.plotData?.(prediction);
|
||||
PredictionStore.subscribe((data) => {
|
||||
if (data) {
|
||||
map?.clearMapLayers();
|
||||
}
|
||||
});
|
||||
|
||||
L.DomEvent.disableClickPropagation(panel?.$element);
|
||||
L.DomEvent.disableScrollPropagation(panel?.$element);
|
||||
});
|
||||
</script>
|
||||
|
||||
<main>
|
||||
<Navbar />
|
||||
<Map bind:this={map} mode="prediction">
|
||||
<ControlPanel
|
||||
/>
|
||||
<Map bind:this={map} mode="prediction" bind:data={$PredictionStore}>
|
||||
<ControlPanel bind:this={panel} />
|
||||
</Map>
|
||||
</main>
|
||||
Loading…
Add table
Add a link
Reference in a new issue