feat(sat): set it up in Settings, work the pass in the tab
Two things belong in different places, and they were in one. Settings → Satellites now holds the setup: which satellites to follow — the same two-column shape as the awards, for the same reason, since a feed carries two hundred birds and an operator works six — and the orbital elements, their age, the fetch, and pasting your own. Following none still means every satellite with both elements and a frequency plan, so somebody who has not chosen yet is not handed an empty tab. The panel keeps only what a pass needs. A countdown to AOS, or to LOS once it is up, because that is the number that decides whether you sit down; a bar for where in the pass you are, since mid-pass the useful question is not the clock but whether you are past the peak; rise, peak and set with compass directions, because "rises SW" is a direction to look in and 213° is arithmetic. Distance, altitude and footprint. And approaching or receding, which is the sign of the whole Doppler correction and the only thing that explains why the frequencies are moving the way they are. The countdowns run in the browser from two timestamps. Predicting a pass steps the orbit across a day thirty seconds at a time, which is not something to do once a second for a clock the page can keep itself.
This commit is contained in:
@@ -4075,6 +4075,59 @@ export namespace main {
|
||||
return a;
|
||||
}
|
||||
}
|
||||
export class SatPassInfo {
|
||||
name: string;
|
||||
has_pass: boolean;
|
||||
in_pass: boolean;
|
||||
// Go type: time
|
||||
aos: any;
|
||||
// Go type: time
|
||||
los: any;
|
||||
aos_az: number;
|
||||
los_az: number;
|
||||
max_el: number;
|
||||
max_el_az: number;
|
||||
// Go type: time
|
||||
max_el_at: any;
|
||||
duration_s: number;
|
||||
|
||||
static createFrom(source: any = {}) {
|
||||
return new SatPassInfo(source);
|
||||
}
|
||||
|
||||
constructor(source: any = {}) {
|
||||
if ('string' === typeof source) source = JSON.parse(source);
|
||||
this.name = source["name"];
|
||||
this.has_pass = source["has_pass"];
|
||||
this.in_pass = source["in_pass"];
|
||||
this.aos = this.convertValues(source["aos"], null);
|
||||
this.los = this.convertValues(source["los"], null);
|
||||
this.aos_az = source["aos_az"];
|
||||
this.los_az = source["los_az"];
|
||||
this.max_el = source["max_el"];
|
||||
this.max_el_az = source["max_el_az"];
|
||||
this.max_el_at = this.convertValues(source["max_el_at"], null);
|
||||
this.duration_s = source["duration_s"];
|
||||
}
|
||||
|
||||
convertValues(a: any, classs: any, asMap: boolean = false): any {
|
||||
if (!a) {
|
||||
return a;
|
||||
}
|
||||
if (a.slice && a.map) {
|
||||
return (a as any[]).map(elem => this.convertValues(elem, classs));
|
||||
} else if ("object" === typeof a) {
|
||||
if (asMap) {
|
||||
for (const key of Object.keys(a)) {
|
||||
a[key] = new classs(a[key]);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
return new classs(a);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
}
|
||||
export class SatSettings {
|
||||
favorites: string[];
|
||||
min_el: number;
|
||||
@@ -4218,6 +4271,10 @@ export namespace main {
|
||||
visible: boolean;
|
||||
// Go type: time
|
||||
at: any;
|
||||
lat: number;
|
||||
lon: number;
|
||||
alt_km: number;
|
||||
footprint_km: number;
|
||||
|
||||
static createFrom(source: any = {}) {
|
||||
return new SatTuning(source);
|
||||
@@ -4240,6 +4297,10 @@ export namespace main {
|
||||
this.range_rate = source["range_rate"];
|
||||
this.visible = source["visible"];
|
||||
this.at = this.convertValues(source["at"], null);
|
||||
this.lat = source["lat"];
|
||||
this.lon = source["lon"];
|
||||
this.alt_km = source["alt_km"];
|
||||
this.footprint_km = source["footprint_km"];
|
||||
}
|
||||
|
||||
convertValues(a: any, classs: any, asMap: boolean = false): any {
|
||||
|
||||
Reference in New Issue
Block a user