mirror of
https://gitlab.com/wgp/dougal/software.git
synced 2025-12-06 11:17:08 +00:00
Refactor the function producing Seis+JSON into its own file.
For reuse.
This commit is contained in:
@@ -1,291 +1,5 @@
|
||||
|
||||
const { event, sequence } = require('../../../../lib/db');
|
||||
|
||||
function transform (events, sequences, opts = {}) {
|
||||
|
||||
const dgl = !!opts.projectId;
|
||||
const exportQC = opts.exportQC !== false;
|
||||
const exportGeneral = opts.exportGeneral !== false;
|
||||
const exportMissing = opts.exportMissing !== false;
|
||||
|
||||
const output = {
|
||||
DglProjectId: opts.projectId,
|
||||
Sequences: [],
|
||||
DglCreatedOn: dgl && new Date()
|
||||
};
|
||||
|
||||
// NOTE: Events come in descending chronological
|
||||
// order from the server.
|
||||
for (const event of events.reverse()) {
|
||||
const SequenceNumber = event.sequence;
|
||||
if (SequenceNumber) {
|
||||
const sequence = sequences.find(s => s.sequence == SequenceNumber);
|
||||
if (!sequence) {
|
||||
throw Error(`Sequence ${SequenceNumber} not found in sequence list`);
|
||||
}
|
||||
|
||||
let SequenceObject = output.Sequences.find(s => s.SequenceNumber == SequenceNumber);
|
||||
if (!SequenceObject) {
|
||||
SequenceObject = {
|
||||
SequenceNumber,
|
||||
Entries: [],
|
||||
DglNumPoints: sequence.num_points,
|
||||
DglNumMissing: sequence.missing_shots,
|
||||
// NOTE: Distance & azimuth refer to raw data if the sequence
|
||||
// status is 'raw' and to final data if status is 'final'. In
|
||||
// the event of it being NTBP it depends on whether final data
|
||||
// exists or not.
|
||||
DglLength: sequence.length
|
||||
};
|
||||
[sequence.remarks, sequence.remarks_final].filter(i => !!i).forEach(i => {
|
||||
if (!SequenceObject.DglSequenceComments) {
|
||||
SequenceObject.DglSequenceComments = []
|
||||
}
|
||||
SequenceObject.DglSequenceComments.push(i);
|
||||
});
|
||||
|
||||
output.Sequences.push(SequenceObject);
|
||||
}
|
||||
|
||||
if (event.labels.includes("FSP")) {
|
||||
const entry = {
|
||||
"EntryType": "Start of line recording",
|
||||
"EntryTypeId": 3000,
|
||||
"Comment": event.remarks.toString(),
|
||||
"Heading": Number(sequence.azimuth.toFixed(1)),
|
||||
"IsReshoot": sequence.reshoot, // FIXME Add this property to sequence object
|
||||
"IsUndershoot": false,
|
||||
// NOTE https://gitlab.com/wgp/dougal/software/-/issues/12#note_419162674
|
||||
"LineNumber": sequence.line.toString(),
|
||||
"LineType": "Prime", // FIXME
|
||||
"ShotPointId": event.point,
|
||||
"Time": event.tstamp
|
||||
}
|
||||
|
||||
SequenceObject.Entries.push(entry);
|
||||
}
|
||||
|
||||
if (event.labels.includes("FGSP")) {
|
||||
const entry = {
|
||||
"EntryType": "Start good",
|
||||
"EntryTypeId": 3001,
|
||||
"Comment": event.remarks.toString(),
|
||||
"ShotPointId": event.point,
|
||||
"Time": event.tstamp
|
||||
}
|
||||
|
||||
SequenceObject.Entries.push(entry);
|
||||
}
|
||||
|
||||
if (event.labels.includes("FCSP")) {
|
||||
const entry = {
|
||||
"EntryType": "Start charged",
|
||||
"EntryTypeId": 3002,
|
||||
"Comment": event.remarks.toString(),
|
||||
"ShotPointId": event.point,
|
||||
"Time": event.tstamp
|
||||
}
|
||||
|
||||
SequenceObject.Entries.push(entry);
|
||||
}
|
||||
|
||||
if (event.labels.includes("LGFFSP")) {
|
||||
const entry = {
|
||||
"EntryType": "Last good Full Fold",
|
||||
"EntryTypeId": 3008,
|
||||
"Comment": event.remarks.toString(),
|
||||
"ShotPointId": event.point,
|
||||
"Time": event.tstamp
|
||||
}
|
||||
|
||||
SequenceObject.Entries.push(entry);
|
||||
}
|
||||
|
||||
if (event.labels.includes("LCFFSP")) {
|
||||
const entry = {
|
||||
"EntryType": "Last charged Full Fold",
|
||||
"EntryTypeId": 3009,
|
||||
"Comment": event.remarks.toString(),
|
||||
"ShotPointId": event.point,
|
||||
"Time": event.tstamp
|
||||
}
|
||||
|
||||
SequenceObject.Entries.push(entry);
|
||||
}
|
||||
|
||||
if (event.labels.includes("FDSP")) {
|
||||
const entry = {
|
||||
"EntryType": "Midnight",
|
||||
"EntryTypeId": 3003,
|
||||
"Comment": event.remarks.toString(),
|
||||
"ShotPointId": event.point,
|
||||
"Time": event.tstamp
|
||||
}
|
||||
|
||||
SequenceObject.Entries.push(entry);
|
||||
}
|
||||
|
||||
if (event.labels.includes("LCSP")) {
|
||||
const entry = {
|
||||
"EntryType": "End charged",
|
||||
"EntryTypeId": 3005,
|
||||
"Comment": event.remarks.toString(),
|
||||
"ShotPointId": event.point,
|
||||
"Time": event.tstamp
|
||||
}
|
||||
|
||||
SequenceObject.Entries.push(entry);
|
||||
}
|
||||
|
||||
if (event.labels.includes("LGSP")) {
|
||||
const entry = {
|
||||
"EntryType": "End good",
|
||||
"EntryTypeId": 3006,
|
||||
"Comment": event.remarks.toString(),
|
||||
"ShotPointId": event.point,
|
||||
"Time": event.tstamp
|
||||
}
|
||||
|
||||
SequenceObject.Entries.push(entry);
|
||||
}
|
||||
|
||||
if (event.labels.includes("LSP")) {
|
||||
const entry = {
|
||||
"EntryType": "End of line recording",
|
||||
"EntryTypeId": 3007,
|
||||
"Comment": event.remarks.toString(),
|
||||
"IsNTBP": sequence.status == "ntbp",
|
||||
// NOTE: Always pending, see
|
||||
// https://gitlab.com/wgp/dougal/software/-/issues/12
|
||||
"LineStatus": "Pending",
|
||||
"ShotPointId": event.point,
|
||||
"Time": event.tstamp
|
||||
}
|
||||
|
||||
SequenceObject.Entries.push(entry);
|
||||
}
|
||||
|
||||
// Dougal QC data
|
||||
|
||||
if (exportQC) {
|
||||
if (event.labels.includes("QC")) {
|
||||
if (!event.labels.includes("QCAccepted")) {
|
||||
const entry = {
|
||||
"EntryType": "QC",
|
||||
"Comment": event.remarks.toString(),
|
||||
"ShotPointId": event.point,
|
||||
"Time": event.tstamp
|
||||
}
|
||||
SequenceObject.Entries.push(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (exportGeneral) {
|
||||
// These are labels that we have already (potentially) exported
|
||||
const excluded = [
|
||||
"FSP", "FGSP", "FCSP", "LGFFSP",
|
||||
"LCFFSP", "LCSP", "LGSP", "LSP",
|
||||
"LDSP", "FDSP", "QC", "QCAccepted",
|
||||
"Internal", "Private", "Confidential",
|
||||
"NoExport"
|
||||
];
|
||||
if (!event.labels || !event.labels.some( l => excluded.includes(l) )) {
|
||||
const entry = {
|
||||
"Comment": event.remarks.toString(),
|
||||
"ShotPointId": event.point,
|
||||
"Time": event.tstamp
|
||||
}
|
||||
SequenceObject.Entries.push(entry);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
for (const SequenceObject of output.Sequences) {
|
||||
const sequence = sequences.find(s => s.sequence == SequenceObject.SequenceNumber);
|
||||
|
||||
// If no explicit FSP but there is a FGSP, clone it as FSP.
|
||||
if (!SequenceObject.Entries.find(i => i.EntryTypeId == 3000)) {
|
||||
const fgspIndex = SequenceObject.Entries.findIndex(i => i.EntryTypeId == 3001);
|
||||
if (fgspIndex != -1) {
|
||||
const fsp = Object.assign({}, SequenceObject.Entries[fgspIndex], {
|
||||
"EntryType": "Start of line recording",
|
||||
"EntryTypeId": 3000,
|
||||
"Heading": Number(sequence.azimuth.toFixed(1)),
|
||||
"IsReshoot": sequence.reshoot,
|
||||
"IsUndershoot": false,
|
||||
"LineNumber": sequence.line.toString(),
|
||||
"LineType": "Prime", // FIXME
|
||||
});
|
||||
SequenceObject.Entries.splice(fgspIndex, 0, fsp);
|
||||
} else {
|
||||
// We have neither an FSP nor an FGSP, let us take the first
|
||||
// preplot shot from the sequence data as save that as FSP
|
||||
// (we intentionally omit adding an FGSP as we know nothing
|
||||
// about the user's intent).
|
||||
const fsp = {
|
||||
"EntryType": "Start of line recording",
|
||||
"EntryTypeId": 3000,
|
||||
"Comment": sequence.fsp_final
|
||||
? "(First preplot shot found in P1)"
|
||||
: "(First shot found in P1)",
|
||||
"Heading": Number(sequence.azimuth.toFixed(1)),
|
||||
"IsReshoot": sequence.reshoot, // FIXME Add this property to sequence object
|
||||
"IsUndershoot": false,
|
||||
// NOTE https://gitlab.com/wgp/dougal/software/-/issues/12#note_419162674
|
||||
"LineNumber": sequence.line.toString(),
|
||||
"LineType": "Prime", // FIXME
|
||||
"ShotPointId": sequence.fsp_final || sequence.fsp,
|
||||
"Time": sequence.ts0_final || sequence.ts0
|
||||
}
|
||||
SequenceObject.Entries.unshift(fsp);
|
||||
}
|
||||
}
|
||||
|
||||
// If no explicit LSP but there is a LGSP, clone it as LSP.
|
||||
if (!SequenceObject.Entries.find(i => i.EntryTypeId == 3007)) {
|
||||
const lgspIndex = SequenceObject.Entries.findIndex(i => i.EntryTypeId == 3006);
|
||||
if (lgspIndex != -1) {
|
||||
const lsp = Object.assign({}, SequenceObject.Entries[lgspIndex], {
|
||||
"EntryType": "End of line recording",
|
||||
"EntryTypeId": 3007,
|
||||
"IsNTBP": sequence.status == "ntbp",
|
||||
"LineStatus": "Pending",
|
||||
});
|
||||
SequenceObject.Entries.splice(lgspIndex+1, 0, lsp);
|
||||
} else {
|
||||
// See comment above concerning FSP
|
||||
const lsp = {
|
||||
"EntryType": "End of line recording",
|
||||
"EntryTypeId": 3007,
|
||||
"Comment": sequence.lsp_final
|
||||
? "(Last preplot shot found in P1)"
|
||||
: "(Last shot found in P1)",
|
||||
"IsNTBP": sequence.status == "ntbp",
|
||||
// NOTE: Always pending, see
|
||||
// https://gitlab.com/wgp/dougal/software/-/issues/12
|
||||
"LineStatus": "Pending",
|
||||
"ShotPointId": sequence.lsp_final || sequence.lsp,
|
||||
"Time": sequence.ts1_final || sequence.ts1
|
||||
}
|
||||
SequenceObject.Entries.push(lsp);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the missing shots object if not inhibited by the user.
|
||||
if (exportMissing) {
|
||||
// The user also needs to request missing shots from the sequences
|
||||
// endpoint; these are not returned by default.
|
||||
if ("missing_final" in sequence) {
|
||||
SequenceObject.MissingShots = sequence.missing_final.map(s => s.point).sort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
const { transform } = require('../../../../lib/sse');
|
||||
|
||||
const seis = async function (req, res, next) {
|
||||
try {
|
||||
|
||||
3
lib/www/server/lib/sse/index.js
Normal file
3
lib/www/server/lib/sse/index.js
Normal file
@@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
transform: require('./transform')
|
||||
}
|
||||
289
lib/www/server/lib/sse/transform.js
Normal file
289
lib/www/server/lib/sse/transform.js
Normal file
@@ -0,0 +1,289 @@
|
||||
|
||||
|
||||
function transform (events, sequences, opts = {}) {
|
||||
|
||||
const dgl = !!opts.projectId;
|
||||
const exportQC = opts.exportQC !== false;
|
||||
const exportGeneral = opts.exportGeneral !== false;
|
||||
const exportMissing = opts.exportMissing !== false;
|
||||
|
||||
const output = {
|
||||
DglProjectId: opts.projectId,
|
||||
Sequences: [],
|
||||
DglCreatedOn: dgl && new Date()
|
||||
};
|
||||
|
||||
// NOTE: Events come in descending chronological
|
||||
// order from the server.
|
||||
for (const event of events.reverse()) {
|
||||
const SequenceNumber = event.sequence;
|
||||
if (SequenceNumber) {
|
||||
const sequence = sequences.find(s => s.sequence == SequenceNumber);
|
||||
if (!sequence) {
|
||||
throw Error(`Sequence ${SequenceNumber} not found in sequence list`);
|
||||
}
|
||||
|
||||
let SequenceObject = output.Sequences.find(s => s.SequenceNumber == SequenceNumber);
|
||||
if (!SequenceObject) {
|
||||
SequenceObject = {
|
||||
SequenceNumber,
|
||||
Entries: [],
|
||||
DglNumPoints: sequence.num_points,
|
||||
DglNumMissing: sequence.missing_shots,
|
||||
// NOTE: Distance & azimuth refer to raw data if the sequence
|
||||
// status is 'raw' and to final data if status is 'final'. In
|
||||
// the event of it being NTBP it depends on whether final data
|
||||
// exists or not.
|
||||
DglLength: sequence.length
|
||||
};
|
||||
[sequence.remarks, sequence.remarks_final].filter(i => !!i).forEach(i => {
|
||||
if (!SequenceObject.DglSequenceComments) {
|
||||
SequenceObject.DglSequenceComments = []
|
||||
}
|
||||
SequenceObject.DglSequenceComments.push(i);
|
||||
});
|
||||
|
||||
output.Sequences.push(SequenceObject);
|
||||
}
|
||||
|
||||
if (event.labels.includes("FSP")) {
|
||||
const entry = {
|
||||
"EntryType": "Start of line recording",
|
||||
"EntryTypeId": 3000,
|
||||
"Comment": event.remarks.toString(),
|
||||
"Heading": Number(sequence.azimuth.toFixed(1)),
|
||||
"IsReshoot": sequence.reshoot, // FIXME Add this property to sequence object
|
||||
"IsUndershoot": false,
|
||||
// NOTE https://gitlab.com/wgp/dougal/software/-/issues/12#note_419162674
|
||||
"LineNumber": sequence.line.toString(),
|
||||
"LineType": "Prime", // FIXME
|
||||
"ShotPointId": event.point,
|
||||
"Time": event.tstamp
|
||||
}
|
||||
|
||||
SequenceObject.Entries.push(entry);
|
||||
}
|
||||
|
||||
if (event.labels.includes("FGSP")) {
|
||||
const entry = {
|
||||
"EntryType": "Start good",
|
||||
"EntryTypeId": 3001,
|
||||
"Comment": event.remarks.toString(),
|
||||
"ShotPointId": event.point,
|
||||
"Time": event.tstamp
|
||||
}
|
||||
|
||||
SequenceObject.Entries.push(entry);
|
||||
}
|
||||
|
||||
if (event.labels.includes("FCSP")) {
|
||||
const entry = {
|
||||
"EntryType": "Start charged",
|
||||
"EntryTypeId": 3002,
|
||||
"Comment": event.remarks.toString(),
|
||||
"ShotPointId": event.point,
|
||||
"Time": event.tstamp
|
||||
}
|
||||
|
||||
SequenceObject.Entries.push(entry);
|
||||
}
|
||||
|
||||
if (event.labels.includes("LGFFSP")) {
|
||||
const entry = {
|
||||
"EntryType": "Last good Full Fold",
|
||||
"EntryTypeId": 3008,
|
||||
"Comment": event.remarks.toString(),
|
||||
"ShotPointId": event.point,
|
||||
"Time": event.tstamp
|
||||
}
|
||||
|
||||
SequenceObject.Entries.push(entry);
|
||||
}
|
||||
|
||||
if (event.labels.includes("LCFFSP")) {
|
||||
const entry = {
|
||||
"EntryType": "Last charged Full Fold",
|
||||
"EntryTypeId": 3009,
|
||||
"Comment": event.remarks.toString(),
|
||||
"ShotPointId": event.point,
|
||||
"Time": event.tstamp
|
||||
}
|
||||
|
||||
SequenceObject.Entries.push(entry);
|
||||
}
|
||||
|
||||
if (event.labels.includes("FDSP")) {
|
||||
const entry = {
|
||||
"EntryType": "Midnight",
|
||||
"EntryTypeId": 3003,
|
||||
"Comment": event.remarks.toString(),
|
||||
"ShotPointId": event.point,
|
||||
"Time": event.tstamp
|
||||
}
|
||||
|
||||
SequenceObject.Entries.push(entry);
|
||||
}
|
||||
|
||||
if (event.labels.includes("LCSP")) {
|
||||
const entry = {
|
||||
"EntryType": "End charged",
|
||||
"EntryTypeId": 3005,
|
||||
"Comment": event.remarks.toString(),
|
||||
"ShotPointId": event.point,
|
||||
"Time": event.tstamp
|
||||
}
|
||||
|
||||
SequenceObject.Entries.push(entry);
|
||||
}
|
||||
|
||||
if (event.labels.includes("LGSP")) {
|
||||
const entry = {
|
||||
"EntryType": "End good",
|
||||
"EntryTypeId": 3006,
|
||||
"Comment": event.remarks.toString(),
|
||||
"ShotPointId": event.point,
|
||||
"Time": event.tstamp
|
||||
}
|
||||
|
||||
SequenceObject.Entries.push(entry);
|
||||
}
|
||||
|
||||
if (event.labels.includes("LSP")) {
|
||||
const entry = {
|
||||
"EntryType": "End of line recording",
|
||||
"EntryTypeId": 3007,
|
||||
"Comment": event.remarks.toString(),
|
||||
"IsNTBP": sequence.status == "ntbp",
|
||||
// NOTE: Always pending, see
|
||||
// https://gitlab.com/wgp/dougal/software/-/issues/12
|
||||
"LineStatus": "Pending",
|
||||
"ShotPointId": event.point,
|
||||
"Time": event.tstamp
|
||||
}
|
||||
|
||||
SequenceObject.Entries.push(entry);
|
||||
}
|
||||
|
||||
// Dougal QC data
|
||||
|
||||
if (exportQC) {
|
||||
if (event.labels.includes("QC")) {
|
||||
if (!event.labels.includes("QCAccepted")) {
|
||||
const entry = {
|
||||
"EntryType": "QC",
|
||||
"Comment": event.remarks.toString(),
|
||||
"ShotPointId": event.point,
|
||||
"Time": event.tstamp
|
||||
}
|
||||
SequenceObject.Entries.push(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (exportGeneral) {
|
||||
// These are labels that we have already (potentially) exported
|
||||
const excluded = [
|
||||
"FSP", "FGSP", "FCSP", "LGFFSP",
|
||||
"LCFFSP", "LCSP", "LGSP", "LSP",
|
||||
"LDSP", "FDSP", "QC", "QCAccepted",
|
||||
"Internal", "Private", "Confidential",
|
||||
"NoExport"
|
||||
];
|
||||
if (!event.labels || !event.labels.some( l => excluded.includes(l) )) {
|
||||
const entry = {
|
||||
"Comment": event.remarks.toString(),
|
||||
"ShotPointId": event.point,
|
||||
"Time": event.tstamp
|
||||
}
|
||||
SequenceObject.Entries.push(entry);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
for (const SequenceObject of output.Sequences) {
|
||||
const sequence = sequences.find(s => s.sequence == SequenceObject.SequenceNumber);
|
||||
|
||||
// If no explicit FSP but there is a FGSP, clone it as FSP.
|
||||
if (!SequenceObject.Entries.find(i => i.EntryTypeId == 3000)) {
|
||||
const fgspIndex = SequenceObject.Entries.findIndex(i => i.EntryTypeId == 3001);
|
||||
if (fgspIndex != -1) {
|
||||
const fsp = Object.assign({}, SequenceObject.Entries[fgspIndex], {
|
||||
"EntryType": "Start of line recording",
|
||||
"EntryTypeId": 3000,
|
||||
"Heading": Number(sequence.azimuth.toFixed(1)),
|
||||
"IsReshoot": sequence.reshoot,
|
||||
"IsUndershoot": false,
|
||||
"LineNumber": sequence.line.toString(),
|
||||
"LineType": "Prime", // FIXME
|
||||
});
|
||||
SequenceObject.Entries.splice(fgspIndex, 0, fsp);
|
||||
} else {
|
||||
// We have neither an FSP nor an FGSP, let us take the first
|
||||
// preplot shot from the sequence data as save that as FSP
|
||||
// (we intentionally omit adding an FGSP as we know nothing
|
||||
// about the user's intent).
|
||||
const fsp = {
|
||||
"EntryType": "Start of line recording",
|
||||
"EntryTypeId": 3000,
|
||||
"Comment": sequence.fsp_final
|
||||
? "(First preplot shot found in P1)"
|
||||
: "(First shot found in P1)",
|
||||
"Heading": Number(sequence.azimuth.toFixed(1)),
|
||||
"IsReshoot": sequence.reshoot, // FIXME Add this property to sequence object
|
||||
"IsUndershoot": false,
|
||||
// NOTE https://gitlab.com/wgp/dougal/software/-/issues/12#note_419162674
|
||||
"LineNumber": sequence.line.toString(),
|
||||
"LineType": "Prime", // FIXME
|
||||
"ShotPointId": sequence.fsp_final || sequence.fsp,
|
||||
"Time": sequence.ts0_final || sequence.ts0
|
||||
}
|
||||
SequenceObject.Entries.unshift(fsp);
|
||||
}
|
||||
}
|
||||
|
||||
// If no explicit LSP but there is a LGSP, clone it as LSP.
|
||||
if (!SequenceObject.Entries.find(i => i.EntryTypeId == 3007)) {
|
||||
const lgspIndex = SequenceObject.Entries.findIndex(i => i.EntryTypeId == 3006);
|
||||
if (lgspIndex != -1) {
|
||||
const lsp = Object.assign({}, SequenceObject.Entries[lgspIndex], {
|
||||
"EntryType": "End of line recording",
|
||||
"EntryTypeId": 3007,
|
||||
"IsNTBP": sequence.status == "ntbp",
|
||||
"LineStatus": "Pending",
|
||||
});
|
||||
SequenceObject.Entries.splice(lgspIndex+1, 0, lsp);
|
||||
} else {
|
||||
// See comment above concerning FSP
|
||||
const lsp = {
|
||||
"EntryType": "End of line recording",
|
||||
"EntryTypeId": 3007,
|
||||
"Comment": sequence.lsp_final
|
||||
? "(Last preplot shot found in P1)"
|
||||
: "(Last shot found in P1)",
|
||||
"IsNTBP": sequence.status == "ntbp",
|
||||
// NOTE: Always pending, see
|
||||
// https://gitlab.com/wgp/dougal/software/-/issues/12
|
||||
"LineStatus": "Pending",
|
||||
"ShotPointId": sequence.lsp_final || sequence.lsp,
|
||||
"Time": sequence.ts1_final || sequence.ts1
|
||||
}
|
||||
SequenceObject.Entries.push(lsp);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the missing shots object if not inhibited by the user.
|
||||
if (exportMissing) {
|
||||
// The user also needs to request missing shots from the sequences
|
||||
// endpoint; these are not returned by default.
|
||||
if ("missing_final" in sequence) {
|
||||
SequenceObject.MissingShots = sequence.missing_final.map(s => s.point).sort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
module.exports = transform;
|
||||
Reference in New Issue
Block a user