diff --git a/public/css/responsive-sm.css b/public/css/responsive-sm.css index 2943c98db..1a1758887 100644 --- a/public/css/responsive-sm.css +++ b/public/css/responsive-sm.css @@ -88,6 +88,7 @@ width: 100%; } + #timeline-sensor-list, #multi-site-look-angles-sensor-list { display: grid; justify-content: space-evenly; diff --git a/src/plugins/select-sat-manager/sat-info-box.ts b/src/plugins/select-sat-manager/sat-info-box.ts index eee4648fc..606e66d36 100644 --- a/src/plugins/select-sat-manager/sat-info-box.ts +++ b/src/plugins/select-sat-manager/sat-info-box.ts @@ -450,7 +450,7 @@ export class SatInfoBox extends KeepTrackPlugin { const posZmax = pos.z + distance; (getEl('search')).value = ''; - for (let i = 0; i < catalogManagerInstance.numSats; i++) { + for (let i = 0; i < catalogManagerInstance.numSatellites; i++) { pos = catalogManagerInstance.getObject(i, GetSatType.POSITION_ONLY).position; if (pos.x < posXmax && pos.x > posXmin && pos.y < posYmax && pos.y > posYmin && pos.z < posZmax && pos.z > posZmin) { SCCs.push(catalogManagerInstance.getSat(i, GetSatType.EXTRA_ONLY).sccNum); @@ -1173,41 +1173,42 @@ export class SatInfoBox extends KeepTrackPlugin { } const similarVmag = []; - - keepTrackApi.getCatalogManager().objectCache.forEach((posObj) => { - if (!posObj.isSatellite()) { - return; - } // Only look at satellites - const posSat = posObj as DetailedSatellite; - - if (obj.type !== posSat.type) { + const catalogManager = keepTrackApi.getCatalogManager(); + const curSatType = obj.type; + const curSatId = obj.id; + const curSatCountry = obj.country; + const curSatName = obj.name.toLowerCase(); + + catalogManager.getSats().forEach((posSat) => { + if (!posSat.vmag) { return; - } // Only look at same type of curSat - if (obj.id === posSat.id) { + } + if (curSatCountry !== posSat.country) { + // Only look at same country return; - } // Don't look at the same curSat - if (obj.country !== posSat.country) { + } + if (curSatType !== posSat.type) { + // Only look at same type of curSat return; - } // Only look at same country - - if (posSat.vmag) { - similarVmag.push(posSat.vmag); - } else { + } + if (curSatId === posSat.id) { + // Don't look at the same curSat return; } + similarVmag.push(posSat.vmag); + // Only use the first word of the name - const name = obj.name.toLowerCase(); const posName = posSat.name.toLowerCase(); - if (name.length < 4 || posName.length < 4) { + if (curSatName.length < 4 || posName.length < 4) { return; } // Determine how many characters match - const matchingChars = name.split('').filter((char, index) => char === posName[index]); + const matchingChars = curSatName.split('').filter((char, index) => char === posName[index]); - if (matchingChars.length / name.length > 0.85) { + if (matchingChars.length / curSatName.length > 0.85) { similarVmag.push(posSat.vmag); similarVmag.push(posSat.vmag); similarVmag.push(posSat.vmag); diff --git a/src/plugins/timeline/timeline.ts b/src/plugins/timeline/timeline.ts index 0e8e1398f..5ddb560d1 100644 --- a/src/plugins/timeline/timeline.ts +++ b/src/plugins/timeline/timeline.ts @@ -4,12 +4,12 @@ import { getEl } from '@app/lib/get-el'; import { errorManagerInstance } from '@app/singletons/errorManager'; import viewTimelinePng from '@public/img/icons/view_timeline.png'; -import { sensors } from '@app/catalogs/sensors'; import { SatMath } from '@app/static/sat-math'; import { BaseObject, Degrees, DetailedSatellite, DetailedSensor, Hours, Kilometers, MILLISECONDS_PER_SECOND, SatelliteRecord, Seconds } from 'ootk'; import { KeepTrackPlugin } from '../KeepTrackPlugin'; import { SelectSatManager } from '../select-sat-manager/select-sat-manager'; import { SensorManager } from '../sensor/sensorManager'; +import { SoundNames } from '../sounds/SoundNames'; interface Pass { start: Date; @@ -38,8 +38,8 @@ export class Timeline extends KeepTrackPlugin { keepTrackApi.getSensorManager().sensorListPrc, keepTrackApi.getSensorManager().sensorListOther, ); - disabledSensors_: DetailedSensor[] = this.allSensorLists_.filter((s) => - !keepTrackApi.getSensorManager().sensorListMw.includes(s), + private enabledSensors_: DetailedSensor[] = this.allSensorLists_.filter((s) => + keepTrackApi.getSensorManager().sensorListMw.includes(s), ); private lengthOfLookAngles_ = 6 as Hours; private lengthOfBadPass_ = 120 as Seconds; @@ -83,13 +83,13 @@ export class Timeline extends KeepTrackPlugin { `; sideMenuSettingsHtml: string = keepTrackApi.html` -
+
Calculation Length (Hours)
+
+
+ + +
+
-
+
`; sideMenuSettingsOptions = { @@ -152,6 +160,12 @@ export class Timeline extends KeepTrackPlugin { this.updateTimeline(); }); + getEl('timeline-setting-interval').addEventListener('change', () => { + this.angleCalculationInterval_ = parseFloat((getEl('timeline-setting-interval')).value) as Seconds; + this.ctxStatic_.reset(); + this.updateTimeline(); + }); + getEl('timeline-setting-bad-length').addEventListener('change', () => { this.lengthOfBadPass_ = parseFloat((getEl('timeline-setting-bad-length')).value) as Seconds; this.ctxStatic_.reset(); @@ -176,6 +190,7 @@ export class Timeline extends KeepTrackPlugin { cbName: this.PLUGIN_NAME, cb: (sat: BaseObject) => { if (sat) { + this.ctxStatic_.reset(); this.updateTimeline(); this.canvas_.style.display = 'block'; } @@ -192,20 +207,63 @@ export class Timeline extends KeepTrackPlugin { return; } - const satellite = this.selectSatManager_.getSelectedSat() as DetailedSatellite; - const sensors_ = [sensors.BLEAFB, sensors.CODSFS, sensors.MITMIL, sensors.CAVSFS, sensors.CLRSFS, sensors.COBRADANE, sensors.RAFFYL, sensors.PITSB]; - const sensorPasses = this.calculatePasses_(satellite, sensors_); + this.calculateSensors_(); + const sensorPasses = this.calculatePasses_(); - this.drawTimeline(sensorPasses); + this.drawTimeline_(sensorPasses); } catch (e) { errorManagerInstance.info(e); } } - private calculatePasses_(satellite: DetailedSatellite, sensors: DetailedSensor[]): SensorPasses[] { + private calculateSensors_() { + const sensorListDom = getEl('timeline-sensor-list'); + + if (!sensorListDom) { + errorManagerInstance.warn('Could not find sensor list dom'); + + return; + } + + sensorListDom.innerHTML = ''; + + for (const sensor of this.allSensorLists_) { + if (!sensor.objName) { + continue; + } + + const sensorButton = document.createElement('button'); + + sensorButton.classList.add('btn', 'btn-ui', 'waves-effect', 'waves-light'); + if (!this.enabledSensors_.includes(sensor)) { + sensorButton.classList.add('btn-red'); + } + + sensorButton.innerText = sensor.uiName ?? sensor.shortName ?? sensor.objName; + sensorButton.addEventListener('click', () => { + if (sensorButton.classList.contains('btn-red')) { + sensorButton.classList.remove('btn-red'); + this.enabledSensors_.push(sensor); + keepTrackApi.getSoundManager().play(SoundNames.TOGGLE_ON); + } else { + sensorButton.classList.add('btn-red'); + this.enabledSensors_.splice(this.enabledSensors_.indexOf(sensor), 1); + keepTrackApi.getSoundManager().play(SoundNames.TOGGLE_OFF); + } + + this.ctxStatic_.reset(); + this.updateTimeline(); + }); + sensorListDom.appendChild(sensorButton); + sensorListDom.appendChild(document.createTextNode(' ')); + } + } + + private calculatePasses_(): SensorPasses[] { const sensorPasses: SensorPasses[] = []; + const satellite = this.selectSatManager_.getSelectedSat() as DetailedSatellite; - for (const sensor of sensors) { + for (const sensor of this.enabledSensors_) { const sensorPass: SensorPasses = { sensor, passes: [], @@ -286,7 +344,7 @@ export class Timeline extends KeepTrackPlugin { } - private drawTimeline(sensorPasses: SensorPasses[]): void { + private drawTimeline_(sensorPasses: SensorPasses[]): void { // Clone the canvas element to remove all event listeners const oldCanvas = this.canvas_; const newCanvas = oldCanvas.cloneNode(true) as HTMLCanvasElement; @@ -357,7 +415,7 @@ export class Timeline extends KeepTrackPlugin { // Draw sensor name this.ctx_.fillStyle = 'rgb(255, 255, 255)'; this.ctx_.font = '14px Consolas'; - this.ctx_.fillText(sensorPass.sensor.shortName, leftOffset - 30, y + 5); + this.ctx_.fillText(sensorPass.sensor.uiName, leftOffset - 150, y + 5); // Draw passes sensorPass.passes.forEach((pass) => { @@ -385,7 +443,7 @@ export class Timeline extends KeepTrackPlugin { const endTime = new Date(passEnd).toISOString().slice(11, 19); // Calculate width of box based on text - const text = `${sensorPass.sensor.shortName}: ${startTime} - ${endTime}`; + const text = `${sensorPass.sensor.uiName}: ${startTime} - ${endTime}`; this.ctx_.font = '14px Consolas'; diff --git a/src/singletons/catalog-manager.ts b/src/singletons/catalog-manager.ts index 65c585c42..a442b7776 100644 --- a/src/singletons/catalog-manager.ts +++ b/src/singletons/catalog-manager.ts @@ -88,7 +88,8 @@ export class CatalogManager { missileSats: number = 0; missileSet = []; - numSats: number = 0; + numSatellites: number = 0; + numObjects: number = 0; orbitDensity: number[][] = []; orbitDensityMax = 0; orbitalSats: number; @@ -110,7 +111,7 @@ export class CatalogManager { const highestMarkerNumber = this.sensorMarkerArray?.[this.sensorMarkerArray?.length - 1] || 0; - settingsManager.dotsOnScreen = Math.max(this.numSats - settingsManager.maxFieldOfViewMarkers, highestMarkerNumber); + settingsManager.dotsOnScreen = Math.max(this.numObjects - settingsManager.maxFieldOfViewMarkers, highestMarkerNumber); }; /** @@ -277,7 +278,8 @@ export class CatalogManager { } getSats(): DetailedSatellite[] { - return this.objectCache.filter((obj) => obj?.isSatellite()) as DetailedSatellite[]; + // sats are the first numSats objects in the objectCache + return this.objectCache.slice(0, this.numSatellites).filter((sat) => sat.isSatellite()) as DetailedSatellite[]; } getMissile(missileId: number): MissileObject | null { @@ -295,7 +297,7 @@ export class CatalogManager { } id2satnum(satIdArray: number[]) { - return satIdArray.map((id) => (( this.getObject(id))?.sccNum || -1).toString()).filter((satnum) => satnum !== '-1'); + return satIdArray.map((id) => ((this.getObject(id))?.sccNum || -1).toString()).filter((satnum) => satnum !== '-1'); } async init(satCruncherOveride?: any): Promise { @@ -608,7 +610,7 @@ export class CatalogManager { } } - for (let i = 0; i < this.numSats; i++) { + for (let i = 0; i < this.numObjects; i++) { // Static objects lack these values and including them increase the JS heap a lot if (!this.objectCache[i].isSatellite()) { continue; diff --git a/src/singletons/color-scheme-manager.ts b/src/singletons/color-scheme-manager.ts index 390d092b5..af60a2885 100644 --- a/src/singletons/color-scheme-manager.ts +++ b/src/singletons/color-scheme-manager.ts @@ -835,8 +835,8 @@ export class ColorSchemeManager { } // Generate some buffers - this.colorData = new Float32Array(catalogManagerInstance.numSats * 4); - this.pickableData = new Int8Array(catalogManagerInstance.numSats); + this.colorData = new Float32Array(catalogManagerInstance.numObjects * 4); + this.pickableData = new Int8Array(catalogManagerInstance.numObjects); this.calculateColorBuffers(true).then(() => { this.isReady = true; }); diff --git a/src/static/catalog-loader.ts b/src/static/catalog-loader.ts index 58eacb338..fae0b5fc8 100644 --- a/src/static/catalog-loader.ts +++ b/src/static/catalog-loader.ts @@ -256,7 +256,7 @@ export class CatalogLoader { const catalogManagerInstance = keepTrackApi.getCatalogManager(); - catalogManagerInstance.numSats = catalogManagerInstance.objectCache.length; + catalogManagerInstance.numObjects = catalogManagerInstance.objectCache.length; const satDataString = CatalogLoader.getSatDataString_(catalogManagerInstance.objectCache); @@ -341,6 +341,8 @@ export class CatalogLoader { tempObjData.push(analSat); } + catalogManagerInstance.numSatellites = tempObjData.length; + for (const missileObj of catalogManagerInstance.missileSet) { tempObjData.push(missileObj); }