ezmedicationinput 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/parser.js +21 -9
- package/dist/suggest.js +47 -26
- package/package.json +1 -1
package/dist/parser.js
CHANGED
|
@@ -110,6 +110,7 @@ const COMBO_EVENT_TIMINGS = {
|
|
|
110
110
|
"after sleep": types_1.EventTiming["After Sleep"],
|
|
111
111
|
"upon waking": types_1.EventTiming.Wake
|
|
112
112
|
};
|
|
113
|
+
const MEAL_CONTEXT_CONNECTORS = new Set(["and", "or", "&", "+", "plus"]);
|
|
113
114
|
// Tracking explicit breakfast/lunch/dinner markers lets the meal-expansion
|
|
114
115
|
// logic bail early when the clinician already specified precise events.
|
|
115
116
|
const SPECIFIC_MEAL_TIMINGS = new Set([
|
|
@@ -976,20 +977,31 @@ function applyWhenToken(internal, token, code) {
|
|
|
976
977
|
}
|
|
977
978
|
function parseMealContext(internal, tokens, index, code) {
|
|
978
979
|
const token = tokens[index];
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
980
|
+
let converted = 0;
|
|
981
|
+
for (let lookahead = index + 1; lookahead < tokens.length; lookahead++) {
|
|
982
|
+
const nextToken = tokens[lookahead];
|
|
983
|
+
if (internal.consumed.has(nextToken.index)) {
|
|
984
|
+
continue;
|
|
985
|
+
}
|
|
986
|
+
if (MEAL_CONTEXT_CONNECTORS.has(nextToken.lower)) {
|
|
987
|
+
mark(internal.consumed, nextToken);
|
|
988
|
+
continue;
|
|
989
|
+
}
|
|
990
|
+
const meal = maps_1.MEAL_KEYWORDS[nextToken.lower];
|
|
991
|
+
if (!meal) {
|
|
992
|
+
break;
|
|
993
|
+
}
|
|
986
994
|
const whenCode = code === types_1.EventTiming["After Meal"]
|
|
987
995
|
? meal.pc
|
|
988
996
|
: code === types_1.EventTiming["Before Meal"]
|
|
989
997
|
? meal.ac
|
|
990
998
|
: code;
|
|
991
|
-
|
|
992
|
-
mark(internal.consumed,
|
|
999
|
+
addWhen(internal.when, whenCode);
|
|
1000
|
+
mark(internal.consumed, nextToken);
|
|
1001
|
+
converted++;
|
|
1002
|
+
}
|
|
1003
|
+
if (converted > 0) {
|
|
1004
|
+
mark(internal.consumed, token);
|
|
993
1005
|
return;
|
|
994
1006
|
}
|
|
995
1007
|
applyWhenToken(internal, token, code);
|
package/dist/suggest.js
CHANGED
|
@@ -288,6 +288,7 @@ function buildWhenSequences() {
|
|
|
288
288
|
}
|
|
289
289
|
return sequences;
|
|
290
290
|
}
|
|
291
|
+
const PRECOMPUTED_WHEN_SEQUENCES = buildWhenSequences();
|
|
291
292
|
function tokenizeForMatching(value) {
|
|
292
293
|
return value
|
|
293
294
|
.toLowerCase()
|
|
@@ -403,68 +404,94 @@ function buildDoseValues(input) {
|
|
|
403
404
|
}
|
|
404
405
|
return [...values];
|
|
405
406
|
}
|
|
406
|
-
function generateCandidateDirections(pairs, doseValues, prnReasons, intervalTokens, whenSequences) {
|
|
407
|
+
function generateCandidateDirections(pairs, doseValues, prnReasons, intervalTokens, whenSequences, limit, matcher) {
|
|
407
408
|
const suggestions = [];
|
|
408
409
|
const seen = new Set();
|
|
409
410
|
const push = (value) => {
|
|
410
411
|
const normalized = normalizeSpacing(value);
|
|
411
412
|
if (!normalized) {
|
|
412
|
-
return;
|
|
413
|
+
return false;
|
|
413
414
|
}
|
|
414
415
|
const key = normalizeKey(normalized);
|
|
415
416
|
if (seen.has(key)) {
|
|
416
|
-
return;
|
|
417
|
+
return false;
|
|
417
418
|
}
|
|
418
419
|
seen.add(key);
|
|
420
|
+
if (!matcher(normalized)) {
|
|
421
|
+
return false;
|
|
422
|
+
}
|
|
419
423
|
suggestions.push(normalized);
|
|
424
|
+
return suggestions.length >= limit;
|
|
420
425
|
};
|
|
421
426
|
for (const pair of pairs) {
|
|
422
427
|
const unitVariants = getUnitVariants(pair.unit);
|
|
423
428
|
for (const code of FREQUENCY_CODES) {
|
|
424
429
|
for (const unitVariant of unitVariants) {
|
|
425
430
|
for (const dose of doseValues) {
|
|
426
|
-
push(`${dose} ${unitVariant} ${pair.route} ${code}`)
|
|
431
|
+
if (push(`${dose} ${unitVariant} ${pair.route} ${code}`)) {
|
|
432
|
+
return suggestions;
|
|
433
|
+
}
|
|
427
434
|
}
|
|
428
435
|
}
|
|
429
|
-
push(`${pair.route} ${code}`)
|
|
436
|
+
if (push(`${pair.route} ${code}`)) {
|
|
437
|
+
return suggestions;
|
|
438
|
+
}
|
|
430
439
|
}
|
|
431
440
|
for (const interval of intervalTokens) {
|
|
432
441
|
for (const unitVariant of unitVariants) {
|
|
433
442
|
for (const dose of doseValues) {
|
|
434
|
-
push(`${dose} ${unitVariant} ${pair.route} ${interval}`)
|
|
443
|
+
if (push(`${dose} ${unitVariant} ${pair.route} ${interval}`)) {
|
|
444
|
+
return suggestions;
|
|
445
|
+
}
|
|
435
446
|
for (const reason of prnReasons) {
|
|
436
|
-
push(`${dose} ${unitVariant} ${pair.route} ${interval} prn ${reason}`)
|
|
447
|
+
if (push(`${dose} ${unitVariant} ${pair.route} ${interval} prn ${reason}`)) {
|
|
448
|
+
return suggestions;
|
|
449
|
+
}
|
|
437
450
|
}
|
|
438
451
|
}
|
|
439
452
|
}
|
|
440
|
-
push(`${pair.route} ${interval}`)
|
|
453
|
+
if (push(`${pair.route} ${interval}`)) {
|
|
454
|
+
return suggestions;
|
|
455
|
+
}
|
|
441
456
|
}
|
|
442
457
|
for (const freq of FREQUENCY_NUMBERS) {
|
|
443
458
|
const freqToken = FREQ_TOKEN_BY_NUMBER[freq];
|
|
444
459
|
if (!freqToken) {
|
|
445
460
|
continue;
|
|
446
461
|
}
|
|
447
|
-
push(`1x${freq} ${pair.route} ${freqToken}`)
|
|
462
|
+
if (push(`1x${freq} ${pair.route} ${freqToken}`)) {
|
|
463
|
+
return suggestions;
|
|
464
|
+
}
|
|
448
465
|
for (const when of CORE_WHEN_TOKENS) {
|
|
449
|
-
push(`1x${freq} ${pair.route} ${when}`)
|
|
466
|
+
if (push(`1x${freq} ${pair.route} ${when}`)) {
|
|
467
|
+
return suggestions;
|
|
468
|
+
}
|
|
450
469
|
}
|
|
451
470
|
}
|
|
452
471
|
for (const whenSequence of whenSequences) {
|
|
453
472
|
const suffix = whenSequence.join(" ");
|
|
454
473
|
for (const unitVariant of unitVariants) {
|
|
455
474
|
for (const dose of doseValues) {
|
|
456
|
-
push(`${dose} ${unitVariant} ${pair.route} ${suffix}`)
|
|
475
|
+
if (push(`${dose} ${unitVariant} ${pair.route} ${suffix}`)) {
|
|
476
|
+
return suggestions;
|
|
477
|
+
}
|
|
457
478
|
}
|
|
458
479
|
}
|
|
459
|
-
push(`${pair.route} ${suffix}`)
|
|
480
|
+
if (push(`${pair.route} ${suffix}`)) {
|
|
481
|
+
return suggestions;
|
|
482
|
+
}
|
|
460
483
|
}
|
|
461
484
|
for (const reason of prnReasons) {
|
|
462
485
|
for (const unitVariant of unitVariants) {
|
|
463
486
|
for (const dose of doseValues) {
|
|
464
|
-
push(`${dose} ${unitVariant} ${pair.route} prn ${reason}`)
|
|
487
|
+
if (push(`${dose} ${unitVariant} ${pair.route} prn ${reason}`)) {
|
|
488
|
+
return suggestions;
|
|
489
|
+
}
|
|
465
490
|
}
|
|
466
491
|
}
|
|
467
|
-
push(`${pair.route} prn ${reason}`)
|
|
492
|
+
if (push(`${pair.route} prn ${reason}`)) {
|
|
493
|
+
return suggestions;
|
|
494
|
+
}
|
|
468
495
|
}
|
|
469
496
|
}
|
|
470
497
|
return suggestions;
|
|
@@ -507,6 +534,9 @@ function matchesPrefix(candidate, prefix, prefixCompact, prefixTokens, prefixTok
|
|
|
507
534
|
function suggestSig(input, options) {
|
|
508
535
|
var _a, _b;
|
|
509
536
|
const limit = (_a = options === null || options === void 0 ? void 0 : options.limit) !== null && _a !== void 0 ? _a : DEFAULT_LIMIT;
|
|
537
|
+
if (limit <= 0) {
|
|
538
|
+
return [];
|
|
539
|
+
}
|
|
510
540
|
const prefix = normalizeSpacing(input.toLowerCase());
|
|
511
541
|
const prefixCompact = prefix.replace(/\s+/g, "");
|
|
512
542
|
const prefixNoDashes = prefix.replace(/-/g, "");
|
|
@@ -520,16 +550,7 @@ function suggestSig(input, options) {
|
|
|
520
550
|
const doseValues = buildDoseValues(input);
|
|
521
551
|
const prnReasons = buildPrnReasons(options === null || options === void 0 ? void 0 : options.prnReasons);
|
|
522
552
|
const intervalTokens = buildIntervalTokens(input);
|
|
523
|
-
const whenSequences =
|
|
524
|
-
const
|
|
525
|
-
|
|
526
|
-
for (const candidate of candidates) {
|
|
527
|
-
if (matchesPrefix(candidate, prefix, prefixCompact, prefixTokens, prefixTokensNoDashes, prefixCanonical, prefixCanonicalCompact, prefixNoDashes, prefixCanonicalNoDashes)) {
|
|
528
|
-
results.push(candidate);
|
|
529
|
-
}
|
|
530
|
-
if (results.length >= limit) {
|
|
531
|
-
break;
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
return results;
|
|
553
|
+
const whenSequences = PRECOMPUTED_WHEN_SEQUENCES;
|
|
554
|
+
const matcher = (candidate) => matchesPrefix(candidate, prefix, prefixCompact, prefixTokens, prefixTokensNoDashes, prefixCanonical, prefixCanonicalCompact, prefixNoDashes, prefixCanonicalNoDashes);
|
|
555
|
+
return generateCandidateDirections(pairs, doseValues, prnReasons, intervalTokens, whenSequences, limit, matcher);
|
|
535
556
|
}
|