| 127 | } |
| 128 | |
| 129 | add(s: AutoCalSample): boolean { |
| 130 | if (s.t - this.lastAcceptedAt < MIN_SAMPLE_INTERVAL_MS) return false; |
| 131 | if (s.elDeg < EL_BANDS[0] || s.elDeg >= EL_BANDS[EL_BANDS.length - 1]) return false; |
| 132 | this.prune(s.t); |
| 133 | // Bin-capped insert: evict the oldest sample in the same sky bin. |
| 134 | const key = this.binKey(s.azDeg, s.elDeg); |
| 135 | const inBin = this.samples.filter((x) => this.binKey(x.azDeg, x.elDeg) === key); |
| 136 | if (inBin.length >= PER_BIN) { |
| 137 | const oldest = inBin.reduce((a, b) => (a.t < b.t ? a : b)); |
| 138 | this.samples = this.samples.filter((x) => x !== oldest); |
| 139 | } |
| 140 | this.samples.push(s); |
| 141 | this.lastAcceptedAt = s.t; |
| 142 | this.dirty = true; |
| 143 | this.save(s.t); |
| 144 | return true; |
| 145 | } |
| 146 | |
| 147 | status(current: MountModel): AutoCalStatus { |
| 148 | return { |