Assign (some) offline navdata to a survey.

There is no concept of ‘current survey’ in Dougal, and
assigning navigation data to a particular survey is full
of edge cases but sometimes it is necessary or at least
convenient to do so.

This commit implements once such strategy, which consists
of checking the distance to the preplots of all active
surveys (well, those that do have preplots anyway) and
picking the nearest one.

To reduce load, we only do this every once in a while as
governed by the `offline_survey_detect_interval` option
in the configuration.

This strategy is only active if the configuration option
`offline_survey_heuristics == "nearest_preplot"` for the
corresponding navigation header.
This commit is contained in:
D. Berge
2021-05-16 03:16:19 +02:00
parent ef798860cd
commit 76c9c3ef2a
2 changed files with 67 additions and 0 deletions

View File

@@ -2,6 +2,8 @@
const { setSurvey, transaction, pool } = require('../connection');
let last_tstamp = 0;
async function getAllProjectConfigs () {
const client = await pool.connect();
@@ -64,6 +66,50 @@ async function getNearestPreplot (candidates) {
return res.rows[0] && res.rows[0].schema;
}
async function getNearestOfflinePreplot (candidates) {
const queries = candidates.map( c=> {
let text, values;
if ("latitude" in candidates[0] && "longitude" in candidates[0]) {
text = `
SELECT
'${c._schema}' AS _schema,
ST_Distance(ST_Transform(ST_SetSRID(ST_MakePoint($1, $2), 4326), ST_SRID(geometry)), geometry) AS distance
FROM ${c._schema}.preplot_points
ORDER BY distance ASC
LIMIT 1;
`;
values = [ candidates[0].longitude, candidates[0].latitude ];
} else if ("easting" in candidates[0] && "northing" in candidates[0]) {
text = `
SELECT
'${c._schema}' AS _schema,
ST_Distance(ST_SetSRID(ST_MakePoint($1, $2), ST_SRID(geometry)), geometry) AS distance
FROM ${c._schema}.preplot_points
ORDER BY distance ASC
LIMIT 1;
`;
values = [ candidates[0].easting, candidates[0].northing ];
} else {
// Missing a position, shouldn't happen at this point
return {};
}
return {text, values};
}).filter(i => i.text && i.values);
const client = await pool.connect();
const results = [];
for (const qry of queries) {
const res = await client.query(qry.text, qry.values);
if (res.rows[0] && res.rows[0]._schema) {
results.push(res.rows[0]);
}
}
client.release();
const _schema = results.sort( (a, b) => a.distance - b.distance).shift()._schema;
return candidates.find(c => c._schema == _schema);
}
async function saveOnline (dataset, opts = {}) {
const client = await pool.connect();
@@ -236,6 +282,23 @@ async function save (navData, opts = {}) {
navData.payload._point = candidates[0].point;
navData.payload._online = true;
}
} else {
// We are offline. We only assign _schema once every save_interval seconds at most
if (opts.offline_survey_heuristics == "nearest_preplot") {
const now = Date.now();
const do_save = !opts.offline_survey_detect_interval ||
(now - last_tstamp) >= opts.offline_survey_detect_interval;
if (do_save) {
const configs = await getAllProjectConfigs();
const candidates = configs.map(c => Object.assign({}, navData, {_schema: c.schema}));
const bestCandidate = await getNearestOfflinePreplot(candidates);
if (bestCandidate) {
navData.payload._schema = bestCandidate._schema;
last_tstamp = now;
}
}
}
}
await saveOffline(navData, opts);