Major update: storing trkpt and rtept inside trkseg and rte instead of independent documents.

This commit is contained in:
Eric van der Vlist 2023-02-08 20:44:28 +01:00
parent ecae9b4037
commit 92ffe42ab9
10 changed files with 90 additions and 94 deletions

View File

@ -1,11 +1,15 @@
# Dyomedea # Dyomedea
## License
GPL 3.0.
## Branches ## Branches
* master: dev branch (started as a React project; now using dolidjs) * master: dev (and only active) branch (started as a React project, now using solidjs)
* multi-layers: attempt to create a native React map components. Went pretty far but there was still so many things to implement that I switched to: * multi-layers: (deprecated) attempt to create a native React map components. Went pretty far but there was still so many things to implement that I switched to:
* openlayers: an attempt to use React with Openlayers. Wasn't that easy because Openlayers is heavily based on the DOM while React uses a "pseudo-dom". That has been one of the reasons why I switched (again) to: * openlayers: (deprecated) an attempt to use React with Openlayers. Wasn't that easy because Openlayers is heavily based on the DOM while React uses a "pseudo-dom". That has been one of the reasons why I switched (again) to:
* solid: a SolidJS / Openlayers implementation that has replaced the master branch on Feb 5th, 2023. * solid: (merged into master and deprecated) a SolidJS / Openlayers implementation that has replaced the master branch on Feb 5th, 2023.
## Hiking app. ## Hiking app.
@ -350,6 +354,9 @@ Requires esrun (`sudo npm i -g @digitak/esrun`)
### Patches ### Patches
```
* suid: https://github.com/swordev/suid/issues/89 * suid: https://github.com/swordev/suid/issues/89
### NPM updates: use npm-check-updates ! ### NPM updates: use npm-check-updates !

View File

@ -1,6 +1,5 @@
import { Component, createEffect, createSignal, onCleanup } from 'solid-js'; import { Component, createEffect, createSignal, onCleanup } from 'solid-js';
import dispatch, { cancelDispatch } from '../../workers/dispatcher-main';
import VectorSource from 'ol/source/Vector'; import VectorSource from 'ol/source/Vector';
import GeoJSON from 'ol/format/GeoJSON'; import GeoJSON from 'ol/format/GeoJSON';
import { import {
@ -36,7 +35,7 @@ export const Rte: Component<Props> = ({ vectorSource, rteId, context }) => {
createEffect(() => { createEffect(() => {
console.log({ caller: 'Rte', vectorSource, rteId, rte: rte() }); console.log({ caller: 'Rte', vectorSource, rteId, rte: rte() });
if (rte()) { if (rte() && rte().rtept && rte().rtept.length > 0) {
let geo: any = { let geo: any = {
type: 'FeatureCollection', type: 'FeatureCollection',
features: [ features: [

View File

@ -1,4 +1,4 @@
import { Component, createSignal } from 'solid-js'; import { Component, createSignal, Show } from 'solid-js';
import { peekCachedSignal } from '../../workers/cached-signals'; import { peekCachedSignal } from '../../workers/cached-signals';
import RteIcon from '../../icons/directions-svgrepo-com.svg?component-solid'; import RteIcon from '../../icons/directions-svgrepo-com.svg?component-solid';
import { useI18n } from '@solid-primitives/i18n'; import { useI18n } from '@solid-primitives/i18n';
@ -74,11 +74,13 @@ const RteViewer: Component<Props> = ({ rteId }) => {
<> <>
<div> <div>
{getFormatedLength(lineString)} {t('from')}{' '} {getFormatedLength(lineString)} {t('from')}{' '}
<DisplayOrGetAddress <Show when={false}>
target={() => rte().rtept.at(0)} <DisplayOrGetAddress
putAction='putRtept' target={() => rte().rtept.at(0)}
putParamName='rtept' putAction='putRtept'
/>{' '} putParamName='rtept'
/>{' '}
</Show>
{t('to')}{' '} {t('to')}{' '}
<DisplayOrGetAddress <DisplayOrGetAddress
target={() => rte().rtept.at(-1)} target={() => rte().rtept.at(-1)}

View File

@ -49,7 +49,7 @@ export const Trkseg: Component<Props> = ({
createEffect(() => { createEffect(() => {
console.log({ caller: 'Trkseg', vectorSource, trksegId, trkseg: trkseg() }); console.log({ caller: 'Trkseg', vectorSource, trksegId, trkseg: trkseg() });
if (trkseg()) { if (trkseg() && trkseg().trkpt && trkseg().trkpt.length > 0) {
let geo: any = { let geo: any = {
type: 'FeatureCollection', type: 'FeatureCollection',
features: [ features: [

View File

@ -84,15 +84,15 @@ const prune = (
if ( if (
key === 'wpt' || key === 'wpt' ||
key === 'rte' || key === 'rte' ||
key === 'rtept' || // key === 'rtept' ||
key === 'trk' || key === 'trk' ||
key === 'trkseg' || key === 'trkseg'
key === 'trkpt' // key === 'trkpt'
) { ) {
const subObjects = object[key]; const subObjects = object[key];
for (const index in subObjects) { for (const index in subObjects) {
const subId = { ...id }; const subId = { ...id };
if (key === 'trkpt') { /* if (key === 'trkpt') {
// fix buggy times in GPX tracks // fix buggy times in GPX tracks
const normalId = intToTrkptId( const normalId = intToTrkptId(
new Date(object[key][index].time).valueOf() new Date(object[key][index].time).valueOf()
@ -101,10 +101,10 @@ const prune = (
normalId > previousIds.trk ? normalId : previousIds.trk + 1; normalId > previousIds.trk ? normalId : previousIds.trk + 1;
subId[key] = id; subId[key] = id;
previousIds.trk = id; previousIds.trk = id;
} else { } else { */
previousIds[key] = previousIds[key] + 1; previousIds[key] = previousIds[key] + 1;
subId[key] = previousIds[key]; subId[key] = previousIds[key];
} /* } */
// console.log({ // console.log({
// caller: 'prune', // caller: 'prune',
// id, // id,

View File

@ -1,3 +1,5 @@
import { debounce, memoize, property, wrap } from 'lodash';
import { delay } from '../lib/delay';
import getUri from '../lib/ids'; import getUri from '../lib/ids';
import { appendToArray, putNewGpx } from './gpx'; import { appendToArray, putNewGpx } from './gpx';
import { getFamily, put } from './lib'; import { getFamily, put } from './lib';
@ -32,9 +34,43 @@ export const putNewRte = async (id?: IdRte | IdGpx) => {
return finalId as IdRte; return finalId as IdRte;
}; };
export const getRte = async (params: any) => { // See https://stackoverflow.com/questions/28787436/debounce-a-function-with-argument
const debounceByParam = (
targetFunc: (params: any) => any,
resolver: (params: any) => any,
...debounceParams: any
) =>
wrap(
memoize(() => debounce(targetFunc, ...debounceParams), resolver),
(getMemoizedFunc, ...params) => getMemoizedFunc(...params)(...params)
);
const compactRteOrTrkseg = (params: any) => {
const { getDocs } = params;
getDocs(params).then(({ docs }) => {
if (docs.rows.length > 1) {
const compactedDocs = docs.rows.map((row: any) => {
if (['rte', 'trkseg'].includes(row.doc.type)) {
return row.doc;
}
return { ...row.doc, doc: undefined, _deleted: true };
});
db.bulkDocs(compactedDocs);
}
console.log({ caller: 'compactRteOrTrkseg', params, compactedDocs });
});
};
export const compactRteOrTrksegDebounced = debounceByParam(
compactRteOrTrkseg,
property('id'),
3600000 * (1 + Math.random())
);
const getRteDocs = async (params: any) => {
const { id } = params; const { id } = params;
const docs = await getFamily(id, { include_docs: true }); const docs = await getFamily(id, { include_docs: true });
// console.log({ caller: 'getRte', id, docs });
let target: any[]; let target: any[];
let rte: Rte | undefined = undefined; let rte: Rte | undefined = undefined;
docs.rows.every((row: any) => { docs.rows.every((row: any) => {
@ -56,12 +92,21 @@ export const getRte = async (params: any) => {
//level 1 //level 1
if (row.doc.type === 'rtept') { if (row.doc.type === 'rtept') {
target.splice(1); target.splice(1);
row.doc.doc.id = row.doc._id; // row.doc.doc.id = row.doc._id;
appendToArray(target.at(-1), row.doc.type, row.doc.doc); appendToArray(target.at(-1), row.doc.type, row.doc.doc);
target.push(row.doc.doc); target.push(row.doc.doc);
} }
return true; return true;
}); });
return { docs, rte };
};
export const getRte = async (params: any) => {
const { id } = params;
const { docs, rte } = await getRteDocs(params);
if (docs.rows.length > 1) {
compactRteOrTrksegDebounced({ id, getDocs: getRteDocs });
}
return rte; return rte;
}; };

View File

@ -1,6 +1,3 @@
import getUri from '../lib/ids';
import { put } from './lib';
import { putNewRte } from './rte';
export const emptyRtept: Wpt = { export const emptyRtept: Wpt = {
$: { lat: 0, lon: 0 }, $: { lat: 0, lon: 0 },
@ -24,28 +21,3 @@ export const emptyRtept: Wpt = {
dgpsid: undefined, dgpsid: undefined,
extensions: undefined, extensions: undefined,
}; };
export const putNewRtept = async (id?: IdGpx | IdRte | IdRtept) => {
let finalId = { ...id };
if (!('rtept' in finalId)) {
const rteId = await putNewRte(id);
finalId = { ...rteId, rtept: 0 };
}
const uri = getUri('rtept', finalId);
await put(
uri,
'rtept',
(rtept) => {
return rtept;
},
emptyRtept
);
return finalId as IdRtept;
};
export const putRtept = async (params: any) => {
const { id, rtept } = params;
rtept.id = undefined;
await put(id, 'rtept', (doc) => rtept, rtept);
return rtept;
};

View File

@ -1,6 +1,5 @@
import getUri, { intToTrkptId } from '../lib/ids'; import getUri, { intToTrkptId } from '../lib/ids';
import { put } from './lib'; import { put } from './lib';
import { putNewTrkseg } from './trkseg';
const emptyTrkpt: Wpt = { const emptyTrkpt: Wpt = {
$: { lat: 0, lon: 0 }, $: { lat: 0, lon: 0 },
@ -31,24 +30,6 @@ const emptyTrkpt: Wpt = {
}, },
}; };
export const putNewTrkpt = async (id?: IdTrk | IdGpx | IdTrkseg | IdTrkpt) => {
let finalId = { ...id };
if (!('trkpt' in finalId)) {
const trksegId = await putNewTrkseg(id);
finalId = { ...trksegId, trkpt: intToTrkptId(Date.now()) };
}
const uri = getUri('trkpt', finalId);
await put(
uri,
'trkpt',
(trkpt) => {
return trkpt;
},
emptyTrkpt
);
return finalId;
};
export const putTrkpt = async (params: any) => { export const putTrkpt = async (params: any) => {
const { id, trkpt } = params; const { id, trkpt } = params;

View File

@ -1,6 +1,7 @@
import getUri, { intToTrkptId } from '../lib/ids'; import getUri, { intToTrkptId } from '../lib/ids';
import { appendToArray } from './gpx'; import { appendToArray } from './gpx';
import { getFamily, put } from './lib'; import { getFamily, put } from './lib';
import { compactRteOrTrksegDebounced } from './rte';
import { putNewTrk } from './trk'; import { putNewTrk } from './trk';
import { emptyWpt } from './wpt'; import { emptyWpt } from './wpt';
@ -9,27 +10,10 @@ const emptyTrkseg: Trkseg = {
extensions: undefined, extensions: undefined,
}; };
export const putNewTrkseg = async (id?: IdTrk | IdGpx | IdTrkseg) => { const getTrksegDocs = async (params: any) => {
let finalId = { ...id };
if (!('trkseg' in finalId)) {
const trkId = await putNewTrk(id);
finalId = { ...trkId, trkseg: 0 };
}
const uri = getUri('trkseg', finalId);
await put(
uri,
'trkseg',
(trkseg) => {
return trkseg;
},
emptyTrkseg
);
return finalId as IdTrkseg;
};
export const getTrkseg = async (params: any) => {
const { id } = params; const { id } = params;
const docs = await getFamily(id, { include_docs: true }); const docs = await getFamily(id, { include_docs: true });
console.log({ caller: 'getTrksegDocs', id, docs });
let target: any[]; let target: any[];
let trkseg: Trkseg | undefined = undefined; let trkseg: Trkseg | undefined = undefined;
docs.rows.every((row: any) => { docs.rows.every((row: any) => {
@ -37,13 +21,12 @@ export const getTrkseg = async (params: any) => {
if (row.doc.type === 'trkseg') { if (row.doc.type === 'trkseg') {
if (!!trkseg) { if (!!trkseg) {
console.error({ console.error({
caller: 'getTrkseg', caller: 'getTrksegDocs',
id, id,
row, row,
target, target,
trkseg, trkseg,
}); });
return false; // Hack to stop if getFamily fails return false; // Hack to stop if getFamily fails
} }
target = [row.doc.doc]; target = [row.doc.doc];
@ -52,12 +35,21 @@ export const getTrkseg = async (params: any) => {
//level 1 //level 1
if (row.doc.type === 'trkpt') { if (row.doc.type === 'trkpt') {
target.splice(1); target.splice(1);
row.doc.doc.id = row.doc._id; // row.doc.doc.id = row.doc._id;
appendToArray(target.at(-1), row.doc.type, row.doc.doc); appendToArray(target.at(-1), row.doc.type, row.doc.doc);
target.push(row.doc.doc); target.push(row.doc.doc);
} }
return true; return true;
}); });
return { trkseg, docs };
};
export const getTrkseg = async (params: any) => {
const { id } = params;
const { docs, trkseg } = await getTrksegDocs(params);
if (docs.rows.length > 1) {
compactRteOrTrksegDebounced({ id, getDocs: getTrksegDocs });
}
return trkseg; return trkseg;
}; };

View File

@ -14,7 +14,6 @@ import {
} from '../db/gpx'; } from '../db/gpx';
import { putOverlays } from '../db/overlays'; import { putOverlays } from '../db/overlays';
import { deleteRte, putRte } from '../db/rte'; import { deleteRte, putRte } from '../db/rte';
import { putRtept } from '../db/rtept';
import { getSettings, putSettings } from '../db/settings'; import { getSettings, putSettings } from '../db/settings';
import { getState, setState } from '../db/state'; import { getState, setState } from '../db/state';
import { deleteTrk, getTrk, putNewTrk } from '../db/trk'; import { deleteTrk, getTrk, putNewTrk } from '../db/trk';
@ -52,7 +51,6 @@ onmessage = async function (e) {
putWpt, putWpt,
putRte, putRte,
putRtept,
putTrkpt, putTrkpt,
deleteTrk, deleteTrk,