Files
borges/scripts/merge-sessions.mjs
2026-06-15 20:00:41 +10:00

59 lines
2.0 KiB
JavaScript

#!/usr/bin/env node
// One-time migration: merge consecutive same-story sessions that were split by
// the blur-flush bug (every tab-out ended the session prematurely).
// Sessions of the same story on the same date with a gap < GAP_MS are merged.
import { readFileSync, writeFileSync, copyFileSync } from 'fs'
const GAP_MS = 10 * 60 * 1000 // 10-minute gap = new session
const TELEMETRY = `${process.env.HOME}/Library/Application Support/Borges/.borges/telemetry.json`
const BACKUP = TELEMETRY + '.merge-bak'
const sessions = JSON.parse(readFileSync(TELEMETRY, 'utf-8'))
// Sort chronologically so we can walk them in order
const sorted = [...sessions].sort((a, b) => a.startedAt - b.startedAt)
const merged = []
let mergeCount = 0
for (const s of sorted) {
const prev = merged[merged.length - 1]
const sameStory = prev && prev.storyId === s.storyId
const sameDate = prev && prev.date === s.date
const gapMs = prev ? s.startedAt - prev.endedAt : Infinity
if (sameStory && sameDate && gapMs < GAP_MS) {
// Merge s into prev
const combinedActiveMs = prev.activeMs + s.activeMs
const typedWords = s.wordsEnd - prev.wordsStart
const wpm = combinedActiveMs > 0
? Math.round(Math.max(0, typedWords) / (combinedActiveMs / 60_000))
: 0
console.log(
`Merging ${s.id} into ${prev.id} (${prev.storyId}) ` +
`gap=${(gapMs / 60000).toFixed(1)}m words ${prev.wordsStart}${s.wordsEnd} wpm ${prev.wpm}${wpm}`
)
prev.endedAt = s.endedAt
prev.wordsEnd = s.wordsEnd
prev.activeMs = combinedActiveMs
prev.wpm = wpm
mergeCount++
} else {
merged.push({ ...s })
}
}
if (mergeCount === 0) {
console.log('No sessions to merge.')
process.exit(0)
}
copyFileSync(TELEMETRY, BACKUP)
console.log(`\nBacked up to ${BACKUP}`)
writeFileSync(TELEMETRY, JSON.stringify(merged, null, 2), 'utf-8')
console.log(`Done. Merged ${mergeCount} session(s) → ${merged.length} total (was ${sessions.length}).`)