ezmedicationinput 0.1.44 → 0.1.46
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/README.md +265 -2
- package/dist/body-site-grammar.d.ts +39 -0
- package/dist/body-site-lookup.d.ts +84 -0
- package/dist/body-site-resolution.d.ts +9 -0
- package/dist/body-site-spatial.d.ts +6 -0
- package/dist/clause-tail-grammar.d.ts +18 -0
- package/dist/fhir-translations.d.ts +4 -1
- package/dist/fhir.d.ts +9 -1
- package/dist/hpsg/chart.d.ts +14 -0
- package/dist/hpsg/clause-parser.d.ts +3 -0
- package/dist/hpsg/defaults.d.ts +9 -0
- package/dist/hpsg/lexical-classes.d.ts +89 -0
- package/dist/hpsg/method-lexicon.d.ts +13 -0
- package/dist/hpsg/projection.d.ts +12 -0
- package/dist/hpsg/rule-context.d.ts +32 -0
- package/dist/hpsg/rules/core-rules.d.ts +8 -0
- package/dist/hpsg/rules/instruction-rules.d.ts +4 -0
- package/dist/hpsg/rules/prn-rules.d.ts +3 -0
- package/dist/hpsg/rules/product-route.d.ts +2 -0
- package/dist/hpsg/rules/site-rules.d.ts +4 -0
- package/dist/hpsg/rules/timing-rules.d.ts +12 -0
- package/dist/hpsg/segmenter.d.ts +6 -0
- package/dist/hpsg/signature.d.ts +116 -0
- package/dist/hpsg/timing-lexicon.d.ts +31 -0
- package/dist/hpsg/unification.d.ts +8 -0
- package/dist/index.cjs +21052 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +20865 -680
- package/dist/maps.d.ts +4 -2
- package/dist/parser-state.d.ts +4 -1
- package/dist/parser.d.ts +3 -13
- package/dist/prn-reason-coding.d.ts +8 -0
- package/dist/site-coding.d.ts +5 -0
- package/dist/snomed-postcoordination.d.ts +25 -0
- package/dist/snomed.d.ts +13 -0
- package/dist/types.d.ts +61 -16
- package/dist/unit-lexicon.d.ts +4 -0
- package/package.json +17 -6
- package/dist/advice-rules.json +0 -772
- package/dist/advice-terminology.json +0 -104
- package/dist/advice.js +0 -1375
- package/dist/context.js +0 -50
- package/dist/event-trigger.d.ts +0 -14
- package/dist/event-trigger.js +0 -501
- package/dist/fhir-translations.js +0 -117
- package/dist/fhir.js +0 -693
- package/dist/format.js +0 -1034
- package/dist/i18n.js +0 -1341
- package/dist/internal-types.d.ts +0 -60
- package/dist/internal-types.js +0 -2
- package/dist/ir.js +0 -178
- package/dist/lexer/lex.js +0 -401
- package/dist/lexer/meaning.js +0 -619
- package/dist/lexer/surface.js +0 -62
- package/dist/lexer/token-types.js +0 -19
- package/dist/maps.js +0 -2226
- package/dist/package.json +0 -3
- package/dist/parser-state.js +0 -441
- package/dist/parser.js +0 -5631
- package/dist/prn.js +0 -59
- package/dist/safety.js +0 -15
- package/dist/schedule.js +0 -1636
- package/dist/segment.d.ts +0 -6
- package/dist/segment.js +0 -203
- package/dist/site-phrases.js +0 -344
- package/dist/suggest.js +0 -907
- package/dist/timing-summary.js +0 -138
- package/dist/types.js +0 -276
- package/dist/utils/array.js +0 -11
- package/dist/utils/enum.d.ts +0 -2
- package/dist/utils/enum.js +0 -7
- package/dist/utils/object.js +0 -34
- package/dist/utils/strength.js +0 -149
- package/dist/utils/text.js +0 -48
- package/dist/utils/units.js +0 -82
package/dist/format.js
DELETED
|
@@ -1,1034 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.formatCanonicalClause = formatCanonicalClause;
|
|
4
|
-
exports.formatInternal = formatInternal;
|
|
5
|
-
const prn_1 = require("./prn");
|
|
6
|
-
const types_1 = require("./types");
|
|
7
|
-
const timing_summary_1 = require("./timing-summary");
|
|
8
|
-
const ROUTE_SHORT = {
|
|
9
|
-
[types_1.RouteCode["Oral route"]]: "PO",
|
|
10
|
-
[types_1.RouteCode["Sublingual route"]]: "SL",
|
|
11
|
-
[types_1.RouteCode["Buccal route"]]: "BUC",
|
|
12
|
-
[types_1.RouteCode["Respiratory tract route (qualifier value)"]]: "INH",
|
|
13
|
-
[types_1.RouteCode["Nasal route"]]: "IN",
|
|
14
|
-
[types_1.RouteCode["Topical route"]]: "TOP",
|
|
15
|
-
[types_1.RouteCode["Transdermal route"]]: "TD",
|
|
16
|
-
[types_1.RouteCode["Subcutaneous route"]]: "SC",
|
|
17
|
-
[types_1.RouteCode["Intramuscular route"]]: "IM",
|
|
18
|
-
[types_1.RouteCode["Intravenous route"]]: "IV",
|
|
19
|
-
[types_1.RouteCode["Per rectum"]]: "PR",
|
|
20
|
-
[types_1.RouteCode["Per vagina"]]: "PV",
|
|
21
|
-
[types_1.RouteCode["Ophthalmic route"]]: "OPH",
|
|
22
|
-
[types_1.RouteCode["Intravitreal route (qualifier value)"]]: "IVT"
|
|
23
|
-
};
|
|
24
|
-
const WHEN_TEXT = {
|
|
25
|
-
[types_1.EventTiming["Before Sleep"]]: "at bedtime",
|
|
26
|
-
[types_1.EventTiming["Before Meal"]]: "before meals",
|
|
27
|
-
[types_1.EventTiming["Before Breakfast"]]: "before breakfast",
|
|
28
|
-
[types_1.EventTiming["Before Lunch"]]: "before lunch",
|
|
29
|
-
[types_1.EventTiming["Before Dinner"]]: "before dinner",
|
|
30
|
-
[types_1.EventTiming["After Meal"]]: "after meals",
|
|
31
|
-
[types_1.EventTiming["After Breakfast"]]: "after breakfast",
|
|
32
|
-
[types_1.EventTiming["After Lunch"]]: "after lunch",
|
|
33
|
-
[types_1.EventTiming["After Dinner"]]: "after dinner",
|
|
34
|
-
[types_1.EventTiming.Meal]: "with meals",
|
|
35
|
-
[types_1.EventTiming.Breakfast]: "with breakfast",
|
|
36
|
-
[types_1.EventTiming.Lunch]: "with lunch",
|
|
37
|
-
[types_1.EventTiming.Dinner]: "with dinner",
|
|
38
|
-
[types_1.EventTiming.Morning]: "in the morning",
|
|
39
|
-
[types_1.EventTiming["Early Morning"]]: "in the early morning",
|
|
40
|
-
[types_1.EventTiming["Late Morning"]]: "in the late morning",
|
|
41
|
-
[types_1.EventTiming.Noon]: "at noon",
|
|
42
|
-
[types_1.EventTiming.Afternoon]: "in the afternoon",
|
|
43
|
-
[types_1.EventTiming["Early Afternoon"]]: "in the early afternoon",
|
|
44
|
-
[types_1.EventTiming["Late Afternoon"]]: "in the late afternoon",
|
|
45
|
-
[types_1.EventTiming.Evening]: "in the evening",
|
|
46
|
-
[types_1.EventTiming["Early Evening"]]: "in the early evening",
|
|
47
|
-
[types_1.EventTiming["Late Evening"]]: "in the late evening",
|
|
48
|
-
[types_1.EventTiming.Night]: "at night",
|
|
49
|
-
[types_1.EventTiming.Wake]: "after waking",
|
|
50
|
-
[types_1.EventTiming["After Sleep"]]: "after sleep",
|
|
51
|
-
[types_1.EventTiming.Immediate]: "immediately"
|
|
52
|
-
};
|
|
53
|
-
const DAY_NAMES = {
|
|
54
|
-
mon: "Monday",
|
|
55
|
-
tue: "Tuesday",
|
|
56
|
-
wed: "Wednesday",
|
|
57
|
-
thu: "Thursday",
|
|
58
|
-
fri: "Friday",
|
|
59
|
-
sat: "Saturday",
|
|
60
|
-
sun: "Sunday"
|
|
61
|
-
};
|
|
62
|
-
const EN_TIMES_PER_DAY = {
|
|
63
|
-
1: "once daily",
|
|
64
|
-
2: "twice daily",
|
|
65
|
-
3: "three times daily",
|
|
66
|
-
4: "four times daily"
|
|
67
|
-
};
|
|
68
|
-
const SLOWLY_QUALIFIER_CODE = "419443000";
|
|
69
|
-
const EMPTY_STOMACH_QUALIFIER_CODE = "717154004";
|
|
70
|
-
const DEFAULT_ROUTE_GRAMMAR = { verb: "Use" };
|
|
71
|
-
const ROUTE_GRAMMAR = {
|
|
72
|
-
[types_1.RouteCode["Oral route"]]: { verb: "Take", routePhrase: "orally" },
|
|
73
|
-
[types_1.RouteCode["Ophthalmic route"]]: {
|
|
74
|
-
verb: "Instill",
|
|
75
|
-
routePhrase: ({ hasSite }) => (hasSite ? undefined : "in the eye"),
|
|
76
|
-
sitePreposition: "in"
|
|
77
|
-
},
|
|
78
|
-
[types_1.RouteCode["Intravitreal route (qualifier value)"]]: {
|
|
79
|
-
verb: "Inject",
|
|
80
|
-
routePhrase: ({ hasSite }) => (hasSite ? undefined : "into the eye"),
|
|
81
|
-
sitePreposition: "into"
|
|
82
|
-
},
|
|
83
|
-
[types_1.RouteCode["Per rectum"]]: {
|
|
84
|
-
verb: "Use",
|
|
85
|
-
routePhrase: ({ hasSite }) => (hasSite ? undefined : "rectally"),
|
|
86
|
-
sitePreposition: "into"
|
|
87
|
-
},
|
|
88
|
-
[types_1.RouteCode["Per vagina"]]: {
|
|
89
|
-
verb: "Insert",
|
|
90
|
-
routePhrase: ({ hasSite }) => (hasSite ? undefined : "vaginally"),
|
|
91
|
-
sitePreposition: "into"
|
|
92
|
-
},
|
|
93
|
-
[types_1.RouteCode["Topical route"]]: {
|
|
94
|
-
verb: "Apply",
|
|
95
|
-
routePhrase: ({ hasSite }) => (hasSite ? undefined : "topically"),
|
|
96
|
-
sitePreposition: "to"
|
|
97
|
-
},
|
|
98
|
-
[types_1.RouteCode["Transdermal route"]]: {
|
|
99
|
-
verb: "Apply",
|
|
100
|
-
routePhrase: ({ hasSite }) => (hasSite ? undefined : "transdermally"),
|
|
101
|
-
sitePreposition: "to"
|
|
102
|
-
},
|
|
103
|
-
[types_1.RouteCode["Subcutaneous route"]]: {
|
|
104
|
-
verb: "Inject",
|
|
105
|
-
routePhrase: ({ hasSite }) => (hasSite ? undefined : "subcutaneously"),
|
|
106
|
-
sitePreposition: "into"
|
|
107
|
-
},
|
|
108
|
-
[types_1.RouteCode["Intramuscular route"]]: {
|
|
109
|
-
verb: "Inject",
|
|
110
|
-
routePhrase: ({ hasSite }) => (hasSite ? undefined : "intramuscularly"),
|
|
111
|
-
sitePreposition: "into"
|
|
112
|
-
},
|
|
113
|
-
[types_1.RouteCode["Intravenous route"]]: {
|
|
114
|
-
verb: "Inject",
|
|
115
|
-
routePhrase: ({ hasSite }) => (hasSite ? undefined : "intravenously"),
|
|
116
|
-
sitePreposition: "into"
|
|
117
|
-
},
|
|
118
|
-
[types_1.RouteCode["Nasal route"]]: {
|
|
119
|
-
verb: "Use",
|
|
120
|
-
routePhrase: ({ hasSite }) => (hasSite ? undefined : "via nasal route"),
|
|
121
|
-
sitePreposition: "into"
|
|
122
|
-
},
|
|
123
|
-
[types_1.RouteCode["Respiratory tract route (qualifier value)"]]: {
|
|
124
|
-
verb: "Use",
|
|
125
|
-
routePhrase: ({ hasSite }) => (hasSite ? undefined : "via inhalation"),
|
|
126
|
-
sitePreposition: "into"
|
|
127
|
-
}
|
|
128
|
-
};
|
|
129
|
-
function scheduleOf(clause) {
|
|
130
|
-
var _a;
|
|
131
|
-
return (_a = clause.schedule) !== null && _a !== void 0 ? _a : {};
|
|
132
|
-
}
|
|
133
|
-
function grammarFromRouteText(text) {
|
|
134
|
-
if (!text) {
|
|
135
|
-
return undefined;
|
|
136
|
-
}
|
|
137
|
-
const normalized = text.trim().toLowerCase();
|
|
138
|
-
if (!normalized) {
|
|
139
|
-
return undefined;
|
|
140
|
-
}
|
|
141
|
-
if (normalized.includes("mouth") || normalized.includes("oral")) {
|
|
142
|
-
return ROUTE_GRAMMAR[types_1.RouteCode["Oral route"]];
|
|
143
|
-
}
|
|
144
|
-
if (normalized.includes("ophthalm")) {
|
|
145
|
-
return ROUTE_GRAMMAR[types_1.RouteCode["Ophthalmic route"]];
|
|
146
|
-
}
|
|
147
|
-
if (normalized.includes("intravitreal")) {
|
|
148
|
-
return ROUTE_GRAMMAR[types_1.RouteCode["Intravitreal route (qualifier value)"]];
|
|
149
|
-
}
|
|
150
|
-
if (normalized.includes("topical")) {
|
|
151
|
-
return ROUTE_GRAMMAR[types_1.RouteCode["Topical route"]];
|
|
152
|
-
}
|
|
153
|
-
if (normalized.includes("transdermal")) {
|
|
154
|
-
return ROUTE_GRAMMAR[types_1.RouteCode["Transdermal route"]];
|
|
155
|
-
}
|
|
156
|
-
if (normalized.includes("subcutaneous") || normalized === "sc" || normalized === "sq") {
|
|
157
|
-
return ROUTE_GRAMMAR[types_1.RouteCode["Subcutaneous route"]];
|
|
158
|
-
}
|
|
159
|
-
if (normalized.includes("intramuscular") || normalized === "im") {
|
|
160
|
-
return ROUTE_GRAMMAR[types_1.RouteCode["Intramuscular route"]];
|
|
161
|
-
}
|
|
162
|
-
if (normalized.includes("intravenous") || normalized === "iv") {
|
|
163
|
-
return ROUTE_GRAMMAR[types_1.RouteCode["Intravenous route"]];
|
|
164
|
-
}
|
|
165
|
-
if (normalized.includes("rectal") || normalized.includes("rectum")) {
|
|
166
|
-
return ROUTE_GRAMMAR[types_1.RouteCode["Per rectum"]];
|
|
167
|
-
}
|
|
168
|
-
if (normalized.includes("vagin")) {
|
|
169
|
-
return ROUTE_GRAMMAR[types_1.RouteCode["Per vagina"]];
|
|
170
|
-
}
|
|
171
|
-
if (normalized.includes("nasal")) {
|
|
172
|
-
return ROUTE_GRAMMAR[types_1.RouteCode["Nasal route"]];
|
|
173
|
-
}
|
|
174
|
-
if (normalized.includes("inhal")) {
|
|
175
|
-
return ROUTE_GRAMMAR[types_1.RouteCode["Respiratory tract route (qualifier value)"]];
|
|
176
|
-
}
|
|
177
|
-
return undefined;
|
|
178
|
-
}
|
|
179
|
-
function resolveRouteGrammar(clause) {
|
|
180
|
-
var _a, _b, _c, _d;
|
|
181
|
-
const routeCode = (_a = clause.route) === null || _a === void 0 ? void 0 : _a.code;
|
|
182
|
-
if (routeCode && ROUTE_GRAMMAR[routeCode]) {
|
|
183
|
-
return (_b = ROUTE_GRAMMAR[routeCode]) !== null && _b !== void 0 ? _b : DEFAULT_ROUTE_GRAMMAR;
|
|
184
|
-
}
|
|
185
|
-
return (_d = grammarFromRouteText((_c = clause.route) === null || _c === void 0 ? void 0 : _c.text)) !== null && _d !== void 0 ? _d : DEFAULT_ROUTE_GRAMMAR;
|
|
186
|
-
}
|
|
187
|
-
function resolveMethodVerb(clause, grammar) {
|
|
188
|
-
var _a, _b;
|
|
189
|
-
const methodText = (_b = (_a = clause.method) === null || _a === void 0 ? void 0 : _a.text) === null || _b === void 0 ? void 0 : _b.trim();
|
|
190
|
-
if (methodText) {
|
|
191
|
-
return methodText;
|
|
192
|
-
}
|
|
193
|
-
return grammar.verb;
|
|
194
|
-
}
|
|
195
|
-
function pluralize(unit, value) {
|
|
196
|
-
if (Math.abs(value) === 1) {
|
|
197
|
-
switch (unit) {
|
|
198
|
-
case "tab":
|
|
199
|
-
return "tablet";
|
|
200
|
-
case "cap":
|
|
201
|
-
return "capsule";
|
|
202
|
-
default:
|
|
203
|
-
return unit;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
if (unit.endsWith(" ribbon")) {
|
|
207
|
-
return unit;
|
|
208
|
-
}
|
|
209
|
-
switch (unit) {
|
|
210
|
-
case "tab":
|
|
211
|
-
case "tablet":
|
|
212
|
-
return "tablets";
|
|
213
|
-
case "cap":
|
|
214
|
-
case "capsule":
|
|
215
|
-
return "capsules";
|
|
216
|
-
case "mL":
|
|
217
|
-
case "mg":
|
|
218
|
-
return unit;
|
|
219
|
-
case "puff":
|
|
220
|
-
return "puffs";
|
|
221
|
-
case "patch":
|
|
222
|
-
return "patches";
|
|
223
|
-
case "drop":
|
|
224
|
-
return "drops";
|
|
225
|
-
case "suppository":
|
|
226
|
-
return "suppositories";
|
|
227
|
-
case "pump":
|
|
228
|
-
return "pumps";
|
|
229
|
-
case "squeeze":
|
|
230
|
-
return "squeezes";
|
|
231
|
-
case "applicatorful":
|
|
232
|
-
return "applicatorfuls";
|
|
233
|
-
case "capful":
|
|
234
|
-
return "capfuls";
|
|
235
|
-
case "scoop":
|
|
236
|
-
return "scoops";
|
|
237
|
-
case "application":
|
|
238
|
-
return "applications";
|
|
239
|
-
case "fingertip unit":
|
|
240
|
-
return "fingertip units";
|
|
241
|
-
case "finger length":
|
|
242
|
-
return "finger lengths";
|
|
243
|
-
default:
|
|
244
|
-
return unit;
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
function formatPatientInstructionSentence(text) {
|
|
248
|
-
const trimmed = text === null || text === void 0 ? void 0 : text.trim();
|
|
249
|
-
if (!trimmed) {
|
|
250
|
-
return undefined;
|
|
251
|
-
}
|
|
252
|
-
const sentence = /^[.!?]$/.test(trimmed.slice(-1)) ? trimmed : `${trimmed}.`;
|
|
253
|
-
return sentence.charAt(0).toUpperCase() + sentence.slice(1);
|
|
254
|
-
}
|
|
255
|
-
function describeFrequency(schedule) {
|
|
256
|
-
const frequency = schedule === null || schedule === void 0 ? void 0 : schedule.frequency;
|
|
257
|
-
const frequencyMax = schedule === null || schedule === void 0 ? void 0 : schedule.frequencyMax;
|
|
258
|
-
const period = schedule === null || schedule === void 0 ? void 0 : schedule.period;
|
|
259
|
-
const periodMax = schedule === null || schedule === void 0 ? void 0 : schedule.periodMax;
|
|
260
|
-
const periodUnit = schedule === null || schedule === void 0 ? void 0 : schedule.periodUnit;
|
|
261
|
-
const timingCode = schedule === null || schedule === void 0 ? void 0 : schedule.timingCode;
|
|
262
|
-
if (frequency !== undefined &&
|
|
263
|
-
frequencyMax !== undefined &&
|
|
264
|
-
periodUnit === types_1.FhirPeriodUnit.Day &&
|
|
265
|
-
(!period || period === 1)) {
|
|
266
|
-
if (frequency === 1 && frequencyMax === 1) {
|
|
267
|
-
return "once daily";
|
|
268
|
-
}
|
|
269
|
-
if (frequency === 1 && frequencyMax === 2) {
|
|
270
|
-
return "one to two times daily";
|
|
271
|
-
}
|
|
272
|
-
return `${stripTrailingZero(frequency)} to ${stripTrailingZero(frequencyMax)} times daily`;
|
|
273
|
-
}
|
|
274
|
-
if (frequency && periodUnit === types_1.FhirPeriodUnit.Day && (!period || period === 1)) {
|
|
275
|
-
const dailyText = EN_TIMES_PER_DAY[frequency];
|
|
276
|
-
if (dailyText) {
|
|
277
|
-
return dailyText;
|
|
278
|
-
}
|
|
279
|
-
return `${stripTrailingZero(frequency)} times daily`;
|
|
280
|
-
}
|
|
281
|
-
if (periodUnit === types_1.FhirPeriodUnit.Minute && period) {
|
|
282
|
-
if (periodMax && periodMax !== period) {
|
|
283
|
-
return `every ${stripTrailingZero(period)} to ${stripTrailingZero(periodMax)} minutes`;
|
|
284
|
-
}
|
|
285
|
-
return `every ${stripTrailingZero(period)} minute${period === 1 ? "" : "s"}`;
|
|
286
|
-
}
|
|
287
|
-
if (periodUnit === types_1.FhirPeriodUnit.Hour && period) {
|
|
288
|
-
if (periodMax && periodMax !== period) {
|
|
289
|
-
return `every ${stripTrailingZero(period)} to ${stripTrailingZero(periodMax)} hours`;
|
|
290
|
-
}
|
|
291
|
-
return `every ${stripTrailingZero(period)} hour${period === 1 ? "" : "s"}`;
|
|
292
|
-
}
|
|
293
|
-
if (periodUnit === types_1.FhirPeriodUnit.Day && period && period !== 1) {
|
|
294
|
-
if (period === 2 && (!periodMax || periodMax === 2)) {
|
|
295
|
-
return "every other day";
|
|
296
|
-
}
|
|
297
|
-
if (periodMax && periodMax !== period) {
|
|
298
|
-
return `every ${stripTrailingZero(period)} to ${stripTrailingZero(periodMax)} days`;
|
|
299
|
-
}
|
|
300
|
-
return `every ${stripTrailingZero(period)} days`;
|
|
301
|
-
}
|
|
302
|
-
if (periodUnit === types_1.FhirPeriodUnit.Week && period) {
|
|
303
|
-
if (period === 1 && (!periodMax || periodMax === 1)) {
|
|
304
|
-
return "once weekly";
|
|
305
|
-
}
|
|
306
|
-
if (periodMax && periodMax !== period) {
|
|
307
|
-
return `every ${stripTrailingZero(period)} to ${stripTrailingZero(periodMax)} weeks`;
|
|
308
|
-
}
|
|
309
|
-
return `every ${stripTrailingZero(period)} weeks`;
|
|
310
|
-
}
|
|
311
|
-
if (periodUnit === types_1.FhirPeriodUnit.Month && period) {
|
|
312
|
-
if (period === 1 && (!periodMax || periodMax === 1)) {
|
|
313
|
-
return "once monthly";
|
|
314
|
-
}
|
|
315
|
-
if (periodMax && periodMax !== period) {
|
|
316
|
-
return `every ${stripTrailingZero(period)} to ${stripTrailingZero(periodMax)} months`;
|
|
317
|
-
}
|
|
318
|
-
return `every ${stripTrailingZero(period)} months`;
|
|
319
|
-
}
|
|
320
|
-
if (periodUnit === types_1.FhirPeriodUnit.Year && period) {
|
|
321
|
-
if (period === 1 && (!periodMax || periodMax === 1)) {
|
|
322
|
-
return "once yearly";
|
|
323
|
-
}
|
|
324
|
-
if (periodMax && periodMax !== period) {
|
|
325
|
-
return `every ${stripTrailingZero(period)} to ${stripTrailingZero(periodMax)} years`;
|
|
326
|
-
}
|
|
327
|
-
return `every ${stripTrailingZero(period)} years`;
|
|
328
|
-
}
|
|
329
|
-
if (timingCode) {
|
|
330
|
-
if (timingCode === "WK") {
|
|
331
|
-
return "once weekly";
|
|
332
|
-
}
|
|
333
|
-
if (timingCode === "MO") {
|
|
334
|
-
return "once monthly";
|
|
335
|
-
}
|
|
336
|
-
const map = {
|
|
337
|
-
BID: "twice daily",
|
|
338
|
-
TID: "three times daily",
|
|
339
|
-
QID: "four times daily",
|
|
340
|
-
QD: "once daily",
|
|
341
|
-
QOD: "every other day",
|
|
342
|
-
Q6H: "every 6 hours",
|
|
343
|
-
Q8H: "every 8 hours"
|
|
344
|
-
};
|
|
345
|
-
if (map[timingCode]) {
|
|
346
|
-
return map[timingCode];
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
if (frequency && periodUnit === undefined && period === undefined) {
|
|
350
|
-
if (frequency === 1) {
|
|
351
|
-
return "once";
|
|
352
|
-
}
|
|
353
|
-
return `${stripTrailingZero(frequency)} times`;
|
|
354
|
-
}
|
|
355
|
-
return undefined;
|
|
356
|
-
}
|
|
357
|
-
function describeFrequencyCount(count) {
|
|
358
|
-
if (!count || count <= 0) {
|
|
359
|
-
return undefined;
|
|
360
|
-
}
|
|
361
|
-
const dailyText = EN_TIMES_PER_DAY[count];
|
|
362
|
-
if (dailyText) {
|
|
363
|
-
return dailyText;
|
|
364
|
-
}
|
|
365
|
-
return `${stripTrailingZero(count)} times daily`;
|
|
366
|
-
}
|
|
367
|
-
function describeStandaloneOccurrenceCount(schedule) {
|
|
368
|
-
var _a, _b, _c;
|
|
369
|
-
const count = schedule === null || schedule === void 0 ? void 0 : schedule.count;
|
|
370
|
-
if (!count || count <= 0) {
|
|
371
|
-
return undefined;
|
|
372
|
-
}
|
|
373
|
-
if ((schedule === null || schedule === void 0 ? void 0 : schedule.frequency) !== undefined ||
|
|
374
|
-
(schedule === null || schedule === void 0 ? void 0 : schedule.frequencyMax) !== undefined ||
|
|
375
|
-
(schedule === null || schedule === void 0 ? void 0 : schedule.period) !== undefined ||
|
|
376
|
-
(schedule === null || schedule === void 0 ? void 0 : schedule.periodMax) !== undefined ||
|
|
377
|
-
(schedule === null || schedule === void 0 ? void 0 : schedule.periodUnit) !== undefined ||
|
|
378
|
-
((_a = schedule === null || schedule === void 0 ? void 0 : schedule.dayOfWeek) === null || _a === void 0 ? void 0 : _a.length) ||
|
|
379
|
-
((_b = schedule === null || schedule === void 0 ? void 0 : schedule.when) === null || _b === void 0 ? void 0 : _b.length) ||
|
|
380
|
-
((_c = schedule === null || schedule === void 0 ? void 0 : schedule.timeOfDay) === null || _c === void 0 ? void 0 : _c.length) ||
|
|
381
|
-
(schedule === null || schedule === void 0 ? void 0 : schedule.duration) !== undefined ||
|
|
382
|
-
(schedule === null || schedule === void 0 ? void 0 : schedule.durationMax) !== undefined ||
|
|
383
|
-
(schedule === null || schedule === void 0 ? void 0 : schedule.durationUnit) !== undefined ||
|
|
384
|
-
(schedule === null || schedule === void 0 ? void 0 : schedule.timingCode)) {
|
|
385
|
-
return undefined;
|
|
386
|
-
}
|
|
387
|
-
switch (count) {
|
|
388
|
-
case 1:
|
|
389
|
-
return "once";
|
|
390
|
-
case 2:
|
|
391
|
-
return "twice";
|
|
392
|
-
default:
|
|
393
|
-
return `${stripTrailingZero(count)} times`;
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
function formatDoseShort(dose) {
|
|
397
|
-
if (!dose) {
|
|
398
|
-
return undefined;
|
|
399
|
-
}
|
|
400
|
-
if (dose.range) {
|
|
401
|
-
if (dose.range.low !== undefined && dose.range.high !== undefined) {
|
|
402
|
-
const base = `${stripTrailingZero(dose.range.low)}-${stripTrailingZero(dose.range.high)}`;
|
|
403
|
-
if (dose.unit) {
|
|
404
|
-
return `${base} ${dose.unit}`;
|
|
405
|
-
}
|
|
406
|
-
return base;
|
|
407
|
-
}
|
|
408
|
-
if (dose.range.low !== undefined) {
|
|
409
|
-
const base = `>=${stripTrailingZero(dose.range.low)}`;
|
|
410
|
-
if (dose.unit) {
|
|
411
|
-
return `${base} ${dose.unit}`;
|
|
412
|
-
}
|
|
413
|
-
return base;
|
|
414
|
-
}
|
|
415
|
-
if (dose.range.high !== undefined) {
|
|
416
|
-
const base = `<=${stripTrailingZero(dose.range.high)}`;
|
|
417
|
-
if (dose.unit) {
|
|
418
|
-
return `${base} ${dose.unit}`;
|
|
419
|
-
}
|
|
420
|
-
return base;
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
if (dose.value !== undefined) {
|
|
424
|
-
if (dose.unit) {
|
|
425
|
-
return `${stripTrailingZero(dose.value)} ${dose.unit}`;
|
|
426
|
-
}
|
|
427
|
-
return `${stripTrailingZero(dose.value)}`;
|
|
428
|
-
}
|
|
429
|
-
return undefined;
|
|
430
|
-
}
|
|
431
|
-
function formatDoseLong(dose) {
|
|
432
|
-
if (!dose) {
|
|
433
|
-
return undefined;
|
|
434
|
-
}
|
|
435
|
-
if (dose.range) {
|
|
436
|
-
if (dose.range.low !== undefined && dose.range.high !== undefined) {
|
|
437
|
-
if (dose.unit) {
|
|
438
|
-
return `${stripTrailingZero(dose.range.low)} to ${stripTrailingZero(dose.range.high)} ${pluralize(dose.unit, dose.range.high)}`;
|
|
439
|
-
}
|
|
440
|
-
return `${stripTrailingZero(dose.range.low)} to ${stripTrailingZero(dose.range.high)}`;
|
|
441
|
-
}
|
|
442
|
-
if (dose.range.low !== undefined) {
|
|
443
|
-
if (dose.unit) {
|
|
444
|
-
return `at least ${stripTrailingZero(dose.range.low)} ${pluralize(dose.unit, dose.range.low)}`;
|
|
445
|
-
}
|
|
446
|
-
return `at least ${stripTrailingZero(dose.range.low)}`;
|
|
447
|
-
}
|
|
448
|
-
if (dose.range.high !== undefined) {
|
|
449
|
-
if (dose.unit) {
|
|
450
|
-
return `up to ${stripTrailingZero(dose.range.high)} ${pluralize(dose.unit, dose.range.high)}`;
|
|
451
|
-
}
|
|
452
|
-
return `up to ${stripTrailingZero(dose.range.high)}`;
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
if (dose.value !== undefined) {
|
|
456
|
-
if (dose.unit) {
|
|
457
|
-
return `${stripTrailingZero(dose.value)} ${pluralize(dose.unit, dose.value)}`;
|
|
458
|
-
}
|
|
459
|
-
return `${stripTrailingZero(dose.value)}`;
|
|
460
|
-
}
|
|
461
|
-
return undefined;
|
|
462
|
-
}
|
|
463
|
-
function summarizeMealTimingGroup(group) {
|
|
464
|
-
let relationText = "with";
|
|
465
|
-
if (group.relation === "before") {
|
|
466
|
-
relationText = "before";
|
|
467
|
-
}
|
|
468
|
-
else if (group.relation === "after") {
|
|
469
|
-
relationText = "after";
|
|
470
|
-
}
|
|
471
|
-
return `${relationText} ${joinWithAnd(group.meals)}`;
|
|
472
|
-
}
|
|
473
|
-
function collectWhenPhrases(schedule, options) {
|
|
474
|
-
var _a, _b, _c;
|
|
475
|
-
const when = (_a = schedule === null || schedule === void 0 ? void 0 : schedule.when) !== null && _a !== void 0 ? _a : [];
|
|
476
|
-
if (!when.length) {
|
|
477
|
-
return [];
|
|
478
|
-
}
|
|
479
|
-
const unique = [];
|
|
480
|
-
const seen = new Set();
|
|
481
|
-
let hasSpecificAfter = false;
|
|
482
|
-
let hasSpecificBefore = false;
|
|
483
|
-
let hasSpecificWith = false;
|
|
484
|
-
for (const code of when) {
|
|
485
|
-
if (!seen.has(code)) {
|
|
486
|
-
seen.add(code);
|
|
487
|
-
unique.push(code);
|
|
488
|
-
if (code === types_1.EventTiming["After Breakfast"] ||
|
|
489
|
-
code === types_1.EventTiming["After Lunch"] ||
|
|
490
|
-
code === types_1.EventTiming["After Dinner"]) {
|
|
491
|
-
hasSpecificAfter = true;
|
|
492
|
-
}
|
|
493
|
-
if (code === types_1.EventTiming["Before Breakfast"] ||
|
|
494
|
-
code === types_1.EventTiming["Before Lunch"] ||
|
|
495
|
-
code === types_1.EventTiming["Before Dinner"]) {
|
|
496
|
-
hasSpecificBefore = true;
|
|
497
|
-
}
|
|
498
|
-
if (code === types_1.EventTiming.Breakfast || code === types_1.EventTiming.Lunch || code === types_1.EventTiming.Dinner) {
|
|
499
|
-
hasSpecificWith = true;
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
const filtered = [];
|
|
504
|
-
for (const code of unique) {
|
|
505
|
-
if (code === types_1.EventTiming["After Meal"] && hasSpecificAfter) {
|
|
506
|
-
continue;
|
|
507
|
-
}
|
|
508
|
-
if (code === types_1.EventTiming["Before Meal"] && hasSpecificBefore) {
|
|
509
|
-
continue;
|
|
510
|
-
}
|
|
511
|
-
if (code === types_1.EventTiming.Meal && hasSpecificWith) {
|
|
512
|
-
continue;
|
|
513
|
-
}
|
|
514
|
-
filtered.push(code);
|
|
515
|
-
}
|
|
516
|
-
const mealGroup = (0, timing_summary_1.getMealTimingGroup)(filtered, options);
|
|
517
|
-
if (!mealGroup) {
|
|
518
|
-
const phrases = [];
|
|
519
|
-
for (const code of filtered) {
|
|
520
|
-
const text = (_b = WHEN_TEXT[code]) !== null && _b !== void 0 ? _b : code;
|
|
521
|
-
if (text) {
|
|
522
|
-
phrases.push(text);
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
return phrases;
|
|
526
|
-
}
|
|
527
|
-
const groupedCodes = new Set(mealGroup.codes);
|
|
528
|
-
const phrases = [];
|
|
529
|
-
let insertedGroup = false;
|
|
530
|
-
for (const code of filtered) {
|
|
531
|
-
if (groupedCodes.has(code)) {
|
|
532
|
-
if (!insertedGroup) {
|
|
533
|
-
phrases.push(summarizeMealTimingGroup(mealGroup));
|
|
534
|
-
insertedGroup = true;
|
|
535
|
-
}
|
|
536
|
-
continue;
|
|
537
|
-
}
|
|
538
|
-
const text = (_c = WHEN_TEXT[code]) !== null && _c !== void 0 ? _c : code;
|
|
539
|
-
if (text) {
|
|
540
|
-
phrases.push(text);
|
|
541
|
-
}
|
|
542
|
-
}
|
|
543
|
-
return phrases;
|
|
544
|
-
}
|
|
545
|
-
function joinWithAnd(parts) {
|
|
546
|
-
if (!parts.length) {
|
|
547
|
-
return "";
|
|
548
|
-
}
|
|
549
|
-
if (parts.length === 1) {
|
|
550
|
-
return parts[0];
|
|
551
|
-
}
|
|
552
|
-
if (parts.length === 2) {
|
|
553
|
-
return `${parts[0]} and ${parts[1]}`;
|
|
554
|
-
}
|
|
555
|
-
return `${parts.slice(0, -1).join(", ")} and ${parts[parts.length - 1]}`;
|
|
556
|
-
}
|
|
557
|
-
function combineFrequencyAndEvents(frequency, events) {
|
|
558
|
-
if (!frequency) {
|
|
559
|
-
if (!events.length) {
|
|
560
|
-
return {};
|
|
561
|
-
}
|
|
562
|
-
return { event: joinWithAnd(events) };
|
|
563
|
-
}
|
|
564
|
-
if (!events.length) {
|
|
565
|
-
return { frequency };
|
|
566
|
-
}
|
|
567
|
-
if (events.length === 1 && events[0] === "at bedtime") {
|
|
568
|
-
const lowerFrequency = frequency.toLowerCase();
|
|
569
|
-
if (lowerFrequency === "twice daily" ||
|
|
570
|
-
lowerFrequency === "three times daily" ||
|
|
571
|
-
lowerFrequency === "four times daily") {
|
|
572
|
-
return { frequency: `${frequency} and ${events[0]}` };
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
return { frequency, event: joinWithAnd(events) };
|
|
576
|
-
}
|
|
577
|
-
function buildRoutePhrase(clause, grammar, hasSite) {
|
|
578
|
-
var _a, _b;
|
|
579
|
-
if (typeof grammar.routePhrase === "function") {
|
|
580
|
-
return grammar.routePhrase({ hasSite, clause });
|
|
581
|
-
}
|
|
582
|
-
if (typeof grammar.routePhrase === "string") {
|
|
583
|
-
return grammar.routePhrase;
|
|
584
|
-
}
|
|
585
|
-
const text = (_b = (_a = clause.route) === null || _a === void 0 ? void 0 : _a.text) === null || _b === void 0 ? void 0 : _b.trim();
|
|
586
|
-
if (!text) {
|
|
587
|
-
return undefined;
|
|
588
|
-
}
|
|
589
|
-
const normalized = text.toLowerCase();
|
|
590
|
-
if (normalized.startsWith("by ") || normalized.startsWith("per ") || normalized.startsWith("via ")) {
|
|
591
|
-
return text;
|
|
592
|
-
}
|
|
593
|
-
if (normalized === "oral") {
|
|
594
|
-
return "orally";
|
|
595
|
-
}
|
|
596
|
-
if (normalized === "intravenous") {
|
|
597
|
-
return "intravenously";
|
|
598
|
-
}
|
|
599
|
-
if (normalized === "intramuscular") {
|
|
600
|
-
return "intramuscularly";
|
|
601
|
-
}
|
|
602
|
-
if (normalized === "subcutaneous") {
|
|
603
|
-
return "subcutaneously";
|
|
604
|
-
}
|
|
605
|
-
if (normalized === "topical") {
|
|
606
|
-
return "topically";
|
|
607
|
-
}
|
|
608
|
-
if (normalized === "transdermal") {
|
|
609
|
-
return "transdermally";
|
|
610
|
-
}
|
|
611
|
-
if (normalized === "intranasal" || normalized === "nasal") {
|
|
612
|
-
return "via nasal route";
|
|
613
|
-
}
|
|
614
|
-
if (normalized.includes("inhal")) {
|
|
615
|
-
return "via inhalation";
|
|
616
|
-
}
|
|
617
|
-
return `via ${text}`;
|
|
618
|
-
}
|
|
619
|
-
function formatSite(clause, grammar) {
|
|
620
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
621
|
-
let text = (_b = (_a = clause.site) === null || _a === void 0 ? void 0 : _a.text) === null || _b === void 0 ? void 0 : _b.trim();
|
|
622
|
-
if (!text) {
|
|
623
|
-
const display = (_e = (_d = (_c = clause.site) === null || _c === void 0 ? void 0 : _c.coding) === null || _d === void 0 ? void 0 : _d.display) === null || _e === void 0 ? void 0 : _e.trim();
|
|
624
|
-
if (display) {
|
|
625
|
-
text = display.charAt(0).toLowerCase() + display.slice(1);
|
|
626
|
-
}
|
|
627
|
-
else {
|
|
628
|
-
text = (_h = (_g = (_f = clause.site) === null || _f === void 0 ? void 0 : _f.coding) === null || _g === void 0 ? void 0 : _g.code) === null || _h === void 0 ? void 0 : _h.trim();
|
|
629
|
-
}
|
|
630
|
-
}
|
|
631
|
-
if (!text) {
|
|
632
|
-
return undefined;
|
|
633
|
-
}
|
|
634
|
-
const lower = text.toLowerCase();
|
|
635
|
-
const routeText = (_k = (_j = clause.route) === null || _j === void 0 ? void 0 : _j.text) === null || _k === void 0 ? void 0 : _k.trim().toLowerCase();
|
|
636
|
-
const isRectalRoute = ((_l = clause.route) === null || _l === void 0 ? void 0 : _l.code) === types_1.RouteCode["Per rectum"] ||
|
|
637
|
-
routeText === "rectum" ||
|
|
638
|
-
routeText === "rectal";
|
|
639
|
-
const isVaginalRoute = ((_m = clause.route) === null || _m === void 0 ? void 0 : _m.code) === types_1.RouteCode["Per vagina"] ||
|
|
640
|
-
routeText === "vagina" ||
|
|
641
|
-
routeText === "vaginal";
|
|
642
|
-
if (isRectalRoute && (lower === "rectum" || lower === "rectal")) {
|
|
643
|
-
return undefined;
|
|
644
|
-
}
|
|
645
|
-
if (isVaginalRoute && (lower === "vagina" || lower === "vaginal")) {
|
|
646
|
-
return undefined;
|
|
647
|
-
}
|
|
648
|
-
let preposition = grammar.sitePreposition;
|
|
649
|
-
if (!preposition) {
|
|
650
|
-
if (lower.includes("eye")) {
|
|
651
|
-
preposition = "in";
|
|
652
|
-
}
|
|
653
|
-
else if (lower.includes("nostril") || lower.includes("nose")) {
|
|
654
|
-
preposition = "into";
|
|
655
|
-
}
|
|
656
|
-
else if (lower.includes("lung") || lower.includes("airway") || lower.includes("bronch")) {
|
|
657
|
-
preposition = "into";
|
|
658
|
-
}
|
|
659
|
-
else if (lower.includes("ear")) {
|
|
660
|
-
preposition = "in";
|
|
661
|
-
}
|
|
662
|
-
else if (/(skin|head|temple|arm|leg|thigh|abdomen|shoulder|elbow|wrist|ankle|knee|hand|foot|cheek|forearm|back|chest|breast|axilla|armpit|groin|lip|buttock|hip|face|hair|scalp|forehead|eyelid|chin|neck)/.test(lower)) {
|
|
663
|
-
preposition = "to";
|
|
664
|
-
}
|
|
665
|
-
else {
|
|
666
|
-
preposition = "at";
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
const noun = formatSiteNoun(text, preposition);
|
|
670
|
-
return `${preposition} ${noun}`.trim();
|
|
671
|
-
}
|
|
672
|
-
function formatSiteNoun(site, preposition) {
|
|
673
|
-
const trimmed = site.trim();
|
|
674
|
-
const lower = trimmed.toLowerCase();
|
|
675
|
-
const skipArticlePrefixes = ["the ", "both ", "each ", "either ", "every ", "all ", "bilateral "];
|
|
676
|
-
for (const prefix of skipArticlePrefixes) {
|
|
677
|
-
if (lower.startsWith(prefix)) {
|
|
678
|
-
return trimmed;
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
const needsArticle = /^(left|right|upper|lower|inner|outer|mid|middle|posterior|anterior|proximal|distal|medial|lateral|dorsal|ventral)\b/.test(lower);
|
|
682
|
-
if (needsArticle || preposition === "at") {
|
|
683
|
-
return `the ${trimmed}`;
|
|
684
|
-
}
|
|
685
|
-
return `the ${trimmed}`;
|
|
686
|
-
}
|
|
687
|
-
function describeDayOfWeek(schedule) {
|
|
688
|
-
var _a, _b;
|
|
689
|
-
const dayOfWeek = (_a = schedule === null || schedule === void 0 ? void 0 : schedule.dayOfWeek) !== null && _a !== void 0 ? _a : [];
|
|
690
|
-
if (!dayOfWeek.length) {
|
|
691
|
-
return undefined;
|
|
692
|
-
}
|
|
693
|
-
const days = [];
|
|
694
|
-
for (const day of dayOfWeek) {
|
|
695
|
-
days.push((_b = DAY_NAMES[day]) !== null && _b !== void 0 ? _b : day);
|
|
696
|
-
}
|
|
697
|
-
return days.length ? `on ${joinWithAnd(days)}` : undefined;
|
|
698
|
-
}
|
|
699
|
-
function formatDurationShort(schedule) {
|
|
700
|
-
if (schedule.duration === undefined || !schedule.durationUnit) {
|
|
701
|
-
return undefined;
|
|
702
|
-
}
|
|
703
|
-
const base = stripTrailingZero(schedule.duration);
|
|
704
|
-
const qualifier = schedule.durationMax !== undefined && schedule.durationMax !== schedule.duration
|
|
705
|
-
? `${base}-${stripTrailingZero(schedule.durationMax)}`
|
|
706
|
-
: base;
|
|
707
|
-
return `x${qualifier}${schedule.durationUnit}`;
|
|
708
|
-
}
|
|
709
|
-
function describeDuration(schedule) {
|
|
710
|
-
if (!schedule || schedule.duration === undefined || !schedule.durationUnit) {
|
|
711
|
-
return undefined;
|
|
712
|
-
}
|
|
713
|
-
const unit = schedule.durationUnit;
|
|
714
|
-
const label = (value) => {
|
|
715
|
-
switch (unit) {
|
|
716
|
-
case types_1.FhirPeriodUnit.Minute:
|
|
717
|
-
return value === 1 ? "minute" : "minutes";
|
|
718
|
-
case types_1.FhirPeriodUnit.Hour:
|
|
719
|
-
return value === 1 ? "hour" : "hours";
|
|
720
|
-
case types_1.FhirPeriodUnit.Day:
|
|
721
|
-
return value === 1 ? "day" : "days";
|
|
722
|
-
case types_1.FhirPeriodUnit.Week:
|
|
723
|
-
return value === 1 ? "week" : "weeks";
|
|
724
|
-
case types_1.FhirPeriodUnit.Month:
|
|
725
|
-
return value === 1 ? "month" : "months";
|
|
726
|
-
case types_1.FhirPeriodUnit.Year:
|
|
727
|
-
return value === 1 ? "year" : "years";
|
|
728
|
-
default:
|
|
729
|
-
return value === 1 ? "unit" : "units";
|
|
730
|
-
}
|
|
731
|
-
};
|
|
732
|
-
if (schedule.durationMax !== undefined && schedule.durationMax !== schedule.duration) {
|
|
733
|
-
return `for ${stripTrailingZero(schedule.duration)} to ${stripTrailingZero(schedule.durationMax)} ${label(schedule.durationMax)}`;
|
|
734
|
-
}
|
|
735
|
-
return `for ${stripTrailingZero(schedule.duration)} ${label(schedule.duration)}`;
|
|
736
|
-
}
|
|
737
|
-
function shouldUseGenericMedicationObject(clause) {
|
|
738
|
-
var _a, _b;
|
|
739
|
-
const methodText = (_b = (_a = clause.method) === null || _a === void 0 ? void 0 : _a.text) === null || _b === void 0 ? void 0 : _b.trim();
|
|
740
|
-
switch (methodText) {
|
|
741
|
-
case "Apply sunscreen":
|
|
742
|
-
case "Reapply sunscreen":
|
|
743
|
-
case "Use shampoo":
|
|
744
|
-
return false;
|
|
745
|
-
default:
|
|
746
|
-
return true;
|
|
747
|
-
}
|
|
748
|
-
}
|
|
749
|
-
function shouldSuppressRoutePhrase(clause, grammar, verb) {
|
|
750
|
-
var _a;
|
|
751
|
-
if (((_a = clause.route) === null || _a === void 0 ? void 0 : _a.code) !== types_1.RouteCode["Oral route"]) {
|
|
752
|
-
return false;
|
|
753
|
-
}
|
|
754
|
-
if (grammar.routePhrase !== "orally") {
|
|
755
|
-
return false;
|
|
756
|
-
}
|
|
757
|
-
switch (verb) {
|
|
758
|
-
case "Drink":
|
|
759
|
-
case "Swallow":
|
|
760
|
-
return true;
|
|
761
|
-
default:
|
|
762
|
-
return false;
|
|
763
|
-
}
|
|
764
|
-
}
|
|
765
|
-
function formatShort(clause) {
|
|
766
|
-
var _a, _b, _c, _d, _e, _f;
|
|
767
|
-
const schedule = scheduleOf(clause);
|
|
768
|
-
const parts = [];
|
|
769
|
-
const dosePart = formatDoseShort(clause.dose);
|
|
770
|
-
if (dosePart) {
|
|
771
|
-
parts.push(dosePart);
|
|
772
|
-
}
|
|
773
|
-
const routeCode = (_a = clause.route) === null || _a === void 0 ? void 0 : _a.code;
|
|
774
|
-
const routeText = (_b = clause.route) === null || _b === void 0 ? void 0 : _b.text;
|
|
775
|
-
if (routeCode) {
|
|
776
|
-
const short = ROUTE_SHORT[routeCode];
|
|
777
|
-
if (short) {
|
|
778
|
-
parts.push(short);
|
|
779
|
-
}
|
|
780
|
-
else if (routeText) {
|
|
781
|
-
parts.push(routeText);
|
|
782
|
-
}
|
|
783
|
-
}
|
|
784
|
-
else if (routeText) {
|
|
785
|
-
parts.push(routeText);
|
|
786
|
-
}
|
|
787
|
-
if (schedule.timingCode) {
|
|
788
|
-
parts.push(schedule.timingCode);
|
|
789
|
-
}
|
|
790
|
-
else if (schedule.frequency !== undefined &&
|
|
791
|
-
schedule.frequencyMax !== undefined &&
|
|
792
|
-
schedule.periodUnit === types_1.FhirPeriodUnit.Day &&
|
|
793
|
-
(!schedule.period || schedule.period === 1)) {
|
|
794
|
-
parts.push(`${stripTrailingZero(schedule.frequency)}-${stripTrailingZero(schedule.frequencyMax)}x/d`);
|
|
795
|
-
}
|
|
796
|
-
else if (schedule.frequency &&
|
|
797
|
-
schedule.periodUnit === types_1.FhirPeriodUnit.Day &&
|
|
798
|
-
(!schedule.period || schedule.period === 1)) {
|
|
799
|
-
parts.push(`${stripTrailingZero(schedule.frequency)}x/d`);
|
|
800
|
-
}
|
|
801
|
-
else if (schedule.period && schedule.periodUnit) {
|
|
802
|
-
const base = stripTrailingZero(schedule.period);
|
|
803
|
-
const qualifier = schedule.periodMax && schedule.periodMax !== schedule.period
|
|
804
|
-
? `${base}-${stripTrailingZero(schedule.periodMax)}`
|
|
805
|
-
: base;
|
|
806
|
-
parts.push(`Q${qualifier}${schedule.periodUnit.toUpperCase()}`);
|
|
807
|
-
}
|
|
808
|
-
if ((_c = schedule.when) === null || _c === void 0 ? void 0 : _c.length) {
|
|
809
|
-
parts.push(schedule.when.join(" "));
|
|
810
|
-
}
|
|
811
|
-
if ((_d = schedule.dayOfWeek) === null || _d === void 0 ? void 0 : _d.length) {
|
|
812
|
-
const days = [];
|
|
813
|
-
for (const day of schedule.dayOfWeek) {
|
|
814
|
-
days.push(day.charAt(0).toUpperCase() + day.slice(1, 3));
|
|
815
|
-
}
|
|
816
|
-
parts.push(days.join(","));
|
|
817
|
-
}
|
|
818
|
-
if ((_e = schedule.timeOfDay) === null || _e === void 0 ? void 0 : _e.length) {
|
|
819
|
-
const times = [];
|
|
820
|
-
for (const time of schedule.timeOfDay) {
|
|
821
|
-
times.push(time.slice(0, 5));
|
|
822
|
-
}
|
|
823
|
-
parts.push(times.join(","));
|
|
824
|
-
}
|
|
825
|
-
if (schedule.count !== undefined) {
|
|
826
|
-
parts.push(`x${stripTrailingZero(schedule.count)}`);
|
|
827
|
-
}
|
|
828
|
-
const durationShort = formatDurationShort(schedule);
|
|
829
|
-
if (durationShort) {
|
|
830
|
-
parts.push(durationShort);
|
|
831
|
-
}
|
|
832
|
-
if ((_f = clause.prn) === null || _f === void 0 ? void 0 : _f.enabled) {
|
|
833
|
-
const reason = (0, prn_1.getPreferredCanonicalPrnReasonText)(clause.prn.reason, clause.prn.reasons);
|
|
834
|
-
if (reason) {
|
|
835
|
-
parts.push(`PRN ${reason}`);
|
|
836
|
-
}
|
|
837
|
-
else {
|
|
838
|
-
parts.push("PRN");
|
|
839
|
-
}
|
|
840
|
-
}
|
|
841
|
-
return parts.filter(Boolean).join(" ");
|
|
842
|
-
}
|
|
843
|
-
function formatLong(clause, options) {
|
|
844
|
-
var _a, _b, _c, _d, _e, _f;
|
|
845
|
-
const schedule = scheduleOf(clause);
|
|
846
|
-
const grammar = resolveRouteGrammar(clause);
|
|
847
|
-
const verb = resolveMethodVerb(clause, grammar);
|
|
848
|
-
const explicitDosePart = formatDoseLong(clause.dose);
|
|
849
|
-
const dosePart = explicitDosePart !== null && explicitDosePart !== void 0 ? explicitDosePart : (shouldUseGenericMedicationObject(clause) ? "the medication" : undefined);
|
|
850
|
-
const sitePart = formatSite(clause, grammar);
|
|
851
|
-
const routePart = shouldSuppressRoutePhrase(clause, grammar, verb)
|
|
852
|
-
? undefined
|
|
853
|
-
: buildRoutePhrase(clause, grammar, Boolean(sitePart));
|
|
854
|
-
const standaloneOccurrenceCount = describeStandaloneOccurrenceCount(schedule);
|
|
855
|
-
const frequencyPart = (_b = (_a = describeFrequency(schedule)) !== null && _a !== void 0 ? _a : standaloneOccurrenceCount) !== null && _b !== void 0 ? _b : describeFrequencyCount((0, timing_summary_1.inferDailyOccurrenceCount)(schedule, options));
|
|
856
|
-
const eventParts = collectWhenPhrases(schedule, options);
|
|
857
|
-
if ((_c = schedule.timeOfDay) === null || _c === void 0 ? void 0 : _c.length) {
|
|
858
|
-
const timeStrings = [];
|
|
859
|
-
for (const time of schedule.timeOfDay) {
|
|
860
|
-
const parts = time.split(":");
|
|
861
|
-
const hours = Number(parts[0]);
|
|
862
|
-
const minutes = Number(parts[1]);
|
|
863
|
-
if (!Number.isFinite(hours) || !Number.isFinite(minutes)) {
|
|
864
|
-
continue;
|
|
865
|
-
}
|
|
866
|
-
const isAm = hours < 12;
|
|
867
|
-
const displayHours = hours % 12 || 12;
|
|
868
|
-
const displayMinutes = minutes < 10 ? `0${minutes}` : `${minutes}`;
|
|
869
|
-
timeStrings.push(`${displayHours}:${displayMinutes}${isAm ? " am" : " pm"}`);
|
|
870
|
-
}
|
|
871
|
-
if (timeStrings.length) {
|
|
872
|
-
eventParts.push(`at ${timeStrings.join(", ")}`);
|
|
873
|
-
}
|
|
874
|
-
}
|
|
875
|
-
const timing = combineFrequencyAndEvents(frequencyPart, eventParts);
|
|
876
|
-
const dayPart = describeDayOfWeek(schedule);
|
|
877
|
-
const countPart = schedule.count !== undefined && !standaloneOccurrenceCount
|
|
878
|
-
? `for ${stripTrailingZero(schedule.count)} ${schedule.count === 1 ? "dose" : "doses"}`
|
|
879
|
-
: undefined;
|
|
880
|
-
const durationPart = describeDuration(schedule);
|
|
881
|
-
const reason = (0, prn_1.getPreferredCanonicalPrnReasonText)((_d = clause.prn) === null || _d === void 0 ? void 0 : _d.reason, (_e = clause.prn) === null || _e === void 0 ? void 0 : _e.reasons);
|
|
882
|
-
const asNeededPart = ((_f = clause.prn) === null || _f === void 0 ? void 0 : _f.enabled) ? (reason ? `as needed for ${reason}` : "as needed") : undefined;
|
|
883
|
-
const segments = [];
|
|
884
|
-
if (dosePart) {
|
|
885
|
-
segments.push(dosePart);
|
|
886
|
-
}
|
|
887
|
-
if (routePart) {
|
|
888
|
-
segments.push(routePart);
|
|
889
|
-
}
|
|
890
|
-
if (timing.frequency) {
|
|
891
|
-
segments.push(timing.frequency);
|
|
892
|
-
}
|
|
893
|
-
if (timing.event) {
|
|
894
|
-
segments.push(timing.event);
|
|
895
|
-
}
|
|
896
|
-
if (dayPart) {
|
|
897
|
-
segments.push(dayPart);
|
|
898
|
-
}
|
|
899
|
-
if (countPart) {
|
|
900
|
-
segments.push(countPart);
|
|
901
|
-
}
|
|
902
|
-
if (durationPart) {
|
|
903
|
-
segments.push(durationPart);
|
|
904
|
-
}
|
|
905
|
-
if (asNeededPart) {
|
|
906
|
-
segments.push(asNeededPart);
|
|
907
|
-
}
|
|
908
|
-
if (sitePart) {
|
|
909
|
-
segments.push(sitePart);
|
|
910
|
-
}
|
|
911
|
-
const body = segments.filter(Boolean).join(" ").replace(/\s+/g, " ").trim();
|
|
912
|
-
const instructionPhrases = [];
|
|
913
|
-
const instructionText = formatAdditionalInstructions(clause);
|
|
914
|
-
if (instructionText) {
|
|
915
|
-
instructionPhrases.push(instructionText);
|
|
916
|
-
}
|
|
917
|
-
const patientInstruction = formatPatientInstructionSentence(clause.patientInstruction);
|
|
918
|
-
if (patientInstruction) {
|
|
919
|
-
instructionPhrases.push(patientInstruction);
|
|
920
|
-
}
|
|
921
|
-
const trailingInstructionText = instructionPhrases.join(" ").trim() || undefined;
|
|
922
|
-
if (!body) {
|
|
923
|
-
if (!trailingInstructionText) {
|
|
924
|
-
return `${verb}.`;
|
|
925
|
-
}
|
|
926
|
-
return `${verb}. ${trailingInstructionText}`.trim();
|
|
927
|
-
}
|
|
928
|
-
const baseSentence = `${verb} ${body}.`;
|
|
929
|
-
return trailingInstructionText ? `${baseSentence} ${trailingInstructionText}` : baseSentence;
|
|
930
|
-
}
|
|
931
|
-
function formatAdditionalInstructions(clause) {
|
|
932
|
-
var _a, _b, _c, _d, _e, _f;
|
|
933
|
-
const instructions = (_a = clause.additionalInstructions) !== null && _a !== void 0 ? _a : [];
|
|
934
|
-
if (!instructions.length) {
|
|
935
|
-
return undefined;
|
|
936
|
-
}
|
|
937
|
-
const phrases = [];
|
|
938
|
-
const grammar = resolveRouteGrammar(clause);
|
|
939
|
-
const verb = resolveMethodVerb(clause, grammar);
|
|
940
|
-
for (const instruction of instructions) {
|
|
941
|
-
if (((_b = instruction.coding) === null || _b === void 0 ? void 0 : _b.code) === SLOWLY_QUALIFIER_CODE) {
|
|
942
|
-
const contextual = verb ? `${verb} slowly` : "Slowly";
|
|
943
|
-
phrases.push(contextual);
|
|
944
|
-
continue;
|
|
945
|
-
}
|
|
946
|
-
if (((_c = instruction.coding) === null || _c === void 0 ? void 0 : _c.code) === EMPTY_STOMACH_QUALIFIER_CODE ||
|
|
947
|
-
((_d = instruction.frames) === null || _d === void 0 ? void 0 : _d.some((frame) => frame.relation === types_1.AdviceRelation.On &&
|
|
948
|
-
frame.args.some((arg) => arg.role === types_1.AdviceArgumentRole.MealState &&
|
|
949
|
-
arg.conceptId === "empty_stomach")))) {
|
|
950
|
-
phrases.push("On an empty stomach");
|
|
951
|
-
continue;
|
|
952
|
-
}
|
|
953
|
-
const text = (_e = instruction.text) !== null && _e !== void 0 ? _e : (_f = instruction.coding) === null || _f === void 0 ? void 0 : _f.display;
|
|
954
|
-
if (!text) {
|
|
955
|
-
continue;
|
|
956
|
-
}
|
|
957
|
-
const trimmed = text.trim();
|
|
958
|
-
if (trimmed) {
|
|
959
|
-
phrases.push(trimmed);
|
|
960
|
-
}
|
|
961
|
-
}
|
|
962
|
-
if (!phrases.length) {
|
|
963
|
-
return undefined;
|
|
964
|
-
}
|
|
965
|
-
return phrases.map((phrase) => (/[.!?]$/.test(phrase) ? phrase : `${phrase}.`)).join(" ").trim();
|
|
966
|
-
}
|
|
967
|
-
function firstCanonicalClause(internal) {
|
|
968
|
-
const clauses = internal.clauses;
|
|
969
|
-
if (clauses.length > 0) {
|
|
970
|
-
return clauses[0];
|
|
971
|
-
}
|
|
972
|
-
return {
|
|
973
|
-
kind: "administration",
|
|
974
|
-
rawText: internal.input,
|
|
975
|
-
raw: { start: 0, end: internal.input.length, text: internal.input },
|
|
976
|
-
leftovers: [],
|
|
977
|
-
evidence: [],
|
|
978
|
-
confidence: 0
|
|
979
|
-
};
|
|
980
|
-
}
|
|
981
|
-
function formatCanonicalClause(clause, style, localization, options) {
|
|
982
|
-
let shortDefault;
|
|
983
|
-
let longDefault;
|
|
984
|
-
const formatDefault = (target) => {
|
|
985
|
-
switch (target) {
|
|
986
|
-
case "short":
|
|
987
|
-
if (shortDefault === undefined) {
|
|
988
|
-
shortDefault = formatShort(clause);
|
|
989
|
-
}
|
|
990
|
-
return shortDefault;
|
|
991
|
-
case "long":
|
|
992
|
-
if (longDefault === undefined) {
|
|
993
|
-
longDefault = formatLong(clause, options);
|
|
994
|
-
}
|
|
995
|
-
return longDefault;
|
|
996
|
-
}
|
|
997
|
-
};
|
|
998
|
-
if (!localization) {
|
|
999
|
-
return formatDefault(style);
|
|
1000
|
-
}
|
|
1001
|
-
if (style === "short" && localization.formatShort) {
|
|
1002
|
-
const context = {
|
|
1003
|
-
style: "short",
|
|
1004
|
-
clause,
|
|
1005
|
-
defaultText: formatDefault("short"),
|
|
1006
|
-
groupMealTimingsByRelation: Boolean(options === null || options === void 0 ? void 0 : options.groupMealTimingsByRelation),
|
|
1007
|
-
includeTimesPerDaySummary: Boolean(options === null || options === void 0 ? void 0 : options.includeTimesPerDaySummary),
|
|
1008
|
-
formatDefault
|
|
1009
|
-
};
|
|
1010
|
-
return localization.formatShort(context);
|
|
1011
|
-
}
|
|
1012
|
-
if (style === "long" && localization.formatLong) {
|
|
1013
|
-
const context = {
|
|
1014
|
-
style: "long",
|
|
1015
|
-
clause,
|
|
1016
|
-
defaultText: formatDefault("long"),
|
|
1017
|
-
groupMealTimingsByRelation: Boolean(options === null || options === void 0 ? void 0 : options.groupMealTimingsByRelation),
|
|
1018
|
-
includeTimesPerDaySummary: Boolean(options === null || options === void 0 ? void 0 : options.includeTimesPerDaySummary),
|
|
1019
|
-
formatDefault
|
|
1020
|
-
};
|
|
1021
|
-
return localization.formatLong(context);
|
|
1022
|
-
}
|
|
1023
|
-
return formatDefault(style);
|
|
1024
|
-
}
|
|
1025
|
-
function formatInternal(internal, style, localization, options) {
|
|
1026
|
-
return formatCanonicalClause(firstCanonicalClause(internal), style, localization, options);
|
|
1027
|
-
}
|
|
1028
|
-
function stripTrailingZero(value) {
|
|
1029
|
-
const text = value.toString();
|
|
1030
|
-
if (text.includes(".")) {
|
|
1031
|
-
return text.replace(/\.0+$/, "").replace(/0+$/, "");
|
|
1032
|
-
}
|
|
1033
|
-
return text;
|
|
1034
|
-
}
|