mirror of
https://github.com/acamarata/moon-sighting.git
synced 2026-06-30 19:04:24 +00:00
Merge ed221cfd40 into e8b0afd119
This commit is contained in:
commit
e80505ef8d
2 changed files with 41 additions and 10 deletions
|
|
@ -147,8 +147,8 @@ export class SpkKernel {
|
||||||
const svSunSsb = evaluateSegment(this.buffer, sSunSsb, et, this.le)
|
const svSunSsb = evaluateSegment(this.buffer, sSunSsb, et, this.le)
|
||||||
const svEmbSsb = evaluateSegment(this.buffer, sEmbSsb, et, this.le)
|
const svEmbSsb = evaluateSegment(this.buffer, sEmbSsb, et, this.le)
|
||||||
const svEarthEmb = evaluateSegment(this.buffer, sEarthEmb, et, this.le)
|
const svEarthEmb = evaluateSegment(this.buffer, sEarthEmb, et, this.le)
|
||||||
// Earth/SSB = EMB/SSB - Earth/EMB
|
// Earth/SSB = EMB/SSB + Earth/EMB because the kernel stores 399:3.
|
||||||
const earthSsb = subtractSV(svEmbSsb, svEarthEmb)
|
const earthSsb = addSV(svEmbSsb, svEarthEmb)
|
||||||
return subtractSV(svSunSsb, earthSsb)
|
return subtractSV(svSunSsb, earthSsb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -192,9 +192,11 @@ function parseDafFileRecord(buffer: ArrayBuffer): {
|
||||||
}
|
}
|
||||||
|
|
||||||
const ni = dv.getInt32(12, le)
|
const ni = dv.getInt32(12, le)
|
||||||
const fward = dv.getInt32(256, le)
|
// DAF file record layout stores the forward/backward/free record numbers
|
||||||
const bward = dv.getInt32(260, le)
|
// directly after the 60-byte internal file name, not at byte 256.
|
||||||
const free = dv.getInt32(264, le)
|
const fward = dv.getInt32(76, le)
|
||||||
|
const bward = dv.getInt32(80, le)
|
||||||
|
const free = dv.getInt32(84, le)
|
||||||
|
|
||||||
return { nd, ni, fward, bward, free, le }
|
return { nd, ni, fward, bward, free, le }
|
||||||
}
|
}
|
||||||
|
|
@ -279,9 +281,8 @@ export function evaluateType2(
|
||||||
const intlen = dv.getFloat64(endOffset - 3 * BYTES_PER_DOUBLE, le)
|
const intlen = dv.getFloat64(endOffset - 3 * BYTES_PER_DOUBLE, le)
|
||||||
const init = dv.getFloat64(endOffset - 4 * BYTES_PER_DOUBLE, le)
|
const init = dv.getFloat64(endOffset - 4 * BYTES_PER_DOUBLE, le)
|
||||||
|
|
||||||
// degree = (rsize - 2) / 3 (Type 2 stores 3 components)
|
// Type 2 record size is RSIZE = 3 * NCOEFF + 2.
|
||||||
const degree = Math.round((rsize - 2) / 3)
|
const nCoeffs = Math.round((rsize - 2) / 3)
|
||||||
const nCoeffs = degree + 1
|
|
||||||
|
|
||||||
let recIdx = Math.floor((et - init) / intlen)
|
let recIdx = Math.floor((et - init) / intlen)
|
||||||
recIdx = Math.max(0, Math.min(Math.round(N) - 1, recIdx))
|
recIdx = Math.max(0, Math.min(Math.round(N) - 1, recIdx))
|
||||||
|
|
@ -320,8 +321,8 @@ export function evaluateType3(
|
||||||
const intlen = dv.getFloat64(endOffset - 3 * BYTES_PER_DOUBLE, le)
|
const intlen = dv.getFloat64(endOffset - 3 * BYTES_PER_DOUBLE, le)
|
||||||
const init = dv.getFloat64(endOffset - 4 * BYTES_PER_DOUBLE, le)
|
const init = dv.getFloat64(endOffset - 4 * BYTES_PER_DOUBLE, le)
|
||||||
|
|
||||||
const degree = Math.round((rsize - 2) / 6)
|
// Type 3 record size is RSIZE = 6 * NCOEFF + 2.
|
||||||
const nCoeffs = degree + 1
|
const nCoeffs = Math.round((rsize - 2) / 6)
|
||||||
|
|
||||||
let recIdx = Math.floor((et - init) / intlen)
|
let recIdx = Math.floor((et - init) / intlen)
|
||||||
recIdx = Math.max(0, Math.min(Math.round(N) - 1, recIdx))
|
recIdx = Math.max(0, Math.min(Math.round(N) - 1, recIdx))
|
||||||
|
|
@ -374,6 +375,21 @@ function subtractSV(a: StateVector, b: StateVector): StateVector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addSV(a: StateVector, b: StateVector): StateVector {
|
||||||
|
return {
|
||||||
|
position: [
|
||||||
|
a.position[0] + b.position[0],
|
||||||
|
a.position[1] + b.position[1],
|
||||||
|
a.position[2] + b.position[2],
|
||||||
|
],
|
||||||
|
velocity: [
|
||||||
|
a.velocity[0] + b.velocity[0],
|
||||||
|
a.velocity[1] + b.velocity[1],
|
||||||
|
a.velocity[2] + b.velocity[2],
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ─── Leap-second kernel ───────────────────────────────────────────────────────
|
// ─── Leap-second kernel ───────────────────────────────────────────────────────
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
15
test.mjs
15
test.mjs
|
|
@ -415,3 +415,18 @@ describe('Input validation', () => {
|
||||||
assert.throws(() => getMoon(new Date(), 0, 200), /longitude/)
|
assert.throws(() => getMoon(new Date(), 0, 200), /longitude/)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('kernel-backed sighting pipeline', () => {
|
||||||
|
it('computes London sunset and moonset for 2025-03-29', async () => {
|
||||||
|
await initKernels()
|
||||||
|
|
||||||
|
const observer = { lat: 51.5, lon: -0.1, elevation: 0 }
|
||||||
|
const report = await getMoonSightingReport(new Date('2025-03-29T00:00:00Z'), observer)
|
||||||
|
|
||||||
|
assert.ok(report.sunsetUTC instanceof Date, `report.sunsetUTC=${report.sunsetUTC}`)
|
||||||
|
assert.ok(report.moonsetUTC instanceof Date, `report.moonsetUTC=${report.moonsetUTC}`)
|
||||||
|
assert.ok(report.bestTimeUTC instanceof Date, `report.bestTimeUTC=${report.bestTimeUTC}`)
|
||||||
|
assert.equal(report.yallop?.category, 'F')
|
||||||
|
assert.equal(report.odeh?.zone, 'D')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue