mirror of
https://github.com/Krafpy/KSP-MGA-Planner.git
synced 2025-12-05 20:40:13 -08:00
Option to show dates as elapsed time
Added a checkbox which changes the display of dates (UT, not MET) from Year/Day starting at 1 but elapsed Years/elapsed Days starting at 0 (T+). This has no effect on the solar system that use real time (like RSS).
This commit is contained in:
36
dist/main/editor/editor.js
vendored
36
dist/main/editor/editor.js
vendored
@@ -42,7 +42,9 @@ export async function initEditorWithSystem(systems, systemIndex) {
|
||||
renderer.render(scene, camera);
|
||||
};
|
||||
requestAnimationFrame(loop);
|
||||
const systemTime = new TimeSelector("system", config);
|
||||
const datesAsElapsedCheckbox = document.getElementById("date-as-elapsed-checkbox");
|
||||
const initialDateDisplayMode = datesAsElapsedCheckbox.checked ? "elapsed" : "offset";
|
||||
const systemTime = new TimeSelector("system", config, initialDateDisplayMode);
|
||||
const updateSystemTime = () => {
|
||||
if (systemTime.validate()) {
|
||||
system.date = systemTime.dateSeconds;
|
||||
@@ -132,10 +134,22 @@ export async function initEditorWithSystem(systems, systemIndex) {
|
||||
seqStopBtn.click(() => generator.cancel());
|
||||
}
|
||||
{
|
||||
const timeRangeStart = new TimeSelector("start", config);
|
||||
const timeRangeEnd = new TimeSelector("end", config);
|
||||
const timeRangeStart = new TimeSelector("start", config, initialDateDisplayMode);
|
||||
const timeRangeEnd = new TimeSelector("end", config, initialDateDisplayMode);
|
||||
timeRangeStart.setToDefault();
|
||||
timeRangeEnd.setToDefault();
|
||||
const updateTimeSelectorsUTMode = (mode) => {
|
||||
systemTime.time.utDisplayMode = mode;
|
||||
systemTime.update();
|
||||
timeRangeStart.time.utDisplayMode = mode;
|
||||
timeRangeStart.update();
|
||||
timeRangeEnd.time.utDisplayMode = mode;
|
||||
timeRangeEnd.update();
|
||||
};
|
||||
datesAsElapsedCheckbox.onchange = () => {
|
||||
const mode = datesAsElapsedCheckbox.checked ? "elapsed" : "offset";
|
||||
updateTimeSelectorsUTMode(mode);
|
||||
};
|
||||
const depAltitude = new IntegerInput("start-altitude");
|
||||
const destAltitude = new IntegerInput("end-altitude");
|
||||
const updateAltitudeRange = (input, body) => {
|
||||
@@ -206,7 +220,15 @@ export async function initEditorWithSystem(systems, systemIndex) {
|
||||
const displayFoundTrajectory = (sequence) => {
|
||||
trajectory = new Trajectory(solver, system, config);
|
||||
trajectory.draw(canvas);
|
||||
trajectory.fillResultControls(resultItems, systemTime, controls);
|
||||
const { depDate, arrDate } = trajectory.fillResultControls(resultItems, systemTime, controls);
|
||||
datesAsElapsedCheckbox.onchange = () => {
|
||||
const mode = datesAsElapsedCheckbox.checked ? "elapsed" : "offset";
|
||||
updateTimeSelectorsUTMode(mode);
|
||||
depDate.utDisplayMode = mode;
|
||||
arrDate.utDisplayMode = mode;
|
||||
resultItems.depDateSpan.innerHTML = depDate.stringYDHMS("hms", "ut");
|
||||
resultItems.arrDateSpan.innerHTML = arrDate.stringYDHMS("hms", "ut");
|
||||
};
|
||||
systemTime.input(() => {
|
||||
updateSystemTime();
|
||||
trajectory.updatePodPosition(systemTime);
|
||||
@@ -216,14 +238,15 @@ export async function initEditorWithSystem(systems, systemIndex) {
|
||||
stepSlider.enable();
|
||||
trajectory.updatePodPosition(systemTime);
|
||||
console.log(solver.bestDeltaV);
|
||||
const trajText = trajectoryToText(trajectory, sequence);
|
||||
const currentDateDisplayMode = datesAsElapsedCheckbox.checked ? "elapsed" : "offset";
|
||||
const trajText = trajectoryToText(trajectory, sequence, currentDateDisplayMode);
|
||||
console.log(trajText);
|
||||
trajectoryCounter++;
|
||||
showTrajDetailsBtn.click(() => {
|
||||
DraggableTextbox.create(`Trajectory ${trajectoryCounter}`, trajText);
|
||||
});
|
||||
showTrajDetailsBtn.enable();
|
||||
const trajCSV = trajectoryToCSVData(trajectory);
|
||||
const trajCSV = trajectoryToCSVData(trajectory, currentDateDisplayMode);
|
||||
downloadTrajDataBtn.click(() => {
|
||||
let element = document.createElement('a');
|
||||
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(trajCSV));
|
||||
@@ -334,6 +357,7 @@ export async function initEditorWithSystem(systems, systemIndex) {
|
||||
scene.remove();
|
||||
renderer.dispose();
|
||||
controls.dispose();
|
||||
datesAsElapsedCheckbox.onchange = null;
|
||||
initEditorWithSystem(systems, index);
|
||||
});
|
||||
}
|
||||
|
||||
4
dist/main/editor/time-selector.js
vendored
4
dist/main/editor/time-selector.js
vendored
@@ -1,13 +1,13 @@
|
||||
import { KSPTime } from "../time/time.js";
|
||||
export class TimeSelector {
|
||||
constructor(namePrefix, config) {
|
||||
constructor(namePrefix, config, dateMode) {
|
||||
this.config = config;
|
||||
this.yearInput = document.getElementById(`${namePrefix}-year`);
|
||||
this.dayInput = document.getElementById(`${namePrefix}-day`);
|
||||
this.hourInput = document.getElementById(`${namePrefix}-hour`);
|
||||
this.selector = document.getElementById(`${namePrefix}-time`);
|
||||
this.selector.oninput = () => this.validate();
|
||||
this.time = KSPTime(0, this.config.time);
|
||||
this.time = KSPTime(0, this.config.time, dateMode);
|
||||
this.validate();
|
||||
}
|
||||
get dateSeconds() {
|
||||
|
||||
11
dist/main/solvers/trajectory.js
vendored
11
dist/main/solvers/trajectory.js
vendored
@@ -186,8 +186,8 @@ export class Trajectory {
|
||||
}
|
||||
}
|
||||
fillResultControls(resultItems, systemTime, controls) {
|
||||
const depDate = KSPTime(this.steps[0].dateOfStart, this.config.time);
|
||||
const arrDate = KSPTime(this.steps[this.steps.length - 1].dateOfStart, this.config.time);
|
||||
const depDate = KSPTime(this.steps[0].dateOfStart, this.config.time, systemTime.time.utDisplayMode);
|
||||
const arrDate = KSPTime(this.steps[this.steps.length - 1].dateOfStart, this.config.time, systemTime.time.utDisplayMode);
|
||||
resultItems.totalDVSpan.innerHTML = this.totalDeltaV.toFixed(1);
|
||||
resultItems.depDateSpan.innerHTML = depDate.stringYDHMS("hms", "ut");
|
||||
resultItems.arrDateSpan.innerHTML = arrDate.stringYDHMS("hms", "ut");
|
||||
@@ -255,7 +255,7 @@ export class Trajectory {
|
||||
const option = selectorOptions[index];
|
||||
if (option.type == "maneuver") {
|
||||
const details = this.maneuvres[option.origin];
|
||||
const dateEMT = KSPTime(details.dateMET, this.config.time);
|
||||
const dateEMT = KSPTime(details.dateMET, this.config.time, systemTime.time.utDisplayMode);
|
||||
resultItems.dateSpan.innerHTML = dateEMT.stringYDHMS("hm", "emt");
|
||||
resultItems.progradeDVSpan.innerHTML = details.progradeDV.toFixed(1);
|
||||
resultItems.normalDVSpan.innerHTML = details.normalDV.toFixed(1);
|
||||
@@ -275,8 +275,8 @@ export class Trajectory {
|
||||
}
|
||||
else if (option.type == "flyby") {
|
||||
const details = this.flybys[option.origin];
|
||||
const startDateEMT = KSPTime(details.soiEnterDateMET, this.config.time);
|
||||
const endDateEMT = KSPTime(details.soiExitDateMET, this.config.time);
|
||||
const startDateEMT = KSPTime(details.soiEnterDateMET, this.config.time, systemTime.time.utDisplayMode);
|
||||
const endDateEMT = KSPTime(details.soiExitDateMET, this.config.time, systemTime.time.utDisplayMode);
|
||||
resultItems.startDateSpan.innerHTML = startDateEMT.stringYDHMS("hm", "emt");
|
||||
resultItems.endDateSpan.innerHTML = endDateEMT.stringYDHMS("hm", "emt");
|
||||
resultItems.periAltitudeSpan.innerHTML = details.periAltitude.toFixed(0);
|
||||
@@ -288,6 +288,7 @@ export class Trajectory {
|
||||
resultItems.maneuverDiv.hidden = true;
|
||||
}
|
||||
});
|
||||
return { depDate, arrDate };
|
||||
}
|
||||
_displayStepsUpTo(index) {
|
||||
for (let i = 0; i < this.steps.length; i++) {
|
||||
|
||||
37
dist/main/time/basetime.js
vendored
37
dist/main/time/basetime.js
vendored
@@ -1,13 +1,15 @@
|
||||
export class BaseKSPTime {
|
||||
constructor(date, config) {
|
||||
constructor(date, config, dateMode) {
|
||||
this.config = config;
|
||||
this._exactDate = 0;
|
||||
this.utDisplayMode = "offset";
|
||||
if (typeof date == "number") {
|
||||
this.dateSeconds = date;
|
||||
}
|
||||
else {
|
||||
this.displayYDHMS = date;
|
||||
}
|
||||
this.utDisplayMode = dateMode;
|
||||
}
|
||||
stringYDHMS(precision, display) {
|
||||
let { year, day, hour, minute, second } = this.displayYDHMS;
|
||||
@@ -21,17 +23,27 @@ export class BaseKSPTime {
|
||||
hmsStr += "h";
|
||||
}
|
||||
if (display == "ut") {
|
||||
return `Year ${year} - Day ${day} - ${hmsStr}`;
|
||||
if (this.utDisplayMode == "offset") {
|
||||
return `Year ${year} - Day ${day} - ${hmsStr}`;
|
||||
}
|
||||
else {
|
||||
return `T+ ${year}y - ${day}d - ${hmsStr}`;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return `T+ ${year - 1}y - ${day - 1}d - ${hmsStr}`;
|
||||
if (this.utDisplayMode == "offset") {
|
||||
return `T+ ${year - 1}y - ${day - 1}d - ${hmsStr}`;
|
||||
}
|
||||
else {
|
||||
return `T+ ${year}y - ${day}d - ${hmsStr}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
toUT(from) {
|
||||
if (typeof from == "number")
|
||||
return new BaseKSPTime(from + this._exactDate, this.config);
|
||||
return new BaseKSPTime(from + this._exactDate, this.config, this.utDisplayMode);
|
||||
else
|
||||
return new BaseKSPTime(from.dateSeconds + this._exactDate, this.config);
|
||||
return new BaseKSPTime(from.dateSeconds + this._exactDate, this.config, this.utDisplayMode);
|
||||
}
|
||||
get dateSeconds() {
|
||||
return this._exactDate;
|
||||
@@ -46,12 +58,21 @@ export class BaseKSPTime {
|
||||
const hour = Math.floor((t % this._secondsPerDay) / 3600);
|
||||
const minute = Math.floor((t % 3600) / 60);
|
||||
const second = (t % 60);
|
||||
return { year: years + 1, day: days + 1, hour, minute, second };
|
||||
if (this.utDisplayMode == "offset") {
|
||||
return { year: years + 1, day: days + 1, hour, minute, second };
|
||||
}
|
||||
else {
|
||||
return { year: years, day: days, hour, minute, second };
|
||||
}
|
||||
}
|
||||
set displayYDHMS(date) {
|
||||
let { year, day, hour, minute, second } = date;
|
||||
let t = this._secondsPerYear * (year - 1);
|
||||
t += this._secondsPerDay * (day - 1);
|
||||
if (this.utDisplayMode == "offset") {
|
||||
year -= 1;
|
||||
day -= 1;
|
||||
}
|
||||
let t = this._secondsPerYear * year;
|
||||
t += this._secondsPerDay * day;
|
||||
t += 3600 * hour;
|
||||
t += 60 * minute;
|
||||
t += second;
|
||||
|
||||
1
dist/main/time/realtime.js
vendored
1
dist/main/time/realtime.js
vendored
@@ -2,6 +2,7 @@ export class RealKSPTime {
|
||||
constructor(date, config) {
|
||||
this.config = config;
|
||||
this._exactDate = 0;
|
||||
this.utDisplayMode = "offset";
|
||||
if (typeof date == "number") {
|
||||
this.dateSeconds = date;
|
||||
}
|
||||
|
||||
4
dist/main/time/time.js
vendored
4
dist/main/time/time.js
vendored
@@ -1,11 +1,11 @@
|
||||
import { RealKSPTime } from "./realtime.js";
|
||||
import { BaseKSPTime } from "./basetime.js";
|
||||
export function KSPTime(date, config) {
|
||||
export function KSPTime(date, config, dateMode) {
|
||||
switch (config.type) {
|
||||
case "base":
|
||||
if (config.daysPerYear === undefined || config.hoursPerDay === undefined)
|
||||
throw new Error("Missing daysPerYear or hoursPerDay in time config");
|
||||
return new BaseKSPTime(date, config);
|
||||
return new BaseKSPTime(date, config, dateMode);
|
||||
case "real":
|
||||
return new RealKSPTime(date, config);
|
||||
}
|
||||
|
||||
24
dist/main/utilities/trajectory-text.js
vendored
24
dist/main/utilities/trajectory-text.js
vendored
@@ -1,6 +1,6 @@
|
||||
import { KSPTime } from "../time/time.js";
|
||||
import { joinStrings } from "./array.js";
|
||||
export function trajectoryToText(traj, seq) {
|
||||
export function trajectoryToText(traj, seq, dateMode) {
|
||||
const { steps, system, config } = traj;
|
||||
const pairs = [];
|
||||
const add = (label, data, indent) => {
|
||||
@@ -8,10 +8,10 @@ export function trajectoryToText(traj, seq) {
|
||||
};
|
||||
const space = () => add("", "", 0);
|
||||
add("Sequence", seq.seqStringFullNames, 0);
|
||||
const depDate = KSPTime(steps[0].dateOfStart, config.time);
|
||||
const arrDate = KSPTime(steps[steps.length - 1].dateOfStart, config.time);
|
||||
add("Departure", depDate.stringYDHMS("hms", "ut"), 0);
|
||||
add("Arrival", arrDate.stringYDHMS("hms", "ut"), 0);
|
||||
const depDate = KSPTime(steps[0].dateOfStart, config.time, dateMode);
|
||||
const arrDate = KSPTime(steps[steps.length - 1].dateOfStart, config.time, dateMode);
|
||||
add("Departure", depDate.stringYDHMS("hms", "ut") + " UT", 0);
|
||||
add("Arrival", arrDate.stringYDHMS("hms", "ut") + " UT", 0);
|
||||
add("Total ΔV", `${traj.totalDeltaV.toFixed(1)} m/s`, 0);
|
||||
space();
|
||||
add("Steps", "", 0);
|
||||
@@ -39,7 +39,7 @@ export function trajectoryToText(traj, seq) {
|
||||
label = `${arrivalBodyName} circularization`;
|
||||
}
|
||||
add(label, "", 1);
|
||||
const dateMET = KSPTime(details.dateMET, config.time);
|
||||
const dateMET = KSPTime(details.dateMET, config.time, dateMode);
|
||||
add("Date", dateMET.toUT(depDate).stringYDHMS("hms", "ut") + " UT", 2);
|
||||
add("", dateMET.stringYDHMS("hms", "emt") + " MET", 2);
|
||||
if (details.ejectAngle !== undefined) {
|
||||
@@ -55,8 +55,8 @@ export function trajectoryToText(traj, seq) {
|
||||
space();
|
||||
const details = traj.flybys[flybyIdx];
|
||||
const bodyName = system.bodyFromId(details.bodyId).name;
|
||||
const enterMET = KSPTime(details.soiEnterDateMET, config.time);
|
||||
const exitMET = KSPTime(details.soiExitDateMET, config.time);
|
||||
const enterMET = KSPTime(details.soiEnterDateMET, config.time, dateMode);
|
||||
const exitMET = KSPTime(details.soiExitDateMET, config.time, dateMode);
|
||||
add(`Flyby around ${bodyName}`, "", 1);
|
||||
add("SOI enter date", enterMET.toUT(depDate).stringYDHMS("hms", "ut") + " UT", 2);
|
||||
add("", enterMET.stringYDHMS("hms", "emt") + " MET", 2);
|
||||
@@ -91,7 +91,7 @@ function pairsToString(pairs) {
|
||||
}
|
||||
return joinStrings(lines, "\n");
|
||||
}
|
||||
export function trajectoryToCSVData(traj) {
|
||||
export function trajectoryToCSVData(traj, dateMode) {
|
||||
const { config, steps, orbits } = traj;
|
||||
const n = steps.length;
|
||||
const entries = [];
|
||||
@@ -105,7 +105,7 @@ export function trajectoryToCSVData(traj) {
|
||||
entries.push({
|
||||
type: "dsm",
|
||||
bodyId: step.attractorId,
|
||||
timeUT: KSPTime(dateOfStart, config.time).dateSeconds,
|
||||
timeUT: KSPTime(dateOfStart, config.time, dateMode).dateSeconds,
|
||||
pos: startState.pos,
|
||||
vel: startState.vel
|
||||
});
|
||||
@@ -115,7 +115,7 @@ export function trajectoryToCSVData(traj) {
|
||||
entries.push({
|
||||
type: "flyby",
|
||||
bodyId: steps[i - 1].attractorId,
|
||||
timeUT: KSPTime(dateOfStart, config.time).dateSeconds,
|
||||
timeUT: KSPTime(dateOfStart, config.time, dateMode).dateSeconds,
|
||||
pos: startState.pos,
|
||||
vel: startState.vel
|
||||
});
|
||||
@@ -127,7 +127,7 @@ export function trajectoryToCSVData(traj) {
|
||||
entries.push({
|
||||
type: "arrival",
|
||||
bodyId: steps[n - 1].attractorId,
|
||||
timeUT: KSPTime(arrivalDate, config.time).dateSeconds,
|
||||
timeUT: KSPTime(arrivalDate, config.time, dateMode).dateSeconds,
|
||||
pos: arrivalState.pos,
|
||||
vel: arrivalState.vel
|
||||
});
|
||||
|
||||
@@ -240,6 +240,9 @@
|
||||
<div id="soi-toggle-box">
|
||||
<input type="checkbox" id="soi-checkbox" name="soi-checkbox">
|
||||
<label for="soi-checkbox">Show SOIs</label>
|
||||
|
||||
<input type="checkbox" id="date-as-elapsed-checkbox" name="date-as-elapsed-checkbox">
|
||||
<label for="date-as-elapsed-checkbox">Show dates as elapsed time</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -57,8 +57,12 @@ export async function initEditorWithSystem(systems: SolarSystemData[], systemInd
|
||||
}
|
||||
requestAnimationFrame(loop);
|
||||
|
||||
// Date display mode toggle:
|
||||
const datesAsElapsedCheckbox = document.getElementById("date-as-elapsed-checkbox") as HTMLInputElement;
|
||||
const initialDateDisplayMode = datesAsElapsedCheckbox.checked ? "elapsed" : "offset";
|
||||
|
||||
// Setting up solar system time control
|
||||
const systemTime = new TimeSelector("system", config);
|
||||
const systemTime = new TimeSelector("system", config, initialDateDisplayMode);
|
||||
const updateSystemTime = () => {
|
||||
if(systemTime.validate()){
|
||||
system.date = systemTime.dateSeconds;
|
||||
@@ -175,11 +179,26 @@ export async function initEditorWithSystem(systems: SolarSystemData[], systemInd
|
||||
|
||||
{
|
||||
// Time inputs
|
||||
const timeRangeStart = new TimeSelector("start", config);
|
||||
const timeRangeEnd = new TimeSelector("end", config);
|
||||
const timeRangeStart = new TimeSelector("start", config, initialDateDisplayMode);
|
||||
const timeRangeEnd = new TimeSelector("end", config, initialDateDisplayMode);
|
||||
timeRangeStart.setToDefault();
|
||||
timeRangeEnd.setToDefault();
|
||||
|
||||
// configure time selectors format updates
|
||||
const updateTimeSelectorsUTMode = (mode: "elapsed" | "offset") => {
|
||||
systemTime.time.utDisplayMode = mode;
|
||||
systemTime.update();
|
||||
|
||||
timeRangeStart.time.utDisplayMode = mode;
|
||||
timeRangeStart.update()
|
||||
timeRangeEnd.time.utDisplayMode = mode;
|
||||
timeRangeEnd.update();
|
||||
}
|
||||
datesAsElapsedCheckbox.onchange = () => {
|
||||
const mode = datesAsElapsedCheckbox.checked ? "elapsed" : "offset";
|
||||
updateTimeSelectorsUTMode(mode);
|
||||
}
|
||||
|
||||
// Numerical inputs
|
||||
const depAltitude = new IntegerInput("start-altitude");
|
||||
const destAltitude = new IntegerInput("end-altitude");
|
||||
@@ -271,7 +290,17 @@ export async function initEditorWithSystem(systems: SolarSystemData[], systemInd
|
||||
const displayFoundTrajectory = (sequence: FlybySequence) => {
|
||||
trajectory = new Trajectory(solver, system, config);
|
||||
trajectory.draw(canvas);
|
||||
trajectory.fillResultControls(resultItems, systemTime, controls);
|
||||
const {depDate, arrDate} = trajectory.fillResultControls(resultItems, systemTime, controls);
|
||||
|
||||
// Change the displayed arrival and departure dates as well
|
||||
datesAsElapsedCheckbox.onchange = () => {
|
||||
const mode = datesAsElapsedCheckbox.checked ? "elapsed" : "offset";
|
||||
updateTimeSelectorsUTMode(mode);
|
||||
depDate.utDisplayMode = mode;
|
||||
arrDate.utDisplayMode = mode;
|
||||
resultItems.depDateSpan.innerHTML = depDate.stringYDHMS("hms", "ut");
|
||||
resultItems.arrDateSpan.innerHTML = arrDate.stringYDHMS("hms", "ut");
|
||||
}
|
||||
|
||||
systemTime.input(() => {
|
||||
updateSystemTime();
|
||||
@@ -284,8 +313,9 @@ export async function initEditorWithSystem(systems: SolarSystemData[], systemInd
|
||||
trajectory.updatePodPosition(systemTime);
|
||||
|
||||
console.log(solver.bestDeltaV);
|
||||
|
||||
const trajText = trajectoryToText(trajectory, sequence);
|
||||
|
||||
const currentDateDisplayMode = datesAsElapsedCheckbox.checked ? "elapsed" : "offset";
|
||||
const trajText = trajectoryToText(trajectory, sequence, currentDateDisplayMode);
|
||||
console.log(trajText);
|
||||
|
||||
trajectoryCounter++;
|
||||
@@ -294,7 +324,7 @@ export async function initEditorWithSystem(systems: SolarSystemData[], systemInd
|
||||
});
|
||||
showTrajDetailsBtn.enable();
|
||||
|
||||
const trajCSV = trajectoryToCSVData(trajectory);
|
||||
const trajCSV = trajectoryToCSVData(trajectory, currentDateDisplayMode);
|
||||
downloadTrajDataBtn.click(() => {
|
||||
let element = document.createElement('a');
|
||||
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(trajCSV));
|
||||
@@ -424,6 +454,8 @@ export async function initEditorWithSystem(systems: SolarSystemData[], systemInd
|
||||
scene.remove();
|
||||
renderer.dispose();
|
||||
controls.dispose();
|
||||
|
||||
datesAsElapsedCheckbox.onchange = null;
|
||||
|
||||
initEditorWithSystem(systems, index);
|
||||
});
|
||||
|
||||
@@ -9,7 +9,7 @@ export class TimeSelector {
|
||||
readonly hourInput!: HTMLInputElement;
|
||||
readonly selector!: HTMLDivElement;
|
||||
|
||||
constructor(namePrefix: string, public readonly config: Config) {
|
||||
constructor(namePrefix: string, public readonly config: Config, dateMode: "elapsed" | "offset") {
|
||||
this.yearInput = document.getElementById(`${namePrefix}-year`) as HTMLInputElement;
|
||||
this.dayInput = document.getElementById(`${namePrefix}-day`) as HTMLInputElement;
|
||||
this.hourInput = document.getElementById(`${namePrefix}-hour`) as HTMLInputElement;
|
||||
@@ -17,7 +17,7 @@ export class TimeSelector {
|
||||
this.selector = document.getElementById(`${namePrefix}-time`) as HTMLDivElement;
|
||||
|
||||
this.selector.oninput = () => this.validate();
|
||||
this.time = KSPTime(0, this.config.time);
|
||||
this.time = KSPTime(0, this.config.time, dateMode);
|
||||
this.validate();
|
||||
}
|
||||
|
||||
|
||||
@@ -273,8 +273,8 @@ export class Trajectory {
|
||||
* @param controls The camera controller
|
||||
*/
|
||||
public fillResultControls(resultItems: ResultPannelItems, systemTime: TimeSelector, controls: CameraController){
|
||||
const depDate = KSPTime(this.steps[0].dateOfStart, this.config.time);
|
||||
const arrDate = KSPTime(this.steps[this.steps.length-1].dateOfStart, this.config.time);
|
||||
const depDate = KSPTime(this.steps[0].dateOfStart, this.config.time, systemTime.time.utDisplayMode);
|
||||
const arrDate = KSPTime(this.steps[this.steps.length-1].dateOfStart, this.config.time, systemTime.time.utDisplayMode);
|
||||
|
||||
// total delta-V
|
||||
resultItems.totalDVSpan.innerHTML = this.totalDeltaV.toFixed(1);
|
||||
@@ -364,7 +364,7 @@ export class Trajectory {
|
||||
|
||||
if(option.type == "maneuver"){
|
||||
const details = this.maneuvres[option.origin];
|
||||
const dateEMT = KSPTime(details.dateMET, this.config.time);
|
||||
const dateEMT = KSPTime(details.dateMET, this.config.time, systemTime.time.utDisplayMode);
|
||||
|
||||
resultItems.dateSpan.innerHTML = dateEMT.stringYDHMS("hm", "emt");
|
||||
resultItems.progradeDVSpan.innerHTML = details.progradeDV.toFixed(1);
|
||||
@@ -387,8 +387,8 @@ export class Trajectory {
|
||||
|
||||
} else if(option.type == "flyby"){
|
||||
const details = this.flybys[option.origin];
|
||||
const startDateEMT = KSPTime(details.soiEnterDateMET, this.config.time);
|
||||
const endDateEMT = KSPTime(details.soiExitDateMET, this.config.time);
|
||||
const startDateEMT = KSPTime(details.soiEnterDateMET, this.config.time, systemTime.time.utDisplayMode);
|
||||
const endDateEMT = KSPTime(details.soiExitDateMET, this.config.time, systemTime.time.utDisplayMode);
|
||||
|
||||
resultItems.startDateSpan.innerHTML = startDateEMT.stringYDHMS("hm", "emt");
|
||||
resultItems.endDateSpan.innerHTML = endDateEMT.stringYDHMS("hm", "emt");
|
||||
@@ -407,6 +407,8 @@ export class Trajectory {
|
||||
/*for(const step of this.steps){
|
||||
console.log(step);
|
||||
}*/
|
||||
|
||||
return {depDate, arrDate};
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
export class BaseKSPTime implements IKSPTime {
|
||||
private _exactDate: number = 0;
|
||||
|
||||
constructor(date: number | DateYDHMS, public readonly config: BaseTimeSettings){
|
||||
public utDisplayMode: "elapsed" | "offset" = "offset";
|
||||
|
||||
constructor(date: number | DateYDHMS, public readonly config: BaseTimeSettings, dateMode: "elapsed" | "offset"){
|
||||
if(typeof date == "number") {
|
||||
this.dateSeconds = date;
|
||||
} else {
|
||||
this.displayYDHMS = date;
|
||||
}
|
||||
this.utDisplayMode = dateMode;
|
||||
}
|
||||
|
||||
public stringYDHMS(precision: "h" | "hm" | "hms", display: "emt" | "ut"): string {
|
||||
@@ -23,17 +26,25 @@ export class BaseKSPTime implements IKSPTime {
|
||||
}
|
||||
|
||||
if(display == "ut"){
|
||||
return `Year ${year} - Day ${day} - ${hmsStr}`;
|
||||
if(this.utDisplayMode == "offset"){
|
||||
return `Year ${year} - Day ${day} - ${hmsStr}`;
|
||||
} else {
|
||||
return `T+ ${year}y - ${day}d - ${hmsStr}`;
|
||||
}
|
||||
} else {
|
||||
return `T+ ${year-1}y - ${day-1}d - ${hmsStr}`;
|
||||
if(this.utDisplayMode == "offset"){
|
||||
return `T+ ${year-1}y - ${day-1}d - ${hmsStr}`;
|
||||
} else {
|
||||
return `T+ ${year}y - ${day}d - ${hmsStr}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public toUT(from: number | IKSPTime): IKSPTime {
|
||||
if(typeof from == "number")
|
||||
return new BaseKSPTime(from + this._exactDate, this.config);
|
||||
return new BaseKSPTime(from + this._exactDate, this.config, this.utDisplayMode);
|
||||
else
|
||||
return new BaseKSPTime(from.dateSeconds + this._exactDate, this.config);
|
||||
return new BaseKSPTime(from.dateSeconds + this._exactDate, this.config, this.utDisplayMode);
|
||||
}
|
||||
|
||||
public get dateSeconds(){
|
||||
@@ -51,14 +62,23 @@ export class BaseKSPTime implements IKSPTime {
|
||||
const hour = Math.floor((t % this._secondsPerDay) / 3600);
|
||||
const minute = Math.floor((t % 3600) / 60);
|
||||
const second = (t % 60);
|
||||
return {year:years+1, day:days+1, hour, minute, second};
|
||||
if(this.utDisplayMode == "offset"){
|
||||
return {year:years+1, day:days+1, hour, minute, second};
|
||||
} else {
|
||||
return {year:years, day:days, hour, minute, second};
|
||||
}
|
||||
}
|
||||
|
||||
public set displayYDHMS(date: DateYDHMS) {
|
||||
let {year, day, hour, minute, second} = date;
|
||||
|
||||
let t = this._secondsPerYear * (year-1);
|
||||
t += this._secondsPerDay * (day-1);
|
||||
if(this.utDisplayMode == "offset"){
|
||||
year -= 1;
|
||||
day -= 1;
|
||||
}
|
||||
|
||||
let t = this._secondsPerYear * year;
|
||||
t += this._secondsPerDay * day;
|
||||
t += 3600 * hour;
|
||||
t += 60 * minute;
|
||||
t += second;
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
export class RealKSPTime implements IKSPTime {
|
||||
private _exactDate: number = 0; // time elapsed since Jan 1st 1970 (positive or negative), in seconds
|
||||
|
||||
public readonly utDisplayMode = "offset";
|
||||
|
||||
constructor(date: number | DateYDHMS, public readonly config: RealTimeSettings){
|
||||
if(typeof date == "number") {
|
||||
this.dateSeconds = date;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { RealKSPTime } from "./realtime.js";
|
||||
import { BaseKSPTime } from "./basetime.js";
|
||||
|
||||
export function KSPTime(date: number | DateYDHMS, config: BaseTimeSettings | RealTimeSettings): IKSPTime {
|
||||
export function KSPTime(date: number | DateYDHMS, config: BaseTimeSettings | RealTimeSettings, dateMode: "elapsed" | "offset"): IKSPTime {
|
||||
switch(config.type) {
|
||||
case "base":
|
||||
if(config.daysPerYear === undefined || config.hoursPerDay === undefined)
|
||||
throw new Error("Missing daysPerYear or hoursPerDay in time config");
|
||||
return new BaseKSPTime(date, config);
|
||||
return new BaseKSPTime(date, config, dateMode);
|
||||
case "real":
|
||||
return new RealKSPTime(date, config);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { joinStrings } from "./array.js";
|
||||
|
||||
type pair = {label: string, data: string, indent: number};
|
||||
|
||||
export function trajectoryToText(traj: Trajectory, seq: FlybySequence) {
|
||||
export function trajectoryToText(traj: Trajectory, seq: FlybySequence, dateMode: "elapsed" | "offset") {
|
||||
const {steps, system, config} = traj;
|
||||
|
||||
const pairs: pair[] = [];
|
||||
@@ -17,10 +17,10 @@ export function trajectoryToText(traj: Trajectory, seq: FlybySequence) {
|
||||
|
||||
add("Sequence", seq.seqStringFullNames, 0);
|
||||
|
||||
const depDate = KSPTime(steps[0].dateOfStart, config.time);
|
||||
const arrDate = KSPTime(steps[steps.length-1].dateOfStart, config.time);
|
||||
add("Departure", depDate.stringYDHMS("hms", "ut"), 0);
|
||||
add("Arrival", arrDate.stringYDHMS("hms", "ut"), 0);
|
||||
const depDate = KSPTime(steps[0].dateOfStart, config.time, dateMode);
|
||||
const arrDate = KSPTime(steps[steps.length-1].dateOfStart, config.time, dateMode);
|
||||
add("Departure", depDate.stringYDHMS("hms", "ut") + " UT", 0);
|
||||
add("Arrival", arrDate.stringYDHMS("hms", "ut") + " UT", 0);
|
||||
add("Total ΔV", `${traj.totalDeltaV.toFixed(1)} m/s`, 0);
|
||||
space();
|
||||
add("Steps", "", 0);
|
||||
@@ -49,7 +49,7 @@ export function trajectoryToText(traj: Trajectory, seq: FlybySequence) {
|
||||
label = `${arrivalBodyName} circularization`;
|
||||
}
|
||||
add(label, "", 1);
|
||||
const dateMET = KSPTime(details.dateMET, config.time);
|
||||
const dateMET = KSPTime(details.dateMET, config.time, dateMode);
|
||||
add("Date", dateMET.toUT(depDate).stringYDHMS("hms", "ut") + " UT", 2);
|
||||
add("", dateMET.stringYDHMS("hms", "emt") + " MET", 2);
|
||||
if(details.ejectAngle !== undefined){
|
||||
@@ -66,8 +66,8 @@ export function trajectoryToText(traj: Trajectory, seq: FlybySequence) {
|
||||
space();
|
||||
const details = traj.flybys[flybyIdx];
|
||||
const bodyName = system.bodyFromId(details.bodyId).name;
|
||||
const enterMET = KSPTime(details.soiEnterDateMET, config.time);
|
||||
const exitMET = KSPTime(details.soiExitDateMET, config.time);
|
||||
const enterMET = KSPTime(details.soiEnterDateMET, config.time, dateMode);
|
||||
const exitMET = KSPTime(details.soiExitDateMET, config.time, dateMode);
|
||||
add(`Flyby around ${bodyName}`, "", 1);
|
||||
add("SOI enter date", enterMET.toUT(depDate).stringYDHMS("hms", "ut") + " UT", 2);
|
||||
add("", enterMET.stringYDHMS("hms", "emt") + " MET", 2);
|
||||
@@ -115,7 +115,7 @@ type CSVEntry = {
|
||||
vel: {x: number, y: number, z: number},
|
||||
};
|
||||
|
||||
export function trajectoryToCSVData(traj: Trajectory){
|
||||
export function trajectoryToCSVData(traj: Trajectory, dateMode: "elapsed" | "offset"){
|
||||
const {config, steps, orbits} = traj;
|
||||
const n = steps.length;
|
||||
const entries: CSVEntry[] = [];
|
||||
@@ -130,7 +130,7 @@ export function trajectoryToCSVData(traj: Trajectory){
|
||||
entries.push({
|
||||
type: "dsm",
|
||||
bodyId: step.attractorId,
|
||||
timeUT: KSPTime(dateOfStart, config.time).dateSeconds,
|
||||
timeUT: KSPTime(dateOfStart, config.time, dateMode).dateSeconds,
|
||||
pos: startState.pos,
|
||||
vel: startState.vel
|
||||
});
|
||||
@@ -139,7 +139,7 @@ export function trajectoryToCSVData(traj: Trajectory){
|
||||
entries.push({
|
||||
type: "flyby",
|
||||
bodyId: steps[i-1].attractorId,
|
||||
timeUT: KSPTime(dateOfStart, config.time).dateSeconds,
|
||||
timeUT: KSPTime(dateOfStart, config.time, dateMode).dateSeconds,
|
||||
pos: startState.pos,
|
||||
vel: startState.vel
|
||||
});
|
||||
@@ -153,7 +153,7 @@ export function trajectoryToCSVData(traj: Trajectory){
|
||||
entries.push({
|
||||
type: "arrival",
|
||||
bodyId: steps[n-1].attractorId,
|
||||
timeUT: KSPTime(arrivalDate, config.time).dateSeconds,
|
||||
timeUT: KSPTime(arrivalDate, config.time, dateMode).dateSeconds,
|
||||
pos: arrivalState.pos,
|
||||
vel: arrivalState.vel
|
||||
});
|
||||
|
||||
5
src/types.d.ts
vendored
5
src/types.d.ts
vendored
@@ -140,8 +140,9 @@ interface SequenceParameters {
|
||||
type DateYDHMS = {year: number, day: number, hour: number, minute: number, second: number};
|
||||
|
||||
interface IKSPTime {
|
||||
public dateSeconds: number;
|
||||
public displayYDHMS: DateYDH;
|
||||
public dateSeconds: number;
|
||||
public displayYDHMS: DateYDH;
|
||||
public utDisplayMode: "elapsed" | "offset";
|
||||
public readonly defaultDate: number;
|
||||
public stringYDHMS(precision: "h" | "hm" | "hms", display: "emt" | "ut"): string;
|
||||
public toUT(from: IKSPTime | number): IKSPTime;
|
||||
|
||||
Reference in New Issue
Block a user