From b30af4c3ac27feb9f71d9f9efc4b8ca9e05a8c77 Mon Sep 17 00:00:00 2001 From: evlist Date: Fri, 10 Feb 2023 15:30:45 +0100 Subject: [PATCH] Applying the same update to trkpt --- src/db/rte.ts | 18 ++-- src/db/trkpt.test.ts | 197 +++++++++++++++++++++++++++++++++++++++++++ src/db/trkpt.ts | 32 +++++-- src/db/trkseg.ts | 58 ++++++------- 4 files changed, 263 insertions(+), 42 deletions(-) create mode 100644 src/db/trkpt.test.ts diff --git a/src/db/rte.ts b/src/db/rte.ts index 927d8b1..f148caf 100644 --- a/src/db/rte.ts +++ b/src/db/rte.ts @@ -86,13 +86,13 @@ export const getRteDocs: ({ rte.rtept.push(row.doc.doc); }); } - console.log({ - caller: 'getRteDocs', - id, - docs, - nbRteptIn: docs.rows[0].doc.doc.rtept?.length, - nbRteptTotal: rte?.rtept?.length, - }); + // console.log({ + // caller: 'getRteDocs', + // id, + // docs, + // nbRteptIn: docs.rows[0].doc.doc.rtept?.length, + // nbRteptTotal: rte?.rtept?.length, + // }); return { docs, rte }; }; @@ -100,6 +100,10 @@ export const getRte = async (params: any) => { const { id } = params; const { docs, rte } = await getRteDocs(params); if (docs.rows.length > 1) { + console.log({ + caller: 'getRte compactRteOrTrksegDebounced required', + id, + }); compactRteOrTrksegDebounced({ id, getDocs: getRteDocs }); } return rte; diff --git a/src/db/trkpt.test.ts b/src/db/trkpt.test.ts new file mode 100644 index 0000000..c863c33 --- /dev/null +++ b/src/db/trkpt.test.ts @@ -0,0 +1,197 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import shell from 'shelljs'; +import PouchDB from 'pouchdb'; +import { getTrkseg, getTrksegDocs, putTrkseg } from './trkseg'; + +import { putTrkpt } from './trkpt'; +import { get, getFamily, put } from './lib'; +import { emptyWpt } from './wpt'; + +const test = it; +const jest = vi; + +declare global { + var db: any; + var dbReady: boolean; +} + +const originalDb = globalThis.db; +const originalDateNow = globalThis.Date.now; + +describe('The trkpt module with a real db', () => { + beforeEach(async () => { + globalThis.db = new PouchDB('dyomedea', { + auto_compaction: false, + }); + globalThis.Date.now = () => 0; + // vi.mock('./rte', async () => { + // const originalModule = await vi.importActual('./rte'); + // return { + // ...originalModule, + // compactTrksegOrTrksegDebounced: () => { + // console.log('mocked compactTrksegOrTrksegDebounced'); + // }, + // }; + // }); + }); + afterEach(async () => { + try { + await db.destroy(); + } catch (err) { + // console.error(err); + await shell.exec('rm -rf $*$'); + } + globalThis.db = undefined; + globalThis.dbReady = false; + globalThis.Date.now = originalDateNow; + }); + it('can write a trkpt inside a trkseg', async () => { + const idTrkseg = 'gpx/4320836410265485/2trkseg/000034'; + const trkpt: Wpt = { + $: { lat: 2, lon: 2 }, + }; + const trkseg0: Trkseg = { + trkpt: [ + { + $: { lat: 0, lon: 0 }, + }, + { + $: { lat: 1, lon: 1 }, + }, + ], + }; + const trkseg1: Trkseg = { + trkpt: [ + { + $: { lat: 0, lon: 0 }, + }, + { + $: { lat: 2, lon: 2 }, + }, + ], + }; + + const trksegPut = await putTrkseg(idTrkseg, trkseg0); + expect(trksegPut).toEqual(idTrkseg); + const trksegPutTrksegpt = await putTrkpt({ + id: idTrkseg, + index: 1, + wpt: trkpt, + }); + const trksegGetTrksegpt = await getTrkseg({ id: idTrkseg }); + expect(trksegGetTrksegpt).toEqual(trkseg1); + }); + it('can write a trkpt outside a trkseg', async () => { + const idTrkseg = 'gpx/4320836410265485/2trkseg/000034'; + const idTrksegpt = 'gpx/4320836410265485/2trkseg/000034/000035'; + const trkpt3: Wpt = { + $: { lat: 3, lon: 3 }, + }; + const trkpt4: Wpt = { + $: { lat: 4, lon: 4 }, + }; + const trkseg0: Trkseg = { + trkpt: [ + { + $: { lat: 1, lon: 1 }, + }, + { + $: { lat: 2, lon: 2 }, + }, + ], + }; + const trkseg1: Trkseg = { + trkpt: [ + { + $: { lat: 1, lon: 1 }, + }, + { + $: { lat: 2, lon: 2 }, + }, + trkpt3, + ], + }; + const trkseg2: Trkseg = { + trkpt: [ + { + $: { lat: 1, lon: 1 }, + }, + { + $: { lat: 2, lon: 2 }, + }, + trkpt4, + ], + }; + + const trksegPut = await putTrkseg(idTrkseg, trkseg0); + expect(trksegPut).toEqual(idTrkseg); + expect(await getTrkseg({ id: idTrkseg })).toEqual(trkseg0); + await put(idTrksegpt, 'trkpt', () => trkpt3, emptyWpt); + const { trkseg, docs } = await getTrksegDocs({ id: idTrkseg }); + console.log({ + caller: 'test', + trkptIn: JSON.stringify(docs.rows[0].doc.doc.trkpt), + }); + expect(await getTrkseg({ id: idTrkseg })).toEqual(trkseg1); + await putTrkpt({ + id: idTrkseg, + index: 2, + wpt: trkpt4, + }); + expect((await getFamily(idTrkseg)).rows.length).toEqual(2); + expect(await getTrkseg({ id: idTrkseg })).toEqual(trkseg2); + expect((await get(idTrksegpt)).doc).toEqual(trkpt4); + }); + it('can write a trkpt outside a trkseg with a negative index', async () => { + const idTrkseg = 'gpx/4320836410265485/2trkseg/000034'; + const idTrksegpt = 'gpx/4320836410265485/2trkseg/000034/000035'; + const trkpt3: Wpt = { + $: { lat: 3, lon: 3 }, + }; + const trkpt4: Wpt = { + $: { lat: 4, lon: 4 }, + }; + const trkseg0: Trkseg = { + trkpt: [ + { + $: { lat: 1, lon: 1 }, + }, + { + $: { lat: 2, lon: 2 }, + }, + ], + }; + const trkseg1: Trkseg = { + trkpt: [ + { + $: { lat: 1, lon: 1 }, + }, + { + $: { lat: 2, lon: 2 }, + }, + trkpt3, + ], + }; + const trkseg2: Trkseg = { + trkpt: [ + { + $: { lat: 1, lon: 1 }, + }, + { + $: { lat: 2, lon: 2 }, + }, + trkpt4, + ], + }; + + const trksegPut = await putTrkseg(idTrkseg, trkseg0); + await put(idTrksegpt, 'trkpt', () => trkpt3, emptyWpt); + await putTrkpt({ + id: idTrkseg, + index: -1, + wpt: trkpt4, + }); + expect(await getTrkseg({ id: idTrkseg })).toEqual(trkseg2); + expect((await get(idTrksegpt)).doc).toEqual(trkpt4); + }); +}); diff --git a/src/db/trkpt.ts b/src/db/trkpt.ts index 24c7af3..178a207 100644 --- a/src/db/trkpt.ts +++ b/src/db/trkpt.ts @@ -1,5 +1,7 @@ import getUri, { intToTrkptId } from '../lib/ids'; import { put } from './lib'; +import { getTrksegDocs, putTrkseg } from './trkseg'; +import { emptyWpt } from './wpt'; const emptyTrkpt: Wpt = { $: { lat: 0, lon: 0 }, @@ -30,10 +32,28 @@ const emptyTrkpt: Wpt = { }, }; - export const putTrkpt = async (params: any) => { - const { id, trkpt } = params; - trkpt.id = undefined; - await put(id, 'trkpt', (doc) => trkpt, trkpt); - return trkpt; -}; \ No newline at end of file + const { id, index, wpt } = params; + const { docs } = await getTrksegDocs({ id: id }); + const trkseg = docs.rows[0].doc.doc; + const nbWptInTrkseg = trkseg && trkseg.trkpt ? trkseg.trkpt.length : 0; + const nbWptOutTrkseg = docs.rows.length - 1; + const nbWpt = nbWptInTrkseg + nbWptOutTrkseg; + const positiveIndex = index >= 0 ? index : nbWpt + index; + console.log({ + caller: 'putTrkpt', + nbWptInTrkseg, + nbWptOutTrkseg, + nbWpt, + positiveIndex, + trkpt: JSON.stringify(trkseg.trkpt), + }); + if (positiveIndex < nbWptInTrkseg) { + trkseg.trkpt[positiveIndex] = wpt; + await putTrkseg(id, trkseg); + } else { + const trkptId = docs.rows[1 + positiveIndex - nbWptInTrkseg].doc._id; + await put(trkptId, 'trkpt', () => wpt, emptyWpt); + } + return wpt; +}; diff --git a/src/db/trkseg.ts b/src/db/trkseg.ts index 22c9c8c..a672616 100644 --- a/src/db/trkseg.ts +++ b/src/db/trkseg.ts @@ -1,3 +1,4 @@ +import { cloneDeep } from 'lodash'; import getUri, { intToTrkptId } from '../lib/ids'; import { appendToArray } from './gpx'; import { getFamily, put } from './lib'; @@ -10,44 +11,43 @@ const emptyTrkseg: Trkseg = { extensions: undefined, }; -const getTrksegDocs = async (params: any) => { +export const getTrksegDocs: ({ + id, +}: { + id: string; +}) => Promise<{ docs: any; trkseg: Trkseg }> = async (params) => { const { id } = params; const docs = await getFamily(id, { include_docs: true }); - console.log({ caller: 'getTrksegDocs', id, docs }); - let target: any[]; - let trkseg: Trkseg | undefined = undefined; - docs.rows.every((row: any) => { - // level 0 - if (row.doc.type === 'trkseg') { - if (!!trkseg) { - console.error({ - caller: 'getTrksegDocs', - id, - row, - target, - trkseg, - }); - return false; // Hack to stop if getFamily fails - } - target = [row.doc.doc]; - trkseg = row.doc.doc; + let trkseg: Trkseg; + if (docs.rows.length === 1) { + trkseg = docs.rows[0].doc.doc; + } else { + trkseg = cloneDeep(docs.rows[0].doc.doc); + if (!trkseg.trkpt) { + trkseg.trkpt = []; } - //level 1 - if (row.doc.type === 'trkpt') { - target.splice(1); - // row.doc.doc.id = row.doc._id; - appendToArray(target.at(-1), row.doc.type, row.doc.doc); - target.push(row.doc.doc); - } - return true; - }); - return { trkseg, docs }; + docs.rows.slice(1).forEach((row: any) => { + trkseg.trkpt.push(row.doc.doc); + }); + } + // console.log({ + // caller: 'getRteDocs', + // id, + // docs, + // nbRteptIn: docs.rows[0].doc.doc.rtept?.length, + // nbRteptTotal: rte?.rtept?.length, + // }); + return { docs, trkseg }; }; export const getTrkseg = async (params: any) => { const { id } = params; const { docs, trkseg } = await getTrksegDocs(params); if (docs.rows.length > 1) { + console.log({ + caller: 'getTrkseg compactRteOrTrksegDebounced required', + id, + }); compactRteOrTrksegDebounced({ id, getDocs: getTrksegDocs }); } return trkseg;