ezmedicationinput 0.1.43 → 0.1.44
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 +4 -1
- package/dist/advice-rules.json +772 -0
- package/dist/advice-terminology.json +104 -0
- package/dist/advice.d.ts +16 -0
- package/dist/advice.js +1375 -0
- package/dist/event-trigger.d.ts +14 -0
- package/dist/event-trigger.js +501 -0
- package/dist/fhir-translations.d.ts +5 -0
- package/dist/fhir-translations.js +117 -0
- package/dist/fhir.d.ts +6 -4
- package/dist/fhir.js +566 -134
- package/dist/format.d.ts +4 -2
- package/dist/format.js +515 -218
- package/dist/i18n.d.ts +2 -2
- package/dist/i18n.js +641 -199
- package/dist/index.d.ts +0 -1
- package/dist/index.js +219 -168
- package/dist/internal-types.d.ts +5 -5
- package/dist/ir.d.ts +4 -0
- package/dist/ir.js +178 -0
- package/dist/lexer/lex.d.ts +2 -0
- package/dist/lexer/lex.js +401 -0
- package/dist/lexer/meaning.d.ts +71 -0
- package/dist/lexer/meaning.js +619 -0
- package/dist/lexer/surface.d.ts +2 -0
- package/dist/lexer/surface.js +62 -0
- package/dist/lexer/token-types.d.ts +36 -0
- package/dist/lexer/token-types.js +19 -0
- package/dist/maps.d.ts +6 -12
- package/dist/maps.js +793 -247
- package/dist/parser-state.d.ts +101 -0
- package/dist/parser-state.js +441 -0
- package/dist/parser.d.ts +7 -7
- package/dist/parser.js +3598 -1974
- package/dist/prn.d.ts +4 -0
- package/dist/prn.js +59 -0
- package/dist/schedule.js +230 -32
- package/dist/site-phrases.d.ts +35 -0
- package/dist/site-phrases.js +344 -0
- package/dist/timing-summary.d.ts +13 -3
- package/dist/timing-summary.js +7 -7
- package/dist/types.d.ts +237 -32
- package/dist/types.js +49 -1
- package/dist/utils/text.d.ts +3 -0
- package/dist/utils/text.js +48 -0
- package/package.json +1 -1
package/dist/i18n.js
CHANGED
|
@@ -5,6 +5,10 @@ exports.registerSigLocalization = registerSigLocalization;
|
|
|
5
5
|
exports.getRegisteredSigLocalizations = getRegisteredSigLocalizations;
|
|
6
6
|
exports.resolveSigLocalization = resolveSigLocalization;
|
|
7
7
|
exports.resolveSigTranslation = resolveSigTranslation;
|
|
8
|
+
const advice_1 = require("./advice");
|
|
9
|
+
const fhir_translations_1 = require("./fhir-translations");
|
|
10
|
+
const maps_1 = require("./maps");
|
|
11
|
+
const prn_1 = require("./prn");
|
|
8
12
|
const types_1 = require("./types");
|
|
9
13
|
const timing_summary_1 = require("./timing-summary");
|
|
10
14
|
const REGISTERED_LOCALIZATIONS = new Map();
|
|
@@ -65,8 +69,8 @@ function resolveSigTranslation(locale, config) {
|
|
|
65
69
|
function createThaiLocalization() {
|
|
66
70
|
return {
|
|
67
71
|
locale: "th",
|
|
68
|
-
formatShort: ({
|
|
69
|
-
formatLong: ({
|
|
72
|
+
formatShort: ({ clause }) => formatShortThai(clause),
|
|
73
|
+
formatLong: ({ clause, groupMealTimingsByRelation, includeTimesPerDaySummary }) => formatLongThai(clause, {
|
|
70
74
|
groupMealTimingsByRelation,
|
|
71
75
|
includeTimesPerDaySummary
|
|
72
76
|
})
|
|
@@ -135,6 +139,8 @@ const TH_TIMES_PER_DAY = {
|
|
|
135
139
|
3: "วันละ 3 ครั้ง",
|
|
136
140
|
4: "วันละ 4 ครั้ง"
|
|
137
141
|
};
|
|
142
|
+
const SLOWLY_QUALIFIER_CODE = "419443000";
|
|
143
|
+
const EMPTY_STOMACH_QUALIFIER_CODE = "717154004";
|
|
138
144
|
exports.THAI_SITE_TRANSLATIONS = {
|
|
139
145
|
eye: "ตา",
|
|
140
146
|
eyes: "ตา",
|
|
@@ -169,6 +175,13 @@ exports.THAI_SITE_TRANSLATIONS = {
|
|
|
169
175
|
"left upper arm": "ต้นแขนซ้าย",
|
|
170
176
|
"right upper arm": "ต้นแขนขวา",
|
|
171
177
|
"bilateral arms": "แขนทั้งสองข้าง",
|
|
178
|
+
shoulder: "ไหล่",
|
|
179
|
+
shoulders: "ไหล่ทั้งสองข้าง",
|
|
180
|
+
"left shoulder": "ไหล่ซ้าย",
|
|
181
|
+
"right shoulder": "ไหล่ขวา",
|
|
182
|
+
elbow: "ข้อศอก",
|
|
183
|
+
"left elbow": "ข้อศอกซ้าย",
|
|
184
|
+
"right elbow": "ข้อศอกขวา",
|
|
172
185
|
"right leg": "ขาขวา",
|
|
173
186
|
"left leg": "ขาซ้าย",
|
|
174
187
|
"both legs": "ขาทั้งสองข้าง",
|
|
@@ -177,6 +190,22 @@ exports.THAI_SITE_TRANSLATIONS = {
|
|
|
177
190
|
"left lower leg": "ขาส่วนล่างซ้าย",
|
|
178
191
|
"right lower leg": "ขาส่วนล่างขวา",
|
|
179
192
|
"bilateral legs": "ขาทั้งสองข้าง",
|
|
193
|
+
knee: "เข่า",
|
|
194
|
+
"left knee": "เข่าซ้าย",
|
|
195
|
+
"right knee": "เข่าขวา",
|
|
196
|
+
"both knees": "เข่าทั้งสองข้าง",
|
|
197
|
+
"bilateral knees": "เข่าทั้งสองข้าง",
|
|
198
|
+
wrist: "ข้อมือ",
|
|
199
|
+
"left wrist": "ข้อมือซ้าย",
|
|
200
|
+
"right wrist": "ข้อมือขวา",
|
|
201
|
+
ankle: "ข้อเท้า",
|
|
202
|
+
"left ankle": "ข้อเท้าซ้าย",
|
|
203
|
+
"right ankle": "ข้อเท้าขวา",
|
|
204
|
+
"both ankles": "ข้อเท้าทั้งสองข้าง",
|
|
205
|
+
"bilateral ankles": "ข้อเท้าทั้งสองข้าง",
|
|
206
|
+
hip: "สะโพก",
|
|
207
|
+
"left hip": "สะโพกซ้าย",
|
|
208
|
+
"right hip": "สะโพกขวา",
|
|
180
209
|
"right hand": "มือขวา",
|
|
181
210
|
"left hand": "มือซ้าย",
|
|
182
211
|
"both hands": "มือทั้งสองข้าง",
|
|
@@ -190,19 +219,53 @@ exports.THAI_SITE_TRANSLATIONS = {
|
|
|
190
219
|
abdomen: "ช่องท้อง",
|
|
191
220
|
abdominal: "ช่องท้อง",
|
|
192
221
|
belly: "ท้อง",
|
|
222
|
+
"affected area": "บริเวณที่เป็น",
|
|
223
|
+
"affected site": "บริเวณที่เป็น",
|
|
224
|
+
"บริเวณที่เป็น": "บริเวณที่เป็น",
|
|
225
|
+
head: "ศีรษะ",
|
|
226
|
+
"left head": "ศีรษะซ้าย",
|
|
227
|
+
"left side of head": "ศีรษะซ้าย",
|
|
228
|
+
"right head": "ศีรษะขวา",
|
|
229
|
+
"right side of head": "ศีรษะขวา",
|
|
193
230
|
back: "แผ่นหลัง",
|
|
231
|
+
chest: "ทรวงอก",
|
|
232
|
+
"chest wall": "ผนังทรวงอก",
|
|
233
|
+
breast: "เต้านม",
|
|
234
|
+
"left breast": "เต้านมซ้าย",
|
|
235
|
+
"right breast": "เต้านมขวา",
|
|
236
|
+
"both breasts": "เต้านมทั้งสองข้าง",
|
|
237
|
+
"bilateral breasts": "เต้านมทั้งสองข้าง",
|
|
238
|
+
axilla: "รักแร้",
|
|
239
|
+
axillae: "รักแร้ทั้งสองข้าง",
|
|
240
|
+
armpit: "รักแร้",
|
|
241
|
+
armpits: "รักแร้ทั้งสองข้าง",
|
|
242
|
+
groin: "ขาหนีบ",
|
|
194
243
|
scalp: "หนังศีรษะ",
|
|
195
244
|
face: "ใบหน้า",
|
|
196
245
|
cheek: "แก้ม",
|
|
197
246
|
cheeks: "แก้มทั้งสองข้าง",
|
|
198
247
|
forehead: "หน้าผาก",
|
|
248
|
+
temple: "ขมับ",
|
|
249
|
+
"temple region": "ขมับ",
|
|
250
|
+
"temporal region": "ขมับ",
|
|
251
|
+
temples: "ขมับทั้งสองข้าง",
|
|
252
|
+
"left temple": "ขมับซ้าย",
|
|
253
|
+
"left temple region": "ขมับซ้าย",
|
|
254
|
+
"left temporal region": "ขมับซ้าย",
|
|
255
|
+
"right temple": "ขมับขวา",
|
|
256
|
+
"right temple region": "ขมับขวา",
|
|
257
|
+
"right temporal region": "ขมับขวา",
|
|
258
|
+
"both temples": "ขมับทั้งสองข้าง",
|
|
259
|
+
"bilateral temples": "ขมับทั้งสองข้าง",
|
|
199
260
|
chin: "คาง",
|
|
200
261
|
neck: "คอ",
|
|
262
|
+
eyelid: "เปลือกตา",
|
|
263
|
+
eyelids: "เปลือกตา",
|
|
264
|
+
lip: "ริมฝีปาก",
|
|
265
|
+
lips: "ริมฝีปาก",
|
|
201
266
|
forearm: "ปลายแขน",
|
|
202
267
|
"left forearm": "ปลายแขนซ้าย",
|
|
203
268
|
"right forearm": "ปลายแขนขวา",
|
|
204
|
-
shoulder: "ไหล่",
|
|
205
|
-
shoulders: "ไหล่ทั้งสองข้าง",
|
|
206
269
|
thigh: "ต้นขา",
|
|
207
270
|
thighs: "ต้นขาทั้งสองข้าง",
|
|
208
271
|
"left thigh": "ต้นขาซ้าย",
|
|
@@ -234,6 +297,28 @@ exports.THAI_SITE_TRANSLATIONS = {
|
|
|
234
297
|
skin: "ผิวหนัง",
|
|
235
298
|
hair: "เส้นผม"
|
|
236
299
|
};
|
|
300
|
+
const THAI_SITE_CODE_TRANSLATIONS = (() => {
|
|
301
|
+
var _a;
|
|
302
|
+
const translations = {};
|
|
303
|
+
for (const { names, definition } of maps_1.DEFAULT_BODY_SITE_SNOMED_SOURCE) {
|
|
304
|
+
const code = (_a = definition.coding) === null || _a === void 0 ? void 0 : _a.code;
|
|
305
|
+
if (!code || translations[code]) {
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
308
|
+
let translated;
|
|
309
|
+
for (const name of names) {
|
|
310
|
+
const candidate = exports.THAI_SITE_TRANSLATIONS[(0, maps_1.normalizeBodySiteKey)(name)];
|
|
311
|
+
if (candidate) {
|
|
312
|
+
translated = candidate;
|
|
313
|
+
break;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
if (translated) {
|
|
317
|
+
translations[code] = translated;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
return translations;
|
|
321
|
+
})();
|
|
237
322
|
const DEFAULT_THAI_ROUTE_GRAMMAR = { verb: "ใช้" };
|
|
238
323
|
const THAI_ROUTE_GRAMMAR = {
|
|
239
324
|
[types_1.RouteCode["Oral route"]]: { verb: "รับประทาน", routePhrase: "ทางปาก" },
|
|
@@ -299,26 +384,168 @@ const THAI_ROUTE_GRAMMAR = {
|
|
|
299
384
|
sitePreposition: "ที่"
|
|
300
385
|
}
|
|
301
386
|
};
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
387
|
+
const THAI_METHOD_TEXT_VERBS = {
|
|
388
|
+
Apply: "ทา",
|
|
389
|
+
"Apply sunscreen": "ทากันแดด",
|
|
390
|
+
Dab: "แต้ม",
|
|
391
|
+
Drink: "รับประทาน",
|
|
392
|
+
Insert: "สอด",
|
|
393
|
+
Instill: "หยอด",
|
|
394
|
+
Massage: "นวด",
|
|
395
|
+
Reapply: "ทาซ้ำ",
|
|
396
|
+
"Reapply sunscreen": "ทากันแดดซ้ำ",
|
|
397
|
+
Rub: "ถู",
|
|
398
|
+
Spray: "พ่น",
|
|
399
|
+
Shampoo: "สระ",
|
|
400
|
+
Swallow: "รับประทาน",
|
|
401
|
+
Take: "รับประทาน",
|
|
402
|
+
"Use shampoo": "สระ",
|
|
403
|
+
Wash: "ล้าง"
|
|
404
|
+
};
|
|
405
|
+
const THAI_IMPLIED_OBJECT_VERBS = new Set([
|
|
406
|
+
"ทา",
|
|
407
|
+
"ทาซ้ำ",
|
|
408
|
+
"แต้ม",
|
|
409
|
+
"ถู",
|
|
410
|
+
"นวด",
|
|
411
|
+
"พ่น",
|
|
412
|
+
"หยอด",
|
|
413
|
+
"สอด",
|
|
414
|
+
"ล้าง",
|
|
415
|
+
"สระ"
|
|
416
|
+
]);
|
|
417
|
+
const THAI_SUPPRESSIBLE_ROUTE_VERBS = new Set([
|
|
418
|
+
"ทา",
|
|
419
|
+
"ทากันแดด",
|
|
420
|
+
"ทาซ้ำ",
|
|
421
|
+
"ทากันแดดซ้ำ",
|
|
422
|
+
"แต้ม",
|
|
423
|
+
"ถู",
|
|
424
|
+
"นวด",
|
|
425
|
+
"ล้าง",
|
|
426
|
+
"สระ"
|
|
427
|
+
]);
|
|
428
|
+
const THAI_SITE_FIRST_VERBS = new Set([
|
|
429
|
+
"ทา",
|
|
430
|
+
"ทากันแดด",
|
|
431
|
+
"ทาซ้ำ",
|
|
432
|
+
"ทากันแดดซ้ำ",
|
|
433
|
+
"แต้ม",
|
|
434
|
+
"ถู",
|
|
435
|
+
"นวด",
|
|
436
|
+
"ล้าง",
|
|
437
|
+
"สระ",
|
|
438
|
+
"พ่น"
|
|
439
|
+
]);
|
|
440
|
+
function resolveThaiMethodVerb(clause, grammar) {
|
|
441
|
+
var _a, _b, _c, _d, _e;
|
|
442
|
+
const translatedText = (0, fhir_translations_1.getPrimitiveTranslation)((_a = clause.method) === null || _a === void 0 ? void 0 : _a._text, "th");
|
|
443
|
+
if (translatedText) {
|
|
444
|
+
return translatedText;
|
|
445
|
+
}
|
|
446
|
+
const methodText = (_c = (_b = clause.method) === null || _b === void 0 ? void 0 : _b.text) === null || _c === void 0 ? void 0 : _c.trim();
|
|
447
|
+
if (methodText) {
|
|
448
|
+
const overridden = THAI_METHOD_TEXT_VERBS[methodText];
|
|
449
|
+
if (overridden) {
|
|
450
|
+
return overridden;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
const translatedDisplay = (0, fhir_translations_1.getPrimitiveTranslation)((_e = (_d = clause.method) === null || _d === void 0 ? void 0 : _d.coding) === null || _e === void 0 ? void 0 : _e._display, "th");
|
|
454
|
+
if (translatedDisplay) {
|
|
455
|
+
return translatedDisplay;
|
|
456
|
+
}
|
|
457
|
+
return grammar.verb;
|
|
458
|
+
}
|
|
459
|
+
function joinThaiVerbAndBody(verb, body) {
|
|
460
|
+
const trimmedBody = body.trim();
|
|
461
|
+
if (!trimmedBody) {
|
|
462
|
+
return verb;
|
|
463
|
+
}
|
|
464
|
+
switch (verb) {
|
|
465
|
+
case "พ่น":
|
|
466
|
+
if (trimmedBody.startsWith("เข้า")) {
|
|
467
|
+
return `${verb}${trimmedBody}`;
|
|
468
|
+
}
|
|
469
|
+
break;
|
|
470
|
+
case "ทาซ้ำ":
|
|
471
|
+
case "ทากันแดดซ้ำ":
|
|
472
|
+
case "สระ":
|
|
473
|
+
if (trimmedBody.startsWith("ทุก") ||
|
|
474
|
+
trimmedBody.startsWith("วัน") ||
|
|
475
|
+
trimmedBody.startsWith("ก่อน") ||
|
|
476
|
+
trimmedBody.startsWith("หลัง")) {
|
|
477
|
+
return `${verb}${trimmedBody}`;
|
|
478
|
+
}
|
|
479
|
+
break;
|
|
480
|
+
default:
|
|
481
|
+
break;
|
|
482
|
+
}
|
|
483
|
+
return `${verb} ${trimmedBody}`;
|
|
484
|
+
}
|
|
485
|
+
function shouldUseGenericMedicationObjectThai(clause, verb, explicitDosePart) {
|
|
486
|
+
var _a;
|
|
487
|
+
if (explicitDosePart) {
|
|
488
|
+
return false;
|
|
489
|
+
}
|
|
490
|
+
if (THAI_IMPLIED_OBJECT_VERBS.has(verb)) {
|
|
491
|
+
return false;
|
|
492
|
+
}
|
|
493
|
+
switch ((_a = clause.route) === null || _a === void 0 ? void 0 : _a.code) {
|
|
494
|
+
case types_1.RouteCode["Topical route"]:
|
|
495
|
+
case types_1.RouteCode["Transdermal route"]:
|
|
496
|
+
case types_1.RouteCode["Nasal route"]:
|
|
497
|
+
case types_1.RouteCode["Ophthalmic route"]:
|
|
498
|
+
case types_1.RouteCode["Otic route"]:
|
|
499
|
+
case types_1.RouteCode["Per rectum"]:
|
|
500
|
+
case types_1.RouteCode["Per vagina"]:
|
|
501
|
+
return false;
|
|
502
|
+
default:
|
|
503
|
+
return true;
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
function shouldSuppressRoutePhraseThai(clause, verb, hasSite, explicitDosePart) {
|
|
507
|
+
var _a;
|
|
508
|
+
if (hasSite || explicitDosePart) {
|
|
509
|
+
return false;
|
|
510
|
+
}
|
|
511
|
+
if (!THAI_SUPPRESSIBLE_ROUTE_VERBS.has(verb)) {
|
|
512
|
+
return false;
|
|
513
|
+
}
|
|
514
|
+
switch ((_a = clause.route) === null || _a === void 0 ? void 0 : _a.code) {
|
|
515
|
+
case types_1.RouteCode["Topical route"]:
|
|
516
|
+
case types_1.RouteCode["Transdermal route"]:
|
|
517
|
+
return true;
|
|
518
|
+
default:
|
|
519
|
+
return false;
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
function scheduleOf(clause) {
|
|
523
|
+
var _a;
|
|
524
|
+
return (_a = clause.schedule) !== null && _a !== void 0 ? _a : {};
|
|
525
|
+
}
|
|
526
|
+
function resolveRouteGrammarThai(clause) {
|
|
527
|
+
var _a, _b, _c, _d, _e, _f;
|
|
528
|
+
const routeCode = (_a = clause.route) === null || _a === void 0 ? void 0 : _a.code;
|
|
529
|
+
if (routeCode && THAI_ROUTE_GRAMMAR[routeCode]) {
|
|
530
|
+
return (_b = THAI_ROUTE_GRAMMAR[routeCode]) !== null && _b !== void 0 ? _b : DEFAULT_THAI_ROUTE_GRAMMAR;
|
|
306
531
|
}
|
|
307
|
-
const grammar = grammarFromRouteTextThai(
|
|
532
|
+
const grammar = grammarFromRouteTextThai((_c = clause.route) === null || _c === void 0 ? void 0 : _c.text);
|
|
308
533
|
if (grammar) {
|
|
309
534
|
return grammar;
|
|
310
535
|
}
|
|
311
|
-
if (((
|
|
312
|
-
return (
|
|
536
|
+
if (((_e = (_d = clause.dose) === null || _d === void 0 ? void 0 : _d.unit) === null || _e === void 0 ? void 0 : _e.trim().toLowerCase()) === "puff") {
|
|
537
|
+
return ((_f = THAI_ROUTE_GRAMMAR[types_1.RouteCode["Respiratory tract route (qualifier value)"]]) !== null && _f !== void 0 ? _f : DEFAULT_THAI_ROUTE_GRAMMAR);
|
|
313
538
|
}
|
|
314
539
|
return DEFAULT_THAI_ROUTE_GRAMMAR;
|
|
315
540
|
}
|
|
316
541
|
function grammarFromRouteTextThai(text) {
|
|
317
|
-
if (!text)
|
|
542
|
+
if (!text) {
|
|
318
543
|
return undefined;
|
|
544
|
+
}
|
|
319
545
|
const normalized = text.trim().toLowerCase();
|
|
320
|
-
if (!normalized)
|
|
546
|
+
if (!normalized) {
|
|
321
547
|
return undefined;
|
|
548
|
+
}
|
|
322
549
|
if (normalized.includes("mouth") || normalized.includes("oral")) {
|
|
323
550
|
return THAI_ROUTE_GRAMMAR[types_1.RouteCode["Oral route"]];
|
|
324
551
|
}
|
|
@@ -343,6 +570,12 @@ function grammarFromRouteTextThai(text) {
|
|
|
343
570
|
if (normalized.includes("intravenous") || normalized === "iv") {
|
|
344
571
|
return THAI_ROUTE_GRAMMAR[types_1.RouteCode["Intravenous route"]];
|
|
345
572
|
}
|
|
573
|
+
if (normalized.includes("rectal") || normalized.includes("rectum")) {
|
|
574
|
+
return THAI_ROUTE_GRAMMAR[types_1.RouteCode["Per rectum"]];
|
|
575
|
+
}
|
|
576
|
+
if (normalized.includes("vagin")) {
|
|
577
|
+
return THAI_ROUTE_GRAMMAR[types_1.RouteCode["Per vagina"]];
|
|
578
|
+
}
|
|
346
579
|
if (normalized.includes("nasal")) {
|
|
347
580
|
return THAI_ROUTE_GRAMMAR[types_1.RouteCode["Nasal route"]];
|
|
348
581
|
}
|
|
@@ -351,45 +584,75 @@ function grammarFromRouteTextThai(text) {
|
|
|
351
584
|
}
|
|
352
585
|
return undefined;
|
|
353
586
|
}
|
|
354
|
-
function formatDoseThaiShort(
|
|
355
|
-
if (
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
587
|
+
function formatDoseThaiShort(dose) {
|
|
588
|
+
if (!dose) {
|
|
589
|
+
return undefined;
|
|
590
|
+
}
|
|
591
|
+
if (dose.range) {
|
|
592
|
+
if (dose.range.low !== undefined && dose.range.high !== undefined) {
|
|
593
|
+
const base = `${stripTrailingZero(dose.range.low)}-${stripTrailingZero(dose.range.high)}`;
|
|
594
|
+
if (dose.unit) {
|
|
595
|
+
return `${base} ${formatUnitThai(dose.unit, dose.range.high, "short")}`;
|
|
596
|
+
}
|
|
597
|
+
return base;
|
|
598
|
+
}
|
|
599
|
+
if (dose.range.low !== undefined) {
|
|
600
|
+
const base = `>=${stripTrailingZero(dose.range.low)}`;
|
|
601
|
+
if (dose.unit) {
|
|
602
|
+
return `${base} ${formatUnitThai(dose.unit, dose.range.low, "short")}`;
|
|
603
|
+
}
|
|
604
|
+
return base;
|
|
605
|
+
}
|
|
606
|
+
if (dose.range.high !== undefined) {
|
|
607
|
+
const base = `<=${stripTrailingZero(dose.range.high)}`;
|
|
608
|
+
if (dose.unit) {
|
|
609
|
+
return `${base} ${formatUnitThai(dose.unit, dose.range.high, "short")}`;
|
|
610
|
+
}
|
|
611
|
+
return base;
|
|
360
612
|
}
|
|
361
|
-
return base;
|
|
362
613
|
}
|
|
363
|
-
if (
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
return `${amount} ${formatUnitThai(internal.unit, internal.dose, "short")}`;
|
|
614
|
+
if (dose.value !== undefined) {
|
|
615
|
+
if (dose.unit) {
|
|
616
|
+
return `${stripTrailingZero(dose.value)} ${formatUnitThai(dose.unit, dose.value, "short")}`;
|
|
367
617
|
}
|
|
368
|
-
return
|
|
618
|
+
return stripTrailingZero(dose.value);
|
|
369
619
|
}
|
|
370
620
|
return undefined;
|
|
371
621
|
}
|
|
372
|
-
function formatDoseThaiLong(
|
|
373
|
-
if (
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
622
|
+
function formatDoseThaiLong(dose) {
|
|
623
|
+
if (!dose) {
|
|
624
|
+
return undefined;
|
|
625
|
+
}
|
|
626
|
+
if (dose.range) {
|
|
627
|
+
if (dose.range.low !== undefined && dose.range.high !== undefined) {
|
|
628
|
+
if (dose.unit) {
|
|
629
|
+
return `ครั้งละ ${stripTrailingZero(dose.range.low)} ถึง ${stripTrailingZero(dose.range.high)} ${formatUnitThai(dose.unit, dose.range.high, "long")}`;
|
|
630
|
+
}
|
|
631
|
+
return `ครั้งละ ${stripTrailingZero(dose.range.low)} ถึง ${stripTrailingZero(dose.range.high)}`;
|
|
632
|
+
}
|
|
633
|
+
if (dose.range.low !== undefined) {
|
|
634
|
+
if (dose.unit) {
|
|
635
|
+
return `ครั้งละ อย่างน้อย ${stripTrailingZero(dose.range.low)} ${formatUnitThai(dose.unit, dose.range.low, "long")}`;
|
|
636
|
+
}
|
|
637
|
+
return `ครั้งละ อย่างน้อย ${stripTrailingZero(dose.range.low)}`;
|
|
638
|
+
}
|
|
639
|
+
if (dose.range.high !== undefined) {
|
|
640
|
+
if (dose.unit) {
|
|
641
|
+
return `ครั้งละ ไม่เกิน ${stripTrailingZero(dose.range.high)} ${formatUnitThai(dose.unit, dose.range.high, "long")}`;
|
|
642
|
+
}
|
|
643
|
+
return `ครั้งละ ไม่เกิน ${stripTrailingZero(dose.range.high)}`;
|
|
378
644
|
}
|
|
379
|
-
return `ครั้งละ ${stripTrailingZero(low)} ถึง ${stripTrailingZero(high)}`;
|
|
380
645
|
}
|
|
381
|
-
if (
|
|
382
|
-
if (
|
|
383
|
-
|
|
384
|
-
return `ครั้งละ ${stripTrailingZero(internal.dose)} ${unit}`;
|
|
646
|
+
if (dose.value !== undefined) {
|
|
647
|
+
if (dose.unit) {
|
|
648
|
+
return `ครั้งละ ${stripTrailingZero(dose.value)} ${formatUnitThai(dose.unit, dose.value, "long")}`;
|
|
385
649
|
}
|
|
386
|
-
return `ครั้งละ ${stripTrailingZero(
|
|
650
|
+
return `ครั้งละ ${stripTrailingZero(dose.value)}`;
|
|
387
651
|
}
|
|
388
652
|
return undefined;
|
|
389
653
|
}
|
|
390
|
-
function formatUnitThai(unit,
|
|
654
|
+
function formatUnitThai(unit, _value, style) {
|
|
391
655
|
const lower = unit.toLowerCase();
|
|
392
|
-
const quantity = Math.abs(value);
|
|
393
656
|
const mapping = {
|
|
394
657
|
tab: { short: "เม็ด", long: "เม็ด" },
|
|
395
658
|
tablet: { short: "เม็ด", long: "เม็ด" },
|
|
@@ -413,13 +676,16 @@ function formatUnitThai(unit, value, style) {
|
|
|
413
676
|
suppositories: { short: "ยาเหน็บ", long: "ยาเหน็บ" }
|
|
414
677
|
};
|
|
415
678
|
const entry = mapping[lower];
|
|
416
|
-
|
|
417
|
-
return style === "short" ? entry.short : entry.long;
|
|
418
|
-
}
|
|
419
|
-
return unit;
|
|
679
|
+
return entry ? entry[style] : unit;
|
|
420
680
|
}
|
|
421
|
-
function describeFrequencyThai(
|
|
422
|
-
|
|
681
|
+
function describeFrequencyThai(schedule) {
|
|
682
|
+
var _a;
|
|
683
|
+
const frequency = schedule === null || schedule === void 0 ? void 0 : schedule.frequency;
|
|
684
|
+
const frequencyMax = schedule === null || schedule === void 0 ? void 0 : schedule.frequencyMax;
|
|
685
|
+
const period = schedule === null || schedule === void 0 ? void 0 : schedule.period;
|
|
686
|
+
const periodMax = schedule === null || schedule === void 0 ? void 0 : schedule.periodMax;
|
|
687
|
+
const periodUnit = schedule === null || schedule === void 0 ? void 0 : schedule.periodUnit;
|
|
688
|
+
const timingCode = schedule === null || schedule === void 0 ? void 0 : schedule.timingCode;
|
|
423
689
|
if (frequency !== undefined &&
|
|
424
690
|
frequencyMax !== undefined &&
|
|
425
691
|
periodUnit === types_1.FhirPeriodUnit.Day &&
|
|
@@ -433,11 +699,13 @@ function describeFrequencyThai(internal) {
|
|
|
433
699
|
return `วันละ ${stripTrailingZero(frequency)} ถึง ${stripTrailingZero(frequencyMax)} ครั้ง`;
|
|
434
700
|
}
|
|
435
701
|
if (frequency && periodUnit === types_1.FhirPeriodUnit.Day && (!period || period === 1)) {
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
702
|
+
return (_a = TH_TIMES_PER_DAY[frequency]) !== null && _a !== void 0 ? _a : `วันละ ${stripTrailingZero(frequency)} ครั้ง`;
|
|
703
|
+
}
|
|
704
|
+
if (periodUnit === types_1.FhirPeriodUnit.Minute && period) {
|
|
705
|
+
if (periodMax && periodMax !== period) {
|
|
706
|
+
return `ทุก ${stripTrailingZero(period)} ถึง ${stripTrailingZero(periodMax)} นาที`;
|
|
439
707
|
}
|
|
440
|
-
return
|
|
708
|
+
return `ทุก ${stripTrailingZero(period)} นาที`;
|
|
441
709
|
}
|
|
442
710
|
if (periodUnit === types_1.FhirPeriodUnit.Hour && period) {
|
|
443
711
|
if (periodMax && periodMax !== period) {
|
|
@@ -472,6 +740,15 @@ function describeFrequencyThai(internal) {
|
|
|
472
740
|
}
|
|
473
741
|
return `ทุก ${stripTrailingZero(period)} เดือน`;
|
|
474
742
|
}
|
|
743
|
+
if (periodUnit === types_1.FhirPeriodUnit.Year && period) {
|
|
744
|
+
if (period === 1 && (!periodMax || periodMax === 1)) {
|
|
745
|
+
return "ปีละครั้ง";
|
|
746
|
+
}
|
|
747
|
+
if (periodMax && periodMax !== period) {
|
|
748
|
+
return `ทุก ${stripTrailingZero(period)} ถึง ${stripTrailingZero(periodMax)} ปี`;
|
|
749
|
+
}
|
|
750
|
+
return `ทุก ${stripTrailingZero(period)} ปี`;
|
|
751
|
+
}
|
|
475
752
|
if (timingCode) {
|
|
476
753
|
const map = {
|
|
477
754
|
BID: "วันละ 2 ครั้ง",
|
|
@@ -490,24 +767,44 @@ function describeFrequencyThai(internal) {
|
|
|
490
767
|
}
|
|
491
768
|
}
|
|
492
769
|
if (frequency && periodUnit === undefined && period === undefined) {
|
|
493
|
-
if (frequency === 1)
|
|
770
|
+
if (frequency === 1) {
|
|
494
771
|
return "ครั้งเดียว";
|
|
772
|
+
}
|
|
495
773
|
return `${stripTrailingZero(frequency)} ครั้ง`;
|
|
496
774
|
}
|
|
497
775
|
return undefined;
|
|
498
776
|
}
|
|
499
777
|
function describeFrequencyCountThai(count) {
|
|
778
|
+
var _a;
|
|
779
|
+
if (!count || count <= 0) {
|
|
780
|
+
return undefined;
|
|
781
|
+
}
|
|
782
|
+
return (_a = TH_TIMES_PER_DAY[count]) !== null && _a !== void 0 ? _a : `วันละ ${stripTrailingZero(count)} ครั้ง`;
|
|
783
|
+
}
|
|
784
|
+
function describeStandaloneOccurrenceCountThai(schedule) {
|
|
785
|
+
var _a, _b, _c;
|
|
786
|
+
const count = schedule === null || schedule === void 0 ? void 0 : schedule.count;
|
|
500
787
|
if (!count || count <= 0) {
|
|
501
788
|
return undefined;
|
|
502
789
|
}
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
790
|
+
if ((schedule === null || schedule === void 0 ? void 0 : schedule.frequency) !== undefined ||
|
|
791
|
+
(schedule === null || schedule === void 0 ? void 0 : schedule.frequencyMax) !== undefined ||
|
|
792
|
+
(schedule === null || schedule === void 0 ? void 0 : schedule.period) !== undefined ||
|
|
793
|
+
(schedule === null || schedule === void 0 ? void 0 : schedule.periodMax) !== undefined ||
|
|
794
|
+
(schedule === null || schedule === void 0 ? void 0 : schedule.periodUnit) !== undefined ||
|
|
795
|
+
((_a = schedule === null || schedule === void 0 ? void 0 : schedule.dayOfWeek) === null || _a === void 0 ? void 0 : _a.length) ||
|
|
796
|
+
((_b = schedule === null || schedule === void 0 ? void 0 : schedule.when) === null || _b === void 0 ? void 0 : _b.length) ||
|
|
797
|
+
((_c = schedule === null || schedule === void 0 ? void 0 : schedule.timeOfDay) === null || _c === void 0 ? void 0 : _c.length) ||
|
|
798
|
+
(schedule === null || schedule === void 0 ? void 0 : schedule.duration) !== undefined ||
|
|
799
|
+
(schedule === null || schedule === void 0 ? void 0 : schedule.durationMax) !== undefined ||
|
|
800
|
+
(schedule === null || schedule === void 0 ? void 0 : schedule.durationUnit) !== undefined ||
|
|
801
|
+
(schedule === null || schedule === void 0 ? void 0 : schedule.timingCode)) {
|
|
802
|
+
return undefined;
|
|
506
803
|
}
|
|
507
|
-
return
|
|
804
|
+
return `${stripTrailingZero(count)} ครั้ง`;
|
|
508
805
|
}
|
|
509
806
|
function joinMealNamesThai(parts) {
|
|
510
|
-
if (parts.length
|
|
807
|
+
if (!parts.length) {
|
|
511
808
|
return "";
|
|
512
809
|
}
|
|
513
810
|
if (parts.length === 1) {
|
|
@@ -534,13 +831,15 @@ function summarizeMealTimingGroupThai(group) {
|
|
|
534
831
|
dinner: "เย็น"
|
|
535
832
|
};
|
|
536
833
|
const meals = [];
|
|
537
|
-
for (
|
|
538
|
-
meals.push(mealText[
|
|
834
|
+
for (const meal of group.meals) {
|
|
835
|
+
meals.push(mealText[meal]);
|
|
539
836
|
}
|
|
540
837
|
return `${relationText[group.relation]}${joinMealNamesThai(meals)}`;
|
|
541
838
|
}
|
|
542
|
-
function collectWhenPhrasesThai(
|
|
543
|
-
|
|
839
|
+
function collectWhenPhrasesThai(schedule, options) {
|
|
840
|
+
var _a;
|
|
841
|
+
const when = (_a = schedule === null || schedule === void 0 ? void 0 : schedule.when) !== null && _a !== void 0 ? _a : [];
|
|
842
|
+
if (!when.length) {
|
|
544
843
|
return [];
|
|
545
844
|
}
|
|
546
845
|
const unique = [];
|
|
@@ -548,7 +847,7 @@ function collectWhenPhrasesThai(internal, options) {
|
|
|
548
847
|
let hasSpecificAfter = false;
|
|
549
848
|
let hasSpecificBefore = false;
|
|
550
849
|
let hasSpecificWith = false;
|
|
551
|
-
for (const code of
|
|
850
|
+
for (const code of when) {
|
|
552
851
|
if (!seen.has(code)) {
|
|
553
852
|
seen.add(code);
|
|
554
853
|
unique.push(code);
|
|
@@ -562,16 +861,13 @@ function collectWhenPhrasesThai(internal, options) {
|
|
|
562
861
|
code === types_1.EventTiming["Before Dinner"]) {
|
|
563
862
|
hasSpecificBefore = true;
|
|
564
863
|
}
|
|
565
|
-
if (code === types_1.EventTiming.Breakfast ||
|
|
566
|
-
code === types_1.EventTiming.Lunch ||
|
|
567
|
-
code === types_1.EventTiming.Dinner) {
|
|
864
|
+
if (code === types_1.EventTiming.Breakfast || code === types_1.EventTiming.Lunch || code === types_1.EventTiming.Dinner) {
|
|
568
865
|
hasSpecificWith = true;
|
|
569
866
|
}
|
|
570
867
|
}
|
|
571
868
|
}
|
|
572
869
|
const filtered = [];
|
|
573
|
-
for (
|
|
574
|
-
const code = unique[i];
|
|
870
|
+
for (const code of unique) {
|
|
575
871
|
if (code === types_1.EventTiming["After Meal"] && hasSpecificAfter) {
|
|
576
872
|
continue;
|
|
577
873
|
}
|
|
@@ -584,19 +880,9 @@ function collectWhenPhrasesThai(internal, options) {
|
|
|
584
880
|
filtered.push(code);
|
|
585
881
|
}
|
|
586
882
|
const mealGroup = (0, timing_summary_1.getMealTimingGroup)(filtered, options);
|
|
587
|
-
if (mealGroup) {
|
|
588
|
-
const groupedCodes = new Set(mealGroup.codes);
|
|
883
|
+
if (!mealGroup) {
|
|
589
884
|
const phrases = [];
|
|
590
|
-
|
|
591
|
-
for (let i = 0; i < filtered.length; i += 1) {
|
|
592
|
-
const code = filtered[i];
|
|
593
|
-
if (groupedCodes.has(code)) {
|
|
594
|
-
if (!insertedGroup) {
|
|
595
|
-
phrases.push(summarizeMealTimingGroupThai(mealGroup));
|
|
596
|
-
insertedGroup = true;
|
|
597
|
-
}
|
|
598
|
-
continue;
|
|
599
|
-
}
|
|
885
|
+
for (const code of filtered) {
|
|
600
886
|
const text = WHEN_TEXT_THAI[code];
|
|
601
887
|
if (text) {
|
|
602
888
|
phrases.push(text);
|
|
@@ -604,9 +890,18 @@ function collectWhenPhrasesThai(internal, options) {
|
|
|
604
890
|
}
|
|
605
891
|
return phrases;
|
|
606
892
|
}
|
|
893
|
+
const groupedCodes = new Set(mealGroup.codes);
|
|
607
894
|
const phrases = [];
|
|
608
|
-
|
|
609
|
-
|
|
895
|
+
let insertedGroup = false;
|
|
896
|
+
for (const code of filtered) {
|
|
897
|
+
if (groupedCodes.has(code)) {
|
|
898
|
+
if (!insertedGroup) {
|
|
899
|
+
phrases.push(summarizeMealTimingGroupThai(mealGroup));
|
|
900
|
+
insertedGroup = true;
|
|
901
|
+
}
|
|
902
|
+
continue;
|
|
903
|
+
}
|
|
904
|
+
const text = WHEN_TEXT_THAI[code];
|
|
610
905
|
if (text) {
|
|
611
906
|
phrases.push(text);
|
|
612
907
|
}
|
|
@@ -635,39 +930,34 @@ function combineFrequencyAndEventsThai(frequency, events) {
|
|
|
635
930
|
if (!events.length) {
|
|
636
931
|
return { frequency };
|
|
637
932
|
}
|
|
638
|
-
if (events.length === 1 && events[0] === "ก่อนนอน") {
|
|
639
|
-
|
|
640
|
-
return { frequency: `${frequency} และ ${events[0]}` };
|
|
641
|
-
}
|
|
933
|
+
if (events.length === 1 && events[0] === "ก่อนนอน" && frequency.includes("วันละ")) {
|
|
934
|
+
return { frequency: `${frequency} และ ${events[0]}` };
|
|
642
935
|
}
|
|
643
936
|
return { frequency, event: joinWithAndThai(events) };
|
|
644
937
|
}
|
|
645
|
-
function isOralRouteThai(
|
|
646
|
-
var _a;
|
|
647
|
-
if (
|
|
938
|
+
function isOralRouteThai(clause) {
|
|
939
|
+
var _a, _b, _c;
|
|
940
|
+
if (((_a = clause.route) === null || _a === void 0 ? void 0 : _a.code) === types_1.RouteCode["Oral route"]) {
|
|
648
941
|
return true;
|
|
649
942
|
}
|
|
650
|
-
const text = (
|
|
943
|
+
const text = (_c = (_b = clause.route) === null || _b === void 0 ? void 0 : _b.text) === null || _c === void 0 ? void 0 : _c.trim().toLowerCase();
|
|
651
944
|
if (!text) {
|
|
652
945
|
return false;
|
|
653
946
|
}
|
|
654
|
-
return
|
|
655
|
-
text === "oral" ||
|
|
656
|
-
text.includes("mouth") ||
|
|
657
|
-
text.includes("per os"));
|
|
947
|
+
return text === "po" || text === "oral" || text.includes("mouth") || text.includes("per os");
|
|
658
948
|
}
|
|
659
|
-
function buildRoutePhraseThai(
|
|
660
|
-
var _a;
|
|
661
|
-
if (grammar.verb === "รับประทาน" && isOralRouteThai(
|
|
949
|
+
function buildRoutePhraseThai(clause, grammar, hasSite) {
|
|
950
|
+
var _a, _b;
|
|
951
|
+
if (grammar.verb === "รับประทาน" && isOralRouteThai(clause)) {
|
|
662
952
|
return undefined;
|
|
663
953
|
}
|
|
664
954
|
if (typeof grammar.routePhrase === "function") {
|
|
665
|
-
return grammar.routePhrase({ hasSite,
|
|
955
|
+
return grammar.routePhrase({ hasSite, clause });
|
|
666
956
|
}
|
|
667
957
|
if (typeof grammar.routePhrase === "string") {
|
|
668
958
|
return grammar.routePhrase;
|
|
669
959
|
}
|
|
670
|
-
const text = (_a =
|
|
960
|
+
const text = (_b = (_a = clause.route) === null || _a === void 0 ? void 0 : _a.text) === null || _b === void 0 ? void 0 : _b.trim();
|
|
671
961
|
if (!text) {
|
|
672
962
|
return undefined;
|
|
673
963
|
}
|
|
@@ -701,138 +991,261 @@ function buildRoutePhraseThai(internal, grammar, hasSite) {
|
|
|
701
991
|
}
|
|
702
992
|
return text;
|
|
703
993
|
}
|
|
704
|
-
function formatSiteThai(
|
|
705
|
-
var _a, _b;
|
|
706
|
-
const text = (_a =
|
|
707
|
-
|
|
994
|
+
function formatSiteThai(clause, grammar) {
|
|
995
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
996
|
+
const text = ((_b = (_a = clause.site) === null || _a === void 0 ? void 0 : _a.text) === null || _b === void 0 ? void 0 : _b.trim()) || ((_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());
|
|
997
|
+
const lower = text === null || text === void 0 ? void 0 : text.toLowerCase();
|
|
998
|
+
const codingCode = (_g = (_f = clause.site) === null || _f === void 0 ? void 0 : _f.coding) === null || _g === void 0 ? void 0 : _g.code;
|
|
999
|
+
const routeText = (_j = (_h = clause.route) === null || _h === void 0 ? void 0 : _h.text) === null || _j === void 0 ? void 0 : _j.trim().toLowerCase();
|
|
1000
|
+
const isRectalRoute = ((_k = clause.route) === null || _k === void 0 ? void 0 : _k.code) === types_1.RouteCode["Per rectum"] ||
|
|
1001
|
+
routeText === "rectum" ||
|
|
1002
|
+
routeText === "rectal";
|
|
1003
|
+
const isVaginalRoute = ((_l = clause.route) === null || _l === void 0 ? void 0 : _l.code) === types_1.RouteCode["Per vagina"] ||
|
|
1004
|
+
routeText === "vagina" ||
|
|
1005
|
+
routeText === "vaginal";
|
|
1006
|
+
const isRectumSite = codingCode === "34402009" || lower === "rectum" || lower === "rectal";
|
|
1007
|
+
const isVaginaSite = codingCode === "76784001" || lower === "vagina" || lower === "vaginal";
|
|
1008
|
+
if (isRectalRoute &&
|
|
1009
|
+
isRectumSite) {
|
|
708
1010
|
return undefined;
|
|
709
1011
|
}
|
|
710
|
-
|
|
711
|
-
|
|
1012
|
+
if (isVaginalRoute &&
|
|
1013
|
+
isVaginaSite) {
|
|
1014
|
+
return undefined;
|
|
1015
|
+
}
|
|
1016
|
+
const translated = translateSiteThai(text, codingCode);
|
|
1017
|
+
if (!translated) {
|
|
1018
|
+
return undefined;
|
|
1019
|
+
}
|
|
1020
|
+
if (((_m = clause.route) === null || _m === void 0 ? void 0 : _m.code) === types_1.RouteCode["Nasal route"]) {
|
|
1021
|
+
return `เข้า${translated}`;
|
|
1022
|
+
}
|
|
1023
|
+
const preposition = (_o = grammar.sitePreposition) !== null && _o !== void 0 ? _o : "ที่";
|
|
712
1024
|
const separator = /^[\u0E00-\u0E7F]/.test(translated) ? "" : " ";
|
|
713
1025
|
return `${preposition}${separator}${translated}`.trim();
|
|
714
1026
|
}
|
|
715
|
-
function translateSiteThai(site) {
|
|
1027
|
+
function translateSiteThai(site, code) {
|
|
716
1028
|
var _a;
|
|
717
|
-
|
|
1029
|
+
if (code) {
|
|
1030
|
+
const translatedByCode = THAI_SITE_CODE_TRANSLATIONS[code];
|
|
1031
|
+
if (translatedByCode) {
|
|
1032
|
+
return translatedByCode;
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
if (!site) {
|
|
1036
|
+
return undefined;
|
|
1037
|
+
}
|
|
1038
|
+
const normalized = (0, maps_1.normalizeBodySiteKey)(site);
|
|
718
1039
|
if (!normalized) {
|
|
719
1040
|
return site;
|
|
720
1041
|
}
|
|
721
1042
|
return (_a = exports.THAI_SITE_TRANSLATIONS[normalized]) !== null && _a !== void 0 ? _a : site;
|
|
722
1043
|
}
|
|
723
|
-
function describeDayOfWeekThai(
|
|
724
|
-
|
|
1044
|
+
function describeDayOfWeekThai(schedule) {
|
|
1045
|
+
var _a;
|
|
1046
|
+
const dayOfWeek = (_a = schedule === null || schedule === void 0 ? void 0 : schedule.dayOfWeek) !== null && _a !== void 0 ? _a : [];
|
|
1047
|
+
if (!dayOfWeek.length) {
|
|
725
1048
|
return undefined;
|
|
726
1049
|
}
|
|
727
|
-
const days =
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
1050
|
+
const days = [];
|
|
1051
|
+
for (const day of dayOfWeek) {
|
|
1052
|
+
const text = DAY_NAMES_THAI[day];
|
|
1053
|
+
if (text) {
|
|
1054
|
+
days.push(text);
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
return days.length ? `ใน${joinWithAndThai(days)}` : undefined;
|
|
1058
|
+
}
|
|
1059
|
+
function formatDurationShortThai(schedule) {
|
|
1060
|
+
if (schedule.duration === undefined || !schedule.durationUnit) {
|
|
731
1061
|
return undefined;
|
|
732
1062
|
}
|
|
733
|
-
|
|
1063
|
+
const base = stripTrailingZero(schedule.duration);
|
|
1064
|
+
const qualifier = schedule.durationMax !== undefined && schedule.durationMax !== schedule.duration
|
|
1065
|
+
? `${base}-${stripTrailingZero(schedule.durationMax)}`
|
|
1066
|
+
: base;
|
|
1067
|
+
return `x${qualifier}${schedule.durationUnit}`;
|
|
734
1068
|
}
|
|
735
|
-
function
|
|
736
|
-
|
|
737
|
-
|
|
1069
|
+
function describeDurationThai(schedule) {
|
|
1070
|
+
if (!schedule || schedule.duration === undefined || !schedule.durationUnit) {
|
|
1071
|
+
return undefined;
|
|
1072
|
+
}
|
|
1073
|
+
const unit = schedule.durationUnit;
|
|
1074
|
+
const label = () => {
|
|
1075
|
+
switch (unit) {
|
|
1076
|
+
case types_1.FhirPeriodUnit.Minute:
|
|
1077
|
+
return "นาที";
|
|
1078
|
+
case types_1.FhirPeriodUnit.Hour:
|
|
1079
|
+
return "ชั่วโมง";
|
|
1080
|
+
case types_1.FhirPeriodUnit.Day:
|
|
1081
|
+
return "วัน";
|
|
1082
|
+
case types_1.FhirPeriodUnit.Week:
|
|
1083
|
+
return "สัปดาห์";
|
|
1084
|
+
case types_1.FhirPeriodUnit.Month:
|
|
1085
|
+
return "เดือน";
|
|
1086
|
+
case types_1.FhirPeriodUnit.Year:
|
|
1087
|
+
return "ปี";
|
|
1088
|
+
default:
|
|
1089
|
+
return unit;
|
|
1090
|
+
}
|
|
1091
|
+
};
|
|
1092
|
+
if (schedule.durationMax !== undefined && schedule.durationMax !== schedule.duration) {
|
|
1093
|
+
return `เป็นเวลา ${stripTrailingZero(schedule.duration)} ถึง ${stripTrailingZero(schedule.durationMax)} ${label()}`;
|
|
1094
|
+
}
|
|
1095
|
+
return `เป็นเวลา ${stripTrailingZero(schedule.duration)} ${label()}`;
|
|
1096
|
+
}
|
|
1097
|
+
function formatAsNeededThai(clause) {
|
|
1098
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
1099
|
+
if (!((_a = clause.prn) === null || _a === void 0 ? void 0 : _a.enabled)) {
|
|
738
1100
|
return undefined;
|
|
739
1101
|
}
|
|
740
|
-
if (
|
|
741
|
-
const
|
|
742
|
-
|
|
1102
|
+
if ((_b = clause.prn.reasons) === null || _b === void 0 ? void 0 : _b.length) {
|
|
1103
|
+
const translatedReasons = [];
|
|
1104
|
+
for (const reason of clause.prn.reasons) {
|
|
1105
|
+
let text = (_c = reason.text) !== null && _c !== void 0 ? _c : (_d = reason.coding) === null || _d === void 0 ? void 0 : _d.display;
|
|
1106
|
+
const coding = reason.coding;
|
|
1107
|
+
if (coding === null || coding === void 0 ? void 0 : coding.code) {
|
|
1108
|
+
const definition = (0, maps_1.findPrnReasonDefinitionByCoding)((_e = coding.system) !== null && _e !== void 0 ? _e : "http://snomed.info/sct", coding.code);
|
|
1109
|
+
text = (_g = (_f = definition === null || definition === void 0 ? void 0 : definition.i18n) === null || _f === void 0 ? void 0 : _f.th) !== null && _g !== void 0 ? _g : text;
|
|
1110
|
+
}
|
|
1111
|
+
translatedReasons.push({ text, coding: reason.coding });
|
|
1112
|
+
}
|
|
1113
|
+
const joined = (0, prn_1.getPreferredCanonicalPrnReasonText)(undefined, translatedReasons, "หรือ");
|
|
1114
|
+
if (joined) {
|
|
1115
|
+
return `ใช้เมื่อจำเป็นสำหรับ ${joined}`;
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
let translation;
|
|
1119
|
+
const coding = (_h = clause.prn.reason) === null || _h === void 0 ? void 0 : _h.coding;
|
|
1120
|
+
if (coding === null || coding === void 0 ? void 0 : coding.code) {
|
|
1121
|
+
const definition = (0, maps_1.findPrnReasonDefinitionByCoding)((_j = coding.system) !== null && _j !== void 0 ? _j : "http://snomed.info/sct", coding.code);
|
|
1122
|
+
translation = (_k = definition === null || definition === void 0 ? void 0 : definition.i18n) === null || _k === void 0 ? void 0 : _k.th;
|
|
1123
|
+
}
|
|
1124
|
+
const reason = (_l = translation !== null && translation !== void 0 ? translation : (0, prn_1.getPreferredCanonicalPrnReasonText)(clause.prn.reason, clause.prn.reasons, "หรือ")) !== null && _l !== void 0 ? _l : coding === null || coding === void 0 ? void 0 : coding.display;
|
|
1125
|
+
if (reason) {
|
|
1126
|
+
return `ใช้เมื่อจำเป็นสำหรับ ${reason}`;
|
|
743
1127
|
}
|
|
744
1128
|
return "ใช้เมื่อจำเป็น";
|
|
745
1129
|
}
|
|
746
|
-
function formatShortThai(
|
|
747
|
-
var _a;
|
|
1130
|
+
function formatShortThai(clause) {
|
|
1131
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1132
|
+
const schedule = scheduleOf(clause);
|
|
748
1133
|
const parts = [];
|
|
749
|
-
const dose = formatDoseThaiShort(
|
|
1134
|
+
const dose = formatDoseThaiShort(clause.dose);
|
|
750
1135
|
if (dose) {
|
|
751
1136
|
parts.push(dose);
|
|
752
1137
|
}
|
|
753
|
-
if (
|
|
754
|
-
const short = ROUTE_SHORT[
|
|
1138
|
+
if ((_a = clause.route) === null || _a === void 0 ? void 0 : _a.code) {
|
|
1139
|
+
const short = ROUTE_SHORT[clause.route.code];
|
|
755
1140
|
if (short) {
|
|
756
1141
|
parts.push(short);
|
|
757
1142
|
}
|
|
758
|
-
else if (
|
|
759
|
-
parts.push(
|
|
1143
|
+
else if (clause.route.text) {
|
|
1144
|
+
parts.push(clause.route.text);
|
|
760
1145
|
}
|
|
761
1146
|
}
|
|
762
|
-
else if (
|
|
763
|
-
parts.push(
|
|
1147
|
+
else if ((_b = clause.route) === null || _b === void 0 ? void 0 : _b.text) {
|
|
1148
|
+
parts.push(clause.route.text);
|
|
764
1149
|
}
|
|
765
|
-
const timing = describeFrequencyThai(
|
|
1150
|
+
const timing = describeFrequencyThai(schedule);
|
|
766
1151
|
if (timing) {
|
|
767
1152
|
parts.push(timing);
|
|
768
1153
|
}
|
|
769
|
-
else if (
|
|
770
|
-
parts.push(
|
|
1154
|
+
else if (schedule.timingCode) {
|
|
1155
|
+
parts.push(schedule.timingCode);
|
|
771
1156
|
}
|
|
772
|
-
else if (
|
|
773
|
-
const base = stripTrailingZero(
|
|
774
|
-
const qualifier =
|
|
775
|
-
? `${base}-${stripTrailingZero(
|
|
1157
|
+
else if (schedule.period && schedule.periodUnit) {
|
|
1158
|
+
const base = stripTrailingZero(schedule.period);
|
|
1159
|
+
const qualifier = schedule.periodMax && schedule.periodMax !== schedule.period
|
|
1160
|
+
? `${base}-${stripTrailingZero(schedule.periodMax)}`
|
|
776
1161
|
: base;
|
|
777
|
-
parts.push(`Q${qualifier}${
|
|
1162
|
+
parts.push(`Q${qualifier}${schedule.periodUnit.toUpperCase()}`);
|
|
1163
|
+
}
|
|
1164
|
+
const events = collectWhenPhrasesThai(schedule);
|
|
1165
|
+
if (events.length) {
|
|
1166
|
+
parts.push(events.join(" "));
|
|
778
1167
|
}
|
|
779
|
-
if (
|
|
780
|
-
const
|
|
781
|
-
|
|
782
|
-
|
|
1168
|
+
if ((_c = schedule.timeOfDay) === null || _c === void 0 ? void 0 : _c.length) {
|
|
1169
|
+
const times = [];
|
|
1170
|
+
for (const time of schedule.timeOfDay) {
|
|
1171
|
+
times.push(time.slice(0, 5));
|
|
783
1172
|
}
|
|
1173
|
+
parts.push(times.join(","));
|
|
784
1174
|
}
|
|
785
|
-
if ((
|
|
786
|
-
const
|
|
787
|
-
|
|
1175
|
+
if ((_d = schedule.dayOfWeek) === null || _d === void 0 ? void 0 : _d.length) {
|
|
1176
|
+
const days = [];
|
|
1177
|
+
for (const day of schedule.dayOfWeek) {
|
|
1178
|
+
days.push((_f = (_e = DAY_NAMES_THAI[day]) === null || _e === void 0 ? void 0 : _e.replace(/^วัน/, "")) !== null && _f !== void 0 ? _f : day);
|
|
1179
|
+
}
|
|
1180
|
+
parts.push(days.join(","));
|
|
788
1181
|
}
|
|
789
|
-
if (
|
|
790
|
-
|
|
791
|
-
.map((d) => { var _a, _b; return (_b = (_a = DAY_NAMES_THAI[d]) === null || _a === void 0 ? void 0 : _a.replace(/^วัน/, "")) !== null && _b !== void 0 ? _b : d; })
|
|
792
|
-
.join(",");
|
|
793
|
-
parts.push(days);
|
|
1182
|
+
if (schedule.count !== undefined) {
|
|
1183
|
+
parts.push(`x${stripTrailingZero(schedule.count)}`);
|
|
794
1184
|
}
|
|
795
|
-
|
|
796
|
-
|
|
1185
|
+
const durationShort = formatDurationShortThai(schedule);
|
|
1186
|
+
if (durationShort) {
|
|
1187
|
+
parts.push(durationShort);
|
|
797
1188
|
}
|
|
798
|
-
const asNeeded = formatAsNeededThai(
|
|
1189
|
+
const asNeeded = formatAsNeededThai(clause);
|
|
799
1190
|
if (asNeeded) {
|
|
800
1191
|
parts.push(asNeeded);
|
|
801
1192
|
}
|
|
802
1193
|
return parts.filter(Boolean).join(" ");
|
|
803
1194
|
}
|
|
804
|
-
function formatLongThai(
|
|
1195
|
+
function formatLongThai(clause, options) {
|
|
805
1196
|
var _a, _b, _c;
|
|
806
|
-
const
|
|
807
|
-
const
|
|
808
|
-
const
|
|
809
|
-
const
|
|
810
|
-
const
|
|
811
|
-
const
|
|
812
|
-
|
|
1197
|
+
const schedule = scheduleOf(clause);
|
|
1198
|
+
const grammar = resolveRouteGrammarThai(clause);
|
|
1199
|
+
const verb = resolveThaiMethodVerb(clause, grammar);
|
|
1200
|
+
const explicitDosePart = formatDoseThaiLong(clause.dose);
|
|
1201
|
+
const sitePart = formatSiteThai(clause, grammar);
|
|
1202
|
+
const dosePart = shouldUseGenericMedicationObjectThai(clause, verb, explicitDosePart)
|
|
1203
|
+
? explicitDosePart !== null && explicitDosePart !== void 0 ? explicitDosePart : "ยา"
|
|
1204
|
+
: explicitDosePart;
|
|
1205
|
+
const routePart = shouldSuppressRoutePhraseThai(clause, verb, Boolean(sitePart), explicitDosePart)
|
|
1206
|
+
? undefined
|
|
1207
|
+
: buildRoutePhraseThai(clause, grammar, Boolean(sitePart));
|
|
1208
|
+
const standaloneOccurrenceCount = describeStandaloneOccurrenceCountThai(schedule);
|
|
1209
|
+
const frequencyPart = (_b = (_a = describeFrequencyThai(schedule)) !== null && _a !== void 0 ? _a : standaloneOccurrenceCount) !== null && _b !== void 0 ? _b : describeFrequencyCountThai((0, timing_summary_1.inferDailyOccurrenceCount)(schedule, options));
|
|
1210
|
+
const eventParts = collectWhenPhrasesThai(schedule, options);
|
|
1211
|
+
if ((_c = schedule.timeOfDay) === null || _c === void 0 ? void 0 : _c.length) {
|
|
813
1212
|
const timeStrings = [];
|
|
814
|
-
for (const time of
|
|
1213
|
+
for (const time of schedule.timeOfDay) {
|
|
815
1214
|
const parts = time.split(":");
|
|
816
|
-
const
|
|
817
|
-
const
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
1215
|
+
const hours = Number(parts[0]);
|
|
1216
|
+
const minutes = Number(parts[1]);
|
|
1217
|
+
if (!Number.isFinite(hours) || !Number.isFinite(minutes)) {
|
|
1218
|
+
continue;
|
|
1219
|
+
}
|
|
1220
|
+
const displayMinutes = minutes < 10 ? `0${minutes}` : `${minutes}`;
|
|
1221
|
+
const displayHours = hours < 10 ? `0${hours}` : `${hours}`;
|
|
1222
|
+
timeStrings.push(`${displayHours}:${displayMinutes}`);
|
|
821
1223
|
}
|
|
822
|
-
if (timeStrings.length
|
|
1224
|
+
if (timeStrings.length) {
|
|
823
1225
|
eventParts.push(`เวลา ${timeStrings.join(", ")}`);
|
|
824
1226
|
}
|
|
825
1227
|
}
|
|
826
1228
|
const timing = combineFrequencyAndEventsThai(frequencyPart, eventParts);
|
|
827
|
-
const dayPart = describeDayOfWeekThai(
|
|
828
|
-
const countPart =
|
|
829
|
-
? `จำนวน ${stripTrailingZero(
|
|
1229
|
+
const dayPart = describeDayOfWeekThai(schedule);
|
|
1230
|
+
const countPart = schedule.count !== undefined && !standaloneOccurrenceCount
|
|
1231
|
+
? `จำนวน ${stripTrailingZero(schedule.count)} ครั้ง`
|
|
830
1232
|
: undefined;
|
|
831
|
-
const
|
|
832
|
-
const
|
|
1233
|
+
const durationPart = describeDurationThai(schedule);
|
|
1234
|
+
const asNeeded = formatAsNeededThai(clause);
|
|
1235
|
+
const segments = [];
|
|
1236
|
+
if (dosePart) {
|
|
1237
|
+
segments.push(dosePart);
|
|
1238
|
+
}
|
|
833
1239
|
if (routePart) {
|
|
834
1240
|
segments.push(routePart);
|
|
835
1241
|
}
|
|
1242
|
+
const siteFirst = Boolean(sitePart) &&
|
|
1243
|
+
THAI_SITE_FIRST_VERBS.has(verb) &&
|
|
1244
|
+
explicitDosePart === undefined &&
|
|
1245
|
+
routePart === undefined;
|
|
1246
|
+
if (siteFirst && sitePart) {
|
|
1247
|
+
segments.push(sitePart);
|
|
1248
|
+
}
|
|
836
1249
|
if (timing.frequency) {
|
|
837
1250
|
segments.push(timing.frequency);
|
|
838
1251
|
}
|
|
@@ -845,50 +1258,79 @@ function formatLongThai(internal, options) {
|
|
|
845
1258
|
if (countPart) {
|
|
846
1259
|
segments.push(countPart);
|
|
847
1260
|
}
|
|
1261
|
+
if (durationPart) {
|
|
1262
|
+
segments.push(durationPart);
|
|
1263
|
+
}
|
|
848
1264
|
if (asNeeded) {
|
|
849
1265
|
segments.push(asNeeded);
|
|
850
1266
|
}
|
|
851
|
-
if (sitePart) {
|
|
1267
|
+
if (!siteFirst && sitePart) {
|
|
852
1268
|
segments.push(sitePart);
|
|
853
1269
|
}
|
|
854
1270
|
const body = segments.filter(Boolean).join(" ").replace(/\s+/g, " ").trim();
|
|
1271
|
+
const instructionPhrases = [];
|
|
1272
|
+
const instructionText = formatAdditionalInstructionsThai(clause);
|
|
1273
|
+
if (instructionText) {
|
|
1274
|
+
instructionPhrases.push(instructionText);
|
|
1275
|
+
}
|
|
1276
|
+
const patientInstruction = formatPatientInstructionSentence(clause.patientInstruction);
|
|
1277
|
+
if (patientInstruction) {
|
|
1278
|
+
instructionPhrases.push(patientInstruction);
|
|
1279
|
+
}
|
|
1280
|
+
const trailingInstructionText = instructionPhrases.join(" ").trim() || undefined;
|
|
1281
|
+
const baseSentence = `${joinThaiVerbAndBody(verb, body)}.`;
|
|
855
1282
|
if (!body) {
|
|
856
|
-
|
|
857
|
-
if (!instructionText) {
|
|
858
|
-
return `${grammar.verb}.`;
|
|
859
|
-
}
|
|
860
|
-
return `${grammar.verb}. ${instructionText}`.trim();
|
|
1283
|
+
return trailingInstructionText ? `${baseSentence} ${trailingInstructionText}` : baseSentence;
|
|
861
1284
|
}
|
|
862
|
-
|
|
863
|
-
const baseSentence = `${grammar.verb} ${body}.`;
|
|
864
|
-
return instructionText ? `${baseSentence} ${instructionText}` : baseSentence;
|
|
1285
|
+
return trailingInstructionText ? `${baseSentence} ${trailingInstructionText}` : baseSentence;
|
|
865
1286
|
}
|
|
866
|
-
function formatAdditionalInstructionsThai(
|
|
867
|
-
var _a;
|
|
868
|
-
|
|
1287
|
+
function formatAdditionalInstructionsThai(clause) {
|
|
1288
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
1289
|
+
const instructions = (_a = clause.additionalInstructions) !== null && _a !== void 0 ? _a : [];
|
|
1290
|
+
if (!instructions.length) {
|
|
869
1291
|
return undefined;
|
|
870
1292
|
}
|
|
871
|
-
const phrases =
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
if (
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
1293
|
+
const phrases = [];
|
|
1294
|
+
const grammar = resolveRouteGrammarThai(clause);
|
|
1295
|
+
const verb = resolveThaiMethodVerb(clause, grammar);
|
|
1296
|
+
for (const instruction of instructions) {
|
|
1297
|
+
if (((_b = instruction.coding) === null || _b === void 0 ? void 0 : _b.code) === SLOWLY_QUALIFIER_CODE) {
|
|
1298
|
+
const contextual = verb ? `${verb}ช้าๆ` : "ช้าๆ";
|
|
1299
|
+
phrases.push(contextual);
|
|
1300
|
+
continue;
|
|
1301
|
+
}
|
|
1302
|
+
if (((_c = instruction.coding) === null || _c === void 0 ? void 0 : _c.code) === EMPTY_STOMACH_QUALIFIER_CODE ||
|
|
1303
|
+
((_d = instruction.frames) === null || _d === void 0 ? void 0 : _d.some((frame) => frame.relation === types_1.AdviceRelation.On &&
|
|
1304
|
+
frame.args.some((arg) => arg.role === types_1.AdviceArgumentRole.MealState &&
|
|
1305
|
+
arg.conceptId === "empty_stomach")))) {
|
|
1306
|
+
phrases.push("ขณะท้องว่าง");
|
|
1307
|
+
continue;
|
|
1308
|
+
}
|
|
1309
|
+
let text = (_e = instruction.text) !== null && _e !== void 0 ? _e : (_f = instruction.coding) === null || _f === void 0 ? void 0 : _f.display;
|
|
1310
|
+
if ((_g = instruction.coding) === null || _g === void 0 ? void 0 : _g.code) {
|
|
1311
|
+
const definition = (0, advice_1.findAdditionalInstructionDefinitionByCoding)((_h = instruction.coding.system) !== null && _h !== void 0 ? _h : "http://snomed.info/sct", instruction.coding.code);
|
|
1312
|
+
text = (_k = (_j = definition === null || definition === void 0 ? void 0 : definition.i18n) === null || _j === void 0 ? void 0 : _j.th) !== null && _k !== void 0 ? _k : text;
|
|
1313
|
+
}
|
|
1314
|
+
if (!text) {
|
|
1315
|
+
continue;
|
|
1316
|
+
}
|
|
1317
|
+
const trimmed = text.trim();
|
|
1318
|
+
if (trimmed) {
|
|
1319
|
+
phrases.push(trimmed);
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
885
1322
|
if (!phrases.length) {
|
|
886
1323
|
return undefined;
|
|
887
1324
|
}
|
|
888
|
-
return phrases
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
1325
|
+
return phrases.map((phrase) => (/[.!?]$/.test(phrase) ? phrase : `${phrase}.`)).join(" ").trim();
|
|
1326
|
+
}
|
|
1327
|
+
function formatPatientInstructionSentence(text) {
|
|
1328
|
+
const trimmed = text === null || text === void 0 ? void 0 : text.trim();
|
|
1329
|
+
if (!trimmed) {
|
|
1330
|
+
return undefined;
|
|
1331
|
+
}
|
|
1332
|
+
const sentence = /^[.!?]$/.test(trimmed.slice(-1)) ? trimmed : `${trimmed}.`;
|
|
1333
|
+
return sentence.charAt(0).toUpperCase() + sentence.slice(1);
|
|
892
1334
|
}
|
|
893
1335
|
function stripTrailingZero(value) {
|
|
894
1336
|
const text = value.toString();
|