// What is different between a study as it is now and an earlier version of it, in words a person can read. const FIELD_NAMES = { observation: 'Observe', interpretation: 'Interpret', application: 'Apply', generalNotes: 'Background', finalScript: 'Script', discussionQuestions: 'Questions', episodeNumber: 'Session number', episodeTitle: 'Session title', teachBack: 'Teach it back', attendees: 'Who came', groupNotes: 'Group notes', }; const same = (a, b) => JSON.stringify(a ?? '') === JSON.stringify(b ?? ''); const chunksOf = (project) => { const out = new Map(); (project?.chapters ?? []).forEach((chapter) => (chapter.chunks ?? []).forEach((chunk) => out.set(chunk.id, { chunk, ref: `${chapter.book} ${chapter.chapter}:${chunk.startVerse}–${chunk.endVerse}` }))); return out; }; // current vs older -> { titleChanged, changed: [{ ref, fields }], removedSince: [ref], addedSince: [ref], identical } // "removedSince" = chunks the older version has that the study doesn't now (restoring brings them back); // "addedSince" = chunks written since (restoring takes them away, though the copy you replace is kept). export function diffProjects(current, older) { const now = chunksOf(current); const then = chunksOf(older); const changed = []; const removedSince = []; const addedSince = []; for (const [id, { chunk, ref }] of then) { const mine = now.get(id); if (!mine) { removedSince.push(ref); continue; } const fields = Object.keys(FIELD_NAMES).filter((f) => !same(mine.chunk[f], chunk[f])).map((f) => FIELD_NAMES[f]); if (!same(mine.chunk.tags, chunk.tags)) fields.push('Tags'); if (!same(mine.chunk.crossReferences, chunk.crossReferences)) fields.push('Cross-references'); if (!same(mine.chunk.greekWords, chunk.greekWords)) fields.push('Words'); if (fields.length) changed.push({ ref, fields }); } for (const [id, { ref }] of now) if (!then.has(id)) addedSince.push(ref); const titleChanged = (current?.title ?? '') !== (older?.title ?? ''); const outlineChanged = !same(current?.outline, older?.outline); return { titleChanged, outlineChanged, changed, removedSince, addedSince, identical: !titleChanged && !outlineChanged && !changed.length && !removedSince.length && !addedSince.length }; } export function describeDiff(diff) { if (diff.identical) return ['This version is the same as what you have now.']; const lines = []; if (diff.titleChanged) lines.push('The title is different.'); for (const c of diff.changed) lines.push(`${c.ref}: ${c.fields.join(', ')} differ${c.fields.length === 1 ? 's' : ''}.`); if (diff.removedSince.length) lines.push(`Brings back ${diff.removedSince.length} chunk${diff.removedSince.length === 1 ? '' : 's'} deleted since: ${diff.removedSince.join('; ')}.`); if (diff.addedSince.length) lines.push(`Takes away ${diff.addedSince.length} chunk${diff.addedSince.length === 1 ? '' : 's'} added since: ${diff.addedSince.join('; ')}.`); if (diff.outlineChanged) lines.push('The whole-study outline is different.'); return lines; }