components
This commit is contained in:
parent
c88469c1d4
commit
0f130c640c
6 changed files with 847 additions and 221 deletions
291
src/routes/ControlPanel.svelte
Normal file
291
src/routes/ControlPanel.svelte
Normal file
|
|
@ -0,0 +1,291 @@
|
|||
<script>
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
|
||||
let startPoint = 'Custom';
|
||||
let startHeight = 0;
|
||||
let startTime = '13:13';
|
||||
let startDate = new Date(2025, 2, 24);
|
||||
let ascentRate = 5;
|
||||
let burstAltitude = 30000;
|
||||
let flightProfile = 'Normal';
|
||||
let descentRate = 5;
|
||||
let forecastMode = 'Single';
|
||||
let inputLat = '56.3576';
|
||||
let inputLng = '39.8666';
|
||||
|
||||
function formatLaunchDateTime(date, time) {
|
||||
// Parse the date
|
||||
const d = new Date(date);
|
||||
const year = d.getUTCFullYear();
|
||||
const month = String(d.getUTCMonth() + 1).padStart(2, '0');
|
||||
const day = String(d.getUTCDate()).padStart(2, '0');
|
||||
|
||||
// Parse the time (add seconds if missing)
|
||||
const [hours, minutes, seconds = '00'] = time.split(':');
|
||||
const formattedTime = `${hours.padStart(2, '0')}:${minutes.padStart(2, '0')}:${seconds.padStart(2, '0')}`;
|
||||
|
||||
return new Date(`${year}-${month}-${day}T${formattedTime}Z`).toISOString();
|
||||
}
|
||||
const launch_datetime = formatLaunchDateTime(startDate, startTime);
|
||||
|
||||
const getForecast = async () => {
|
||||
// Create request object
|
||||
const request = {
|
||||
ascent_rate: parseFloat(ascentRate),
|
||||
burst_altitude: parseFloat(burstAltitude),
|
||||
dataset: new Date().toISOString(), // Current time as dataset timestamp
|
||||
descent_rate: parseFloat(descentRate),
|
||||
format: "json",
|
||||
launch_altitude: parseFloat(startHeight),
|
||||
launch_datetime,
|
||||
launch_latitude: parseFloat(inputLat),
|
||||
launch_longitude: parseFloat(inputLng),
|
||||
profile: flightProfile === 'Normal' ? 'standard_profile' : 'custom_profile',
|
||||
version: 2
|
||||
};
|
||||
|
||||
console.log("Sending request:", request);
|
||||
|
||||
try {
|
||||
// Example POST request - replace with your actual API endpoint
|
||||
const response = await fetch('http://127.0.0.1:8000/api/predictions', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(request)
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
console.log("Forecast response:", data);
|
||||
alert("Forecast request successful!");
|
||||
// Handle the response data as needed
|
||||
} catch (error) {
|
||||
console.error("Error sending forecast request:", error);
|
||||
alert("Error getting forecast: " + error.message);
|
||||
}
|
||||
};
|
||||
|
||||
// Helper function to format date as YYYY-MM-DD
|
||||
const formatDateForAPI = (date) => {
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
return `${year}-${month}-${day}`;
|
||||
};
|
||||
|
||||
function handleUpdatePosition() {
|
||||
dispatch('updatePosition', {
|
||||
lat: inputLat,
|
||||
lng: inputLng
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="control-panel">
|
||||
<div class="control-header">Launch Point</div>
|
||||
|
||||
<div class="control-row">
|
||||
<span>Start Point:</span>
|
||||
<select bind:value={startPoint}>
|
||||
<option>Custom</option>
|
||||
<option>Preset 1</option>
|
||||
<option>Preset 2</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="control-row">
|
||||
<span>Latitude/Longitude:</span>
|
||||
<div class="coordinate-inputs">
|
||||
<input type="text" bind:value={inputLat} placeholder="Latitude">
|
||||
<p>/</p>
|
||||
<input type="text" bind:value={inputLng} placeholder="Longitude">
|
||||
<button on:click={handleUpdatePosition} class="update-button">✓</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-row">
|
||||
<button class="map-button" on:click={() => {
|
||||
inputLat = mouseLat;
|
||||
inputLng = mouseLng;
|
||||
updateMapPosition();
|
||||
}}>Specify on map (click location)</button>
|
||||
</div>
|
||||
|
||||
<div class="control-row">
|
||||
<span>Launch Height (m):</span>
|
||||
<input type="number" bind:value={startHeight}>
|
||||
</div>
|
||||
|
||||
<div class="control-row">
|
||||
<span>Launch Time (UTC):</span>
|
||||
<input type="time" bind:value={startTime}>
|
||||
</div>
|
||||
|
||||
<div class="control-row">
|
||||
<span>Launch Date:</span>
|
||||
<input type="date" bind:value={startDate}>
|
||||
</div>
|
||||
|
||||
<div class="control-row">
|
||||
<span>Ascent Rate (m/s):</span>
|
||||
<input type="number" bind:value={ascentRate}>
|
||||
</div>
|
||||
|
||||
<div class="control-row">
|
||||
<span>Burst/Drift Altitude (m):</span>
|
||||
<input type="number" bind:value={burstAltitude}>
|
||||
</div>
|
||||
|
||||
<div class="control-row">
|
||||
<span>Flight Profile:</span>
|
||||
<select bind:value={flightProfile}>
|
||||
<option>Normal</option>
|
||||
<option>Drift</option>
|
||||
<option>Reversible (on the rise)</option>
|
||||
<option>Custom</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="control-row buttons">
|
||||
<button on:click={toggleBurstCalculator}>Open Burst Calculator</button>
|
||||
<button>Set Custom Flight Profile</button>
|
||||
<button>Show Last Altitude Graph</button>
|
||||
</div>
|
||||
|
||||
<div class="control-row">
|
||||
<span>Descent Rate (m/s):</span>
|
||||
<input type="number" bind:value={descentRate}>
|
||||
</div>
|
||||
|
||||
<div class="control-row">
|
||||
<span>Forecast Mode (help):</span>
|
||||
<div class="radio-group">
|
||||
<label>
|
||||
<input type="radio" bind:group={forecastMode} value="Single"> Single
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" bind:group={forecastMode} value="Multiple"> Multiple
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-row">
|
||||
<button class="primary-button" on:click={getForecast}>Get Forecast</button>
|
||||
<button>Save Point</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.control-panel {
|
||||
position: absolute;
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
padding: 15px;
|
||||
border-radius: 5px;
|
||||
font-family: Arial, sans-serif;
|
||||
font-size: 14px;
|
||||
z-index: 1000;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
|
||||
width: 320px;
|
||||
max-height: 80vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.control-header {
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
font-size: 16px;
|
||||
border-bottom: 1px solid #ddd;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
.control-row {
|
||||
margin-bottom: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.control-row span {
|
||||
width: 160px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.control-row input[type="number"],
|
||||
.control-row input[type="date"],
|
||||
.control-row input[type="time"],
|
||||
.control-row select {
|
||||
width: 120px;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
.coordinate-inputs {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.coordinate-inputs input {
|
||||
width: 70px !important;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
.update-button {
|
||||
padding: 3px 8px;
|
||||
background: #4CAF50;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.map-button {
|
||||
width: 100%;
|
||||
padding: 5px;
|
||||
background: #f0f0f0;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.buttons {
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.buttons button {
|
||||
width: 100%;
|
||||
padding: 5px;
|
||||
margin-bottom: 5px;
|
||||
background: #f0f0f0;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.primary-button {
|
||||
background: #4CAF50 !important;
|
||||
color: white;
|
||||
border: 1px solid #3e8e41 !important;
|
||||
}
|
||||
|
||||
.radio-group {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.radio-group label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
}
|
||||
</style>
|
||||
Loading…
Add table
Add a link
Reference in a new issue