ifct2017 2.0.14 → 2.1.0

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.
Files changed (111) hide show
  1. package/LICENSE +661 -21
  2. package/README.md +1019 -71
  3. package/abbreviations/index.csv +78 -0
  4. package/abbreviations/index.d.ts +39 -0
  5. package/abbreviations/index.js +103 -0
  6. package/abbreviations/index.txt +12 -0
  7. package/about/build.ts +31 -0
  8. package/about/index.d.ts +47 -0
  9. package/about/index.js +110 -0
  10. package/about/index.txt +174 -0
  11. package/build.ts +115 -0
  12. package/carbohydrates/index.csv +8 -0
  13. package/carbohydrates/index.d.ts +42 -0
  14. package/carbohydrates/index.js +112 -0
  15. package/carbohydrates/index.txt +14 -0
  16. package/codes/index.csv +2904 -0
  17. package/codes/index.d.ts +36 -0
  18. package/codes/index.js +102 -0
  19. package/codes/index.txt +12 -0
  20. package/columndescriptions/build.ts +22 -0
  21. package/columndescriptions/index.csv +215 -0
  22. package/columndescriptions/index.d.ts +44 -0
  23. package/columndescriptions/index.js +119 -0
  24. package/columns/build.ts +23 -0
  25. package/columns/index.csv +215 -0
  26. package/columns/index.d.ts +39 -0
  27. package/columns/index.js +111 -0
  28. package/columns/index.txt +71 -0
  29. package/compositingcentres/index.csv +7 -0
  30. package/compositingcentres/index.d.ts +35 -0
  31. package/compositingcentres/index.js +103 -0
  32. package/compositingcentres/index.txt +13 -0
  33. package/compositions/build.ts +212 -0
  34. package/compositions/index.csv +543 -0
  35. package/compositions/index.d.ts +254 -0
  36. package/compositions/index.js +204 -0
  37. package/compositionstats/build.ts +103 -0
  38. package/compositionstats/index.csv +4 -0
  39. package/compositionstats/index.d.ts +31 -0
  40. package/compositionstats/index.js +97 -0
  41. package/contents/index.csv +21 -0
  42. package/contents/index.d.ts +39 -0
  43. package/contents/index.js +102 -0
  44. package/contents/index.txt +13 -0
  45. package/deno.lock +67 -0
  46. package/descriptions/index.csv +543 -0
  47. package/descriptions/index.d.ts +45 -0
  48. package/descriptions/index.js +124 -0
  49. package/descriptions/index.txt +15 -0
  50. package/energies/index.csv +6 -0
  51. package/energies/index.d.ts +34 -0
  52. package/energies/index.js +101 -0
  53. package/energies/index.txt +13 -0
  54. package/frequencydistribution/index.csv +10 -0
  55. package/frequencydistribution/index.d.ts +36 -0
  56. package/frequencydistribution/index.js +90 -0
  57. package/frequencydistribution/index.txt +14 -0
  58. package/groups/index.csv +21 -0
  59. package/groups/index.d.ts +46 -0
  60. package/groups/index.js +118 -0
  61. package/groups/index.txt +14 -0
  62. package/hierarchy/asset.csv +215 -0
  63. package/hierarchy/asset.txt +70 -0
  64. package/hierarchy/build.ts +73 -0
  65. package/hierarchy/index.csv +215 -0
  66. package/hierarchy/index.d.ts +39 -0
  67. package/hierarchy/index.js +100 -0
  68. package/hierarchy/index.txt +14 -0
  69. package/index.d.ts +24 -28
  70. package/index.js +28 -39
  71. package/index.test.ts +717 -0
  72. package/intakes/build.ts +28 -0
  73. package/intakes/index.csv +42 -0
  74. package/intakes/index.d.ts +66 -0
  75. package/intakes/index.js +113 -0
  76. package/intakes/index.txt +20 -0
  77. package/jonesfactors/index.csv +15 -0
  78. package/jonesfactors/index.d.ts +35 -0
  79. package/jonesfactors/index.js +105 -0
  80. package/jonesfactors/index.txt +12 -0
  81. package/languages/index.csv +22 -0
  82. package/languages/index.d.ts +39 -0
  83. package/languages/index.js +103 -0
  84. package/languages/index.txt +12 -0
  85. package/methods/build.ts +101 -0
  86. package/methods/index.csv +37 -0
  87. package/methods/index.d.ts +39 -0
  88. package/methods/index.js +196 -0
  89. package/methods/index.txt +13 -0
  90. package/package.json +15 -63
  91. package/regions/index.csv +7 -0
  92. package/regions/index.d.ts +36 -0
  93. package/regions/index.js +100 -0
  94. package/regions/index.txt +12 -0
  95. package/representations/build.ts +133 -0
  96. package/representations/index.csv +215 -0
  97. package/representations/index.d.ts +36 -0
  98. package/representations/index.js +91 -0
  99. package/retentionfactors/groups.csv +21 -0
  100. package/retentionfactors/index.csv +215 -0
  101. package/samplingunits/index.csv +36 -0
  102. package/samplingunits/index.d.ts +39 -0
  103. package/samplingunits/index.js +110 -0
  104. package/samplingunits/index.txt +14 -0
  105. package/yieldfactors/index.csv +543 -0
  106. package/yieldfactors/index.d.ts +57 -0
  107. package/yieldfactors/index.js +158 -0
  108. package/yieldfactors/index.txt +294 -0
  109. package/corpus.js +0 -6
  110. package/corpus.min.js +0 -1
  111. package/pictures.d.ts +0 -41
@@ -0,0 +1,254 @@
1
+ import { type SetupTableOptions } from "@nodef/extra-sql";
2
+ /** Detailed nutrient composition of a key food in India. */ export interface Composition {
3
+ /** Food Code. */ code: string;
4
+ /** Food Name. */ name: string;
5
+ /** Scientific Name. */ scie: string;
6
+ /** Local Name. */ lang: string;
7
+ /** Food Group. */ grup: string;
8
+ /** No. of Regions. */ regn: number;
9
+ /** Tags. */ tags: string;
10
+ /** Moisture. */ water: number;
11
+ /** Protein. */ protcnt: number;
12
+ /** Ash. */ ash: number;
13
+ /** Total Fat. */ fatce: number;
14
+ /** Dietary Fiber. */ fibtg: number;
15
+ /** Insoluble Dietary Fiber. */ fibins: number;
16
+ /** Soluble Dietary Fiber. */ fibsol: number;
17
+ /** Carbohydrate. */ choavldf: number;
18
+ /** Energy. */ enerc: number;
19
+ /** Thiamine (B1). */ thia: number;
20
+ /** Riboflavin (B2). */ ribf: number;
21
+ /** Niacin (B3). */ nia: number;
22
+ /** Pantothenic acid (B5). */ pantac: number;
23
+ /** Total B6. */ vitb6c: number;
24
+ /** Biotin (B7). */ biot: number;
25
+ /** Folates (B9). */ folsum: number;
26
+ /** Ascorbic acids (C). */ vitc: number;
27
+ /** Retinol. */ retol: number;
28
+ /** Ergocalciferol (D2). */ ergcal: number;
29
+ /** Cholecalciferol (D3). */ chocal: number;
30
+ /** 25-OH-D3. */ doh25: number;
31
+ /** α-Tocopherol. */ tocpha: number;
32
+ /** β-Tocopherol. */ tocphb: number;
33
+ /** γ-Tocopherol. */ tocphg: number;
34
+ /** δ-Tocopherol. */ tocphd: number;
35
+ /** α-Tocotrienol. */ toctra: number;
36
+ /** β-Tocotrienol. */ toctrb: number;
37
+ /** γ-Tocotrienol. */ toctrg: number;
38
+ /** δ-Tocotrienol. */ toctrd: number;
39
+ /** α-Tocopherol equivalent (E). */ vite: number;
40
+ /** Phylloquinones (K1). */ vitk1: number;
41
+ /** Menaquinones (K2). */ vitk2: number;
42
+ /** Lutein. */ lutn: number;
43
+ /** Zeaxanthin. */ zea: number;
44
+ /** β-Cryptoxanthin. */ crypxb: number;
45
+ /** Lycopene. */ lycpn: number;
46
+ /** γ-Carotene. */ cartg: number;
47
+ /** α-Carotene. */ carta: number;
48
+ /** β-Carotene. */ cartb: number;
49
+ /** Carotenoids. */ cartoid: number;
50
+ /** Aluminium (Al). */ al: number;
51
+ /** Arsenic (As). */ as: number;
52
+ /** Cadmium (Cd). */ cd: number;
53
+ /** Calcium (Ca). */ ca: number;
54
+ /** Chromium (Cr). */ cr: number;
55
+ /** Cobalt (Co). */ co: number;
56
+ /** Copper (Cu). */ cu: number;
57
+ /** Iron (Fe). */ fe: number;
58
+ /** Lead (Pb). */ pb: number;
59
+ /** Lithium (Li). */ li: number;
60
+ /** Magnesium (Mg). */ mg: number;
61
+ /** Manganese (Mn). */ mn: number;
62
+ /** Mercury (Hg). */ hg: number;
63
+ /** Molybdenum (Mo). */ mo: number;
64
+ /** Nickel (Ni). */ ni: number;
65
+ /** Phosphorus (P). */ p: number;
66
+ /** Potassium (K). */ k: number;
67
+ /** Selenium (Se). */ se: number;
68
+ /** Sodium (Na). */ na: number;
69
+ /** Zinc (Zn). */ zn: number;
70
+ /** Available CHO. */ cho: number;
71
+ /** Starch. */ starch: number;
72
+ /** Fructose. */ frus: number;
73
+ /** Glucose. */ glus: number;
74
+ /** Sucrose. */ sucs: number;
75
+ /** Maltose. */ mals: number;
76
+ /** Free Sugars. */ fsugar: number;
77
+ /** Lactose. */ lactose: number;
78
+ /** Butyric acid (C4:0). */ f4d0: number;
79
+ /** Caproic acid (C6:0). */ f6d0: number;
80
+ /** Caprylic acid (C8:0). */ f8d0: number;
81
+ /** Capric acid (C10:0). */ f10d0: number;
82
+ /** Undecanoic acid (C11:0). */ f11d0: number;
83
+ /** Lauric acid (C12:0). */ f12d0: number;
84
+ /** Myristic acid (C14:0). */ f14d0: number;
85
+ /** Pentadecanoic acid (C15:0). */ f15d0: number;
86
+ /** Palmitic acid (C16:0). */ f16d0: number;
87
+ /** Stearic acid (C18:0). */ f18d0: number;
88
+ /** Arachidic acid (C20:0). */ f20d0: number;
89
+ /** Behenic acid (C22:0). */ f22d0: number;
90
+ /** Lignoceric acid (C24:0). */ f24d0: number;
91
+ /** Myristoleic acid (C14:1). */ f14d1cn5: number;
92
+ /** Palmitoleic acid (C16:1). */ f16d1cn7: number;
93
+ /** Oleic acid (C18:1n9). */ f18d1cn9: number;
94
+ /** Elaidic acid (C18:1n9t). */ f18d1tn9: number;
95
+ /** Eicosenoic acid (C20:1n9). */ f20d1cn9: number;
96
+ /** Erucic acid (C22:1n9). */ f22d1cn9: number;
97
+ /** Nervonic acid (C24:1n9). */ f24d1cn9: number;
98
+ /** Linoleic acid (C18:2n6). */ f18d2cn6: number;
99
+ /** Eicosadienoic acid (C20:2). */ f20d2n6: number;
100
+ /** Docosadienoic acid (C22:2). */ f22d2n6: number;
101
+ /** α-Linolenic acid (C18:3n3). */ f18d3n3: number;
102
+ /** Eicosatrienoic acid (C20:3n6). */ f20d3n6: number;
103
+ /** Arachidonic acid (C20:4n6). */ f20d4n6: number;
104
+ /** Eicosapentaenoic acid (C20:5n3). */ f20d5n3: number;
105
+ /** Docosapentaenoic acid (C22:5n3). */ f22d5n3: number;
106
+ /** Docosahexaenoic acid (C22:6n3). */ f22d6n3: number;
107
+ /** Saturated Fatty acids. */ fasat: number;
108
+ /** Monounsaturated Fatty acids. */ fams: number;
109
+ /** Polyunsaturated Fatty acids. */ fapu: number;
110
+ /** Cholesterol. */ cholc: number;
111
+ /** Histidine. */ his: number;
112
+ /** Isoleucine. */ ile: number;
113
+ /** Leucine. */ leu: number;
114
+ /** Lysine. */ lys: number;
115
+ /** Methionine. */ met: number;
116
+ /** Cysteine. */ cys: number;
117
+ /** Phenylalanine. */ phe: number;
118
+ /** Threonine. */ thr: number;
119
+ /** Tryptophan. */ trp: number;
120
+ /** Valine. */ val: number;
121
+ /** Alanine. */ ala: number;
122
+ /** Arginine. */ arg: number;
123
+ /** Aspartic acid. */ asp: number;
124
+ /** Glutamic acid. */ glu: number;
125
+ /** Glycine. */ gly: number;
126
+ /** Proline. */ pro: number;
127
+ /** Serine. */ ser: number;
128
+ /** Tyrosine. */ tyr: number;
129
+ /** Oxalates. */ oxalt: number;
130
+ /** Soluble Oxalate. */ oxals: number;
131
+ /** Insoluble Oxalate. */ oxali: number;
132
+ /** Cis-Aconitic acid. */ caconac: number;
133
+ /** Citric acid. */ citac: number;
134
+ /** Fumaric acid. */ fumac: number;
135
+ /** Malic acid. */ malac: number;
136
+ /** Quinic acid. */ quinac: number;
137
+ /** Succinic acid. */ sucac: number;
138
+ /** Tartaric acid. */ tarac: number;
139
+ /** "3. */ dhbenzac34: number;
140
+ /** 3-Hydroxy Benzaldehyde. */ hbenzal3: number;
141
+ /** Protocatechuic acid. */ pcathac: number;
142
+ /** Vanillic acid. */ vanlac: number;
143
+ /** Gallic acid. */ gallac: number;
144
+ /** Cinnamic acid. */ cinmac: number;
145
+ /** o-Coumaric acid. */ coumaco: number;
146
+ /** p-Coumaric acid. */ coumacp: number;
147
+ /** Caffeic acid. */ caffac: number;
148
+ /** Chlorogenic acid. */ chlrac: number;
149
+ /** Ferulic acid. */ ferac: number;
150
+ /** Apigenin. */ apigen: number;
151
+ /** Apigenin-6-C-gluoside. */ apigen6cgls: number;
152
+ /** Apigenin-7-O-neohesperidoside. */ apigen7onshps: number;
153
+ /** Luteolin. */ luteol: number;
154
+ /** Kaempferol. */ kaemf: number;
155
+ /** Quercetin. */ querce: number;
156
+ /** Quercetin-3-β-D-glucoside. */ querce3bdgls: number;
157
+ /** Quercetin-3-O-rutinoside. */ querce3ortns: number;
158
+ /** Quercetin-3-β-galactoside. */ querce3bgls: number;
159
+ /** Isorhamnetin. */ isormt: number;
160
+ /** Myricetin. */ myrct: number;
161
+ /** Resvertrol. */ rsvrtol: number;
162
+ /** Hesperetin. */ hespt: number;
163
+ /** Naringenin. */ narng: number;
164
+ /** Hesperdin. */ hespd: number;
165
+ /** Daidzein. */ daidzn: number;
166
+ /** Genistein. */ gnstein: number;
167
+ /** (-)-Epicatechin. */ epicatec: number;
168
+ /** (-)-Epigallo catechin. */ epicategc: number;
169
+ /** (-)-Epigallo catechin 3-gallate. */ epicatgc3gal: number;
170
+ /** (+)-Catechin. */ catec: number;
171
+ /** (-)-Gallocatechin gallate. */ galcatecgal: number;
172
+ /** (-)-Gallocatechin. */ galcatec: number;
173
+ /** Syringic acid. */ syrgac: number;
174
+ /** Sinapinic acid. */ sinpac: number;
175
+ /** Ellagic acid. */ ellgac: number;
176
+ /** Polyphenols. */ polyph: number;
177
+ /** Raffinose. */ rafs: number;
178
+ /** Stachyose. */ stas: number;
179
+ /** Verbascose. */ vers: number;
180
+ /** Ajugose. */ ajgs: number;
181
+ /** Campesterol. */ camt: number;
182
+ /** Stigmasterol. */ stgstr: number;
183
+ /** β-Sitosterol. */ stostrb: number;
184
+ /** Phytate. */ phytac: number;
185
+ /** Saponins. */ sapon: number;
186
+ /** Vitamin B. */ vitb: number;
187
+ /** Vitamin D. */ vitd: number;
188
+ /** Vitamin K. */ vitk: number;
189
+ /** Tocopherols. */ tocph: number;
190
+ /** Tocotrienols. */ toctr: number;
191
+ /** Essential Amino acids. */ amiace: number;
192
+ /** Conditionally essential Amino acids. */ amiacce: number;
193
+ /** Non-essential Amino acids. */ amiacne: number;
194
+ /** Amino acids. */ amiac: number;
195
+ /** Organic acids. */ orgac: number;
196
+ /** Unsaturated Fatty acids. */ fauns: number;
197
+ /** Essential Fatty acids. */ faess: number;
198
+ /** Cis ω-3 Fatty acids. */ facn3: number;
199
+ /** Cis ω-6 Fatty acids. */ facn6: number;
200
+ /** Cis ω-9 Fatty acids. */ facn9: number;
201
+ /** Cis ω-5 Fatty acids. */ facn5: number;
202
+ /** Cis ω-7 Fatty acids. */ facn7: number;
203
+ /** Cis Fatty acids. */ facis: number;
204
+ /** Trans Fatty acids. */ fatrn: number;
205
+ /** Oligosaccharides. */ olsac: number;
206
+ /** Phytosterols. */ phystr: number;
207
+ /** Essential Quantity Minerals. */ mnrleq: number;
208
+ /** Essential Trace Minerals. */ mnrlet: number;
209
+ /** Possibly essential Trace Minerals. */ mnrlpet: number;
210
+ /** Non-essential Trace Minerals. */ mnrlnet: number;
211
+ /** Toxic Minerals. */ mnrltx: number;
212
+ /** Carotenes. */ carot: number;
213
+ /** Xanthophylls. */ xantp: number;
214
+ /** β-Carotene equivalents. */ cartbeq: number;
215
+ /** Vitamin A. */ vita: number;
216
+ /** Vitamins. */ vit: number;
217
+ }
218
+ /**
219
+ * Load the compositions corpus from the file.
220
+ * @returns compositions corpus
221
+ */ export declare function loadCompositions(): Promise<Map<string, Composition>>;
222
+ /**
223
+ * Get the path to the compositions CSV file.
224
+ * @returns CSV file URL
225
+ */ export declare function compositionsCsv(): string;
226
+ /**
227
+ * Obtain SQL command to create and populate the compositions table.
228
+ * @param tab table name
229
+ * @param opt options for the table
230
+ * @returns CREATE TABLE, INSERT, CREATE VIEW, CREATE INDEX statements
231
+ */ export declare function compositionsSql(tab?: string, opt?: SetupTableOptions): Promise<string>;
232
+ /**
233
+ * Find matching compositions of a code/name/scie/lang/grup/tags query.
234
+ * @param txt code/name/scie/lang/grup/tags query
235
+ * @returns matches `[{code, name, scie, lang, grup, regn, tags, ...}]`
236
+ * @example
237
+ * ```javascript
238
+ * ifct2017.compositions('pineapple');
239
+ * ifct2017.compositions('ananas comosus');
240
+ * // → [ { code: 'E053',
241
+ * // → name: 'Pineapple',
242
+ * // → scie: 'Ananas comosus',
243
+ * // → lang: 'A. Ahnaros; B. Anarasa; G. Anenas; H. Ananas; Kan. Ananas; Kash. Punchitipul; Kh. Soh trun; Kon. Anas; Mal. Kayirha chakka; M. Kihom Ananas; O. Sapuri; P. Ananas; Tam. Annasi pazham; Tel. Anasa pandu; U. Ananas.',
244
+ * // → ... } ]
245
+ *
246
+ * ifct2017.compositions('tell me about cow milk.');
247
+ * ifct2017.compositions('gai ka doodh details.');
248
+ * // → [ { code: 'L002',
249
+ * // → name: 'Milk, Cow',
250
+ * // → scie: '',
251
+ * // → lang: 'A. Garoor gakhir; B. Doodh (garu); G. Gai nu dhudh; H. Gai ka doodh; Kan. Hasuvina halu; Kash. Doodh; Kh. Dud masi; M. San Sanghom; Mar. Doodh (gay); O. Gai dudha; P. Gaan da doodh; S. Gow kshiram; Tam. Pasumpaal; Tel. Aavu paalu.',
252
+ * // → ... } ]
253
+ * ```
254
+ */ export declare function compositions(txt: string): Composition[];
@@ -0,0 +1,204 @@
1
+ // Copyright (C) 2025-26 Subhajit Sahu
2
+ // SPDX-License-Identifier: AGPL-3.0-or-later
3
+ // See LICENSE for full terms
4
+ import * as csv from "@std/csv";
5
+ import lunr from "lunr"; // @deno-types="npm:@types/lunr@2.3.7"
6
+ import { createView, createIndex, setupTableIndex } from "@nodef/extra-sql";
7
+ //#endregion
8
+ //#region CONSTANTS
9
+ const TEXTCOLS = new Set([
10
+ 'code',
11
+ 'name',
12
+ 'scie',
13
+ 'lang',
14
+ 'grup',
15
+ 'tags'
16
+ ]);
17
+ //#endregion
18
+ //#region GLOBALS
19
+ let corpus = null;
20
+ let index = null;
21
+ //#endregion
22
+ //#region FUNCTIONS
23
+ // Parse a row from the CSV file.
24
+ function parseRow(row) {
25
+ const a = {};
26
+ for(const k in row){
27
+ // Name of column is after the last semicolon.
28
+ const l = k.substring(k.lastIndexOf(';') + 1).trim();
29
+ a[l] = TEXTCOLS.has(l) ? row[k] : parseFloat(row[k]);
30
+ }
31
+ return a;
32
+ }
33
+ /**
34
+ * Load the compositions corpus from CSV file.
35
+ * @param file CSV file path
36
+ * @returns compositions corpus
37
+ */ async function loadFromCsv(file) {
38
+ const map = new Map();
39
+ const data = await (await fetch(file)).text();
40
+ const records = csv.parse(data, {
41
+ skipFirstRow: true,
42
+ comment: "#"
43
+ });
44
+ for (const r of records)map.set(r.code, parseRow(r));
45
+ return map;
46
+ }
47
+ /**
48
+ * Setup the lunr index for the compositions corpus.
49
+ * @returns lunr index
50
+ */ function setupIndex(corpus) {
51
+ return lunr(function() {
52
+ this.ref('code');
53
+ this.field('code');
54
+ this.field('name');
55
+ this.field('scie');
56
+ this.field('lang');
57
+ this.field('grup');
58
+ this.field('tags');
59
+ for (const r of corpus.values()){
60
+ let { code, name, scie, lang, grup, tags } = r;
61
+ name = name.replace(/^(\w+),/g, '$1 $1 $1 $1,');
62
+ lang = lang.replace(/\[.*?\]/g, '');
63
+ lang = lang.replace(/\w+\.\s([\w\',\/\(\)\- ]+)[;\.]?/g, '$1');
64
+ lang = lang.replace(/[,\/\(\)\- ]+/g, ' ');
65
+ this.add({
66
+ code,
67
+ name,
68
+ scie,
69
+ lang,
70
+ grup,
71
+ tags
72
+ });
73
+ }
74
+ });
75
+ }
76
+ /**
77
+ * Load the compositions corpus from the file.
78
+ * @returns compositions corpus
79
+ */ export async function loadCompositions() {
80
+ if (corpus) return corpus;
81
+ corpus = await loadFromCsv(compositionsCsv());
82
+ index = setupIndex(corpus);
83
+ return corpus;
84
+ }
85
+ /**
86
+ * Get the path to the compositions CSV file.
87
+ * @returns CSV file URL
88
+ */ export function compositionsCsv() {
89
+ return import.meta.resolve('./index.csv');
90
+ }
91
+ function tsvector(tab, cols) {
92
+ const { code, name, scie, lang, grup, tags } = cols;
93
+ return `setweight(to_tsvector('english', "code"), '${code}')||` + `setweight(to_tsvector('english', left("name", strpos("name", ','))), '${code}')||` + `setweight(to_tsvector('english', "name"), '${name}')||` + `setweight(to_tsvector('english', "scie"), '${scie}')||` + `setweight(to_tsvector('english', ${tab}_lang_tags("lang")), '${lang}')||` + `setweight(to_tsvector('english', "grup"), '${grup}')||` + `setweight(to_tsvector('english', "tags"), '${tags}')`;
94
+ }
95
+ function createFunctionLangTags(tab) {
96
+ return `CREATE OR REPLACE FUNCTION "${tab}_lang_tags" (TEXT) RETURNS TEXT AS $$` + ` SELECT lower(regexp_replace(regexp_replace(regexp_replace($1, ` + ` '\\[.*?\\]', '', 'g'), '\\w+\\.\\s([\\w\\'',\\/\\(\\)\\- ]+)[;\\.]?', '\\1', 'g'),` + ` '[,\\/\\(\\)\\- ]+', ' ', 'g')) $$` + ` LANGUAGE SQL IMMUTABLE RETURNS NULL ON NULL INPUT;\n`;
97
+ }
98
+ function createTable(tab, cols, opt = {}, a = '') {
99
+ const pre = [
100
+ 'code',
101
+ 'name',
102
+ 'scie',
103
+ 'lang',
104
+ 'grup',
105
+ 'regn',
106
+ 'tags'
107
+ ];
108
+ a += `CREATE TABLE IF NOT EXISTS "${tab}" (`;
109
+ for (const c of pre){
110
+ const typ = c === 'regn' ? 'INT' : 'TEXT';
111
+ a += ` "${c}" ${typ} NOT NULL,`;
112
+ }
113
+ for(const c in cols){
114
+ if (pre.includes(c)) continue;
115
+ a += ` "${c}" REAL NOT NULL,`;
116
+ }
117
+ if (opt.pk) a += ` PRIMARY KEY ("code"), `;
118
+ a = a.endsWith(', ') ? a.substring(0, a.length - 2) : a;
119
+ a += `);\n`;
120
+ return a;
121
+ }
122
+ function insertIntoBegin(tab, cols, a = '') {
123
+ a += `INSERT INTO "${tab}" (`;
124
+ for(const c in cols)a += `"${c}", `;
125
+ a = a.endsWith(', ') ? a.substring(0, a.length - 2) : a;
126
+ a += ') VALUES\n(';
127
+ return a;
128
+ }
129
+ function insertIntoMid(val, a = '') {
130
+ for(const k in val)a += `$$${val[k]}$$, `;
131
+ a = a.endsWith(', ') ? a.substring(0, a.length - 2) : a;
132
+ a += `),\n(`;
133
+ return a;
134
+ }
135
+ function insertIntoEnd(a = '') {
136
+ a = a.endsWith(',\n(') ? a.substring(0, a.length - 3) : a;
137
+ a += ';\n';
138
+ return a;
139
+ }
140
+ /**
141
+ * Obtain SQL command to create and populate the compositions table.
142
+ * @param tab table name
143
+ * @param opt options for the table
144
+ * @returns CREATE TABLE, INSERT, CREATE VIEW, CREATE INDEX statements
145
+ */ export async function compositionsSql(tab = "compositions", opt = {}) {
146
+ const tsv = tsvector(tab, {
147
+ code: 'A',
148
+ name: 'B',
149
+ scie: 'B',
150
+ lang: 'B',
151
+ grup: 'C',
152
+ tags: 'C'
153
+ });
154
+ opt = Object.assign({
155
+ pk: 'code',
156
+ index: true
157
+ }, opt);
158
+ const map = await loadCompositions();
159
+ const cols = map.get("A001");
160
+ let a = createTable(tab, cols, opt, '');
161
+ a = insertIntoBegin(tab, cols, a);
162
+ for (const [, row] of map)a = insertIntoMid(row, a);
163
+ a = insertIntoEnd(a);
164
+ a += createFunctionLangTags(tab);
165
+ a += createView(`${tab}_tsvector`, `SELECT *, ${tsv} AS "tsvector" FROM "${tab}"`);
166
+ a += createIndex(`${tab}_tsvector_idx`, tab, `(${tsv})`, {
167
+ method: 'GIN'
168
+ });
169
+ a = setupTableIndex(tab, cols, opt, a);
170
+ return a;
171
+ }
172
+ /**
173
+ * Find matching compositions of a code/name/scie/lang/grup/tags query.
174
+ * @param txt code/name/scie/lang/grup/tags query
175
+ * @returns matches `[{code, name, scie, lang, grup, regn, tags, ...}]`
176
+ * @example
177
+ * ```javascript
178
+ * ifct2017.compositions('pineapple');
179
+ * ifct2017.compositions('ananas comosus');
180
+ * // → [ { code: 'E053',
181
+ * // → name: 'Pineapple',
182
+ * // → scie: 'Ananas comosus',
183
+ * // → lang: 'A. Ahnaros; B. Anarasa; G. Anenas; H. Ananas; Kan. Ananas; Kash. Punchitipul; Kh. Soh trun; Kon. Anas; Mal. Kayirha chakka; M. Kihom Ananas; O. Sapuri; P. Ananas; Tam. Annasi pazham; Tel. Anasa pandu; U. Ananas.',
184
+ * // → ... } ]
185
+ *
186
+ * ifct2017.compositions('tell me about cow milk.');
187
+ * ifct2017.compositions('gai ka doodh details.');
188
+ * // → [ { code: 'L002',
189
+ * // → name: 'Milk, Cow',
190
+ * // → scie: '',
191
+ * // → lang: 'A. Garoor gakhir; B. Doodh (garu); G. Gai nu dhudh; H. Gai ka doodh; Kan. Hasuvina halu; Kash. Doodh; Kh. Dud masi; M. San Sanghom; Mar. Doodh (gay); O. Gai dudha; P. Gaan da doodh; S. Gow kshiram; Tam. Pasumpaal; Tel. Aavu paalu.',
192
+ * // → ... } ]
193
+ * ```
194
+ */ export function compositions(txt) {
195
+ if (index == null) return [];
196
+ const a = [];
197
+ txt = txt.replace(/\W/g, ' ');
198
+ const mats = index.search(txt);
199
+ let max = 0;
200
+ for (const mat of mats)max = Math.max(max, Object.keys(mat.matchData.metadata).length);
201
+ for (const mat of mats)if (Object.keys(mat.matchData.metadata).length === max) a.push(corpus?.get(mat.ref) || {});
202
+ return a;
203
+ } //#endregion
204
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9pZmN0MjAxNy9pZmN0MjAxNy9jb21wb3NpdGlvbnMvaW5kZXgudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IChDKSAyMDI1LTI2IFN1Ymhhaml0IFNhaHVcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBR1BMLTMuMC1vci1sYXRlclxuLy8gU2VlIExJQ0VOU0UgZm9yIGZ1bGwgdGVybXNcbmltcG9ydCAqIGFzIGNzdiAgZnJvbSBcIkBzdGQvY3N2XCI7XG5pbXBvcnQgbHVuciBmcm9tIFwibHVuclwiOyAgLy8gQGRlbm8tdHlwZXM9XCJucG06QHR5cGVzL2x1bnJAMi4zLjdcIlxuaW1wb3J0IHt0eXBlIENvbHVtblR5cGVzLCB0eXBlIFNldHVwVGFibGVPcHRpb25zLCBjcmVhdGVWaWV3LCBjcmVhdGVJbmRleCwgc2V0dXBUYWJsZUluZGV4fSBmcm9tIFwiQG5vZGVmL2V4dHJhLXNxbFwiO1xuXG5cblxuXG4vLyNyZWdpb24gVFlQRVNcbi8qKiBEZXRhaWxlZCBudXRyaWVudCBjb21wb3NpdGlvbiBvZiBhIGtleSBmb29kIGluIEluZGlhLiAqL1xuZXhwb3J0IGludGVyZmFjZSBDb21wb3NpdGlvbiB7XG4gIC8qKiBGb29kIENvZGUuICovXG4gIGNvZGU6IHN0cmluZyxcbiAgLyoqIEZvb2QgTmFtZS4gKi9cbiAgbmFtZTogc3RyaW5nLFxuICAvKiogU2NpZW50aWZpYyBOYW1lLiAqL1xuICBzY2llOiBzdHJpbmcsXG4gIC8qKiBMb2NhbCBOYW1lLiAqL1xuICBsYW5nOiBzdHJpbmcsXG4gIC8qKiBGb29kIEdyb3VwLiAqL1xuICBncnVwOiBzdHJpbmcsXG4gIC8qKiBOby4gb2YgUmVnaW9ucy4gKi9cbiAgcmVnbjogbnVtYmVyLFxuICAvKiogVGFncy4gKi9cbiAgdGFnczogc3RyaW5nLFxuICAvKiogTW9pc3R1cmUuICovXG4gIHdhdGVyOiBudW1iZXIsXG4gIC8qKiBQcm90ZWluLiAqL1xuICBwcm90Y250OiBudW1iZXIsXG4gIC8qKiBBc2guICovXG4gIGFzaDogbnVtYmVyLFxuICAvKiogVG90YWwgRmF0LiAqL1xuICBmYXRjZTogbnVtYmVyLFxuICAvKiogRGlldGFyeSBGaWJlci4gKi9cbiAgZmlidGc6IG51bWJlcixcbiAgLyoqIEluc29sdWJsZSBEaWV0YXJ5IEZpYmVyLiAqL1xuICBmaWJpbnM6IG51bWJlcixcbiAgLyoqIFNvbHVibGUgRGlldGFyeSBGaWJlci4gKi9cbiAgZmlic29sOiBudW1iZXIsXG4gIC8qKiBDYXJib2h5ZHJhdGUuICovXG4gIGNob2F2bGRmOiBudW1iZXIsXG4gIC8qKiBFbmVyZ3kuICovXG4gIGVuZXJjOiBudW1iZXIsXG4gIC8qKiBUaGlhbWluZSAoQjEpLiAqL1xuICB0aGlhOiBudW1iZXIsXG4gIC8qKiBSaWJvZmxhdmluIChCMikuICovXG4gIHJpYmY6IG51bWJlcixcbiAgLyoqIE5pYWNpbiAoQjMpLiAqL1xuICBuaWE6IG51bWJlcixcbiAgLyoqIFBhbnRvdGhlbmljIGFjaWQgKEI1KS4gKi9cbiAgcGFudGFjOiBudW1iZXIsXG4gIC8qKiBUb3RhbCBCNi4gKi9cbiAgdml0YjZjOiBudW1iZXIsXG4gIC8qKiBCaW90aW4gKEI3KS4gKi9cbiAgYmlvdDogbnVtYmVyLFxuICAvKiogRm9sYXRlcyAoQjkpLiAqL1xuICBmb2xzdW06IG51bWJlcixcbiAgLyoqIEFzY29yYmljIGFjaWRzIChDKS4gKi9cbiAgdml0YzogbnVtYmVyLFxuICAvKiogUmV0aW5vbC4gKi9cbiAgcmV0b2w6IG51bWJlcixcbiAgLyoqIEVyZ29jYWxjaWZlcm9sIChEMikuICovXG4gIGVyZ2NhbDogbnVtYmVyLFxuICAvKiogQ2hvbGVjYWxjaWZlcm9sIChEMykuICovXG4gIGNob2NhbDogbnVtYmVyLFxuICAvKiogMjUtT0gtRDMuICovXG4gIGRvaDI1OiBudW1iZXIsXG4gIC8qKiDOsS1Ub2NvcGhlcm9sLiAqL1xuICB0b2NwaGE6IG51bWJlcixcbiAgLyoqIM6yLVRvY29waGVyb2wuICovXG4gIHRvY3BoYjogbnVtYmVyLFxuICAvKiogzrMtVG9jb3BoZXJvbC4gKi9cbiAgdG9jcGhnOiBudW1iZXIsXG4gIC8qKiDOtC1Ub2NvcGhlcm9sLiAqL1xuICB0b2NwaGQ6IG51bWJlcixcbiAgLyoqIM6xLVRvY290cmllbm9sLiAqL1xuICB0b2N0cmE6IG51bWJlcixcbiAgLyoqIM6yLVRvY290cmllbm9sLiAqL1xuICB0b2N0cmI6IG51bWJlcixcbiAgLyoqIM6zLVRvY290cmllbm9sLiAqL1xuICB0b2N0cmc6IG51bWJlcixcbiAgLyoqIM60LVRvY290cmllbm9sLiAqL1xuICB0b2N0cmQ6IG51bWJlcixcbiAgLyoqIM6xLVRvY29waGVyb2wgZXF1aXZhbGVudCAoRSkuICovXG4gIHZpdGU6IG51bWJlcixcbiAgLyoqIFBoeWxsb3F1aW5vbmVzIChLMSkuICovXG4gIHZpdGsxOiBudW1iZXIsXG4gIC8qKiBNZW5hcXVpbm9uZXMgKEsyKS4gKi9cbiAgdml0azI6IG51bWJlcixcbiAgLyoqIEx1dGVpbi4gKi9cbiAgbHV0bjogbnVtYmVyLFxuICAvKiogWmVheGFudGhpbi4gKi9cbiAgemVhOiBudW1iZXIsXG4gIC8qKiDOsi1DcnlwdG94YW50aGluLiAqL1xuICBjcnlweGI6IG51bWJlcixcbiAgLyoqIEx5Y29wZW5lLiAqL1xuICBseWNwbjogbnVtYmVyLFxuICAvKiogzrMtQ2Fyb3RlbmUuICovXG4gIGNhcnRnOiBudW1iZXIsXG4gIC8qKiDOsS1DYXJvdGVuZS4gKi9cbiAgY2FydGE6IG51bWJlcixcbiAgLyoqIM6yLUNhcm90ZW5lLiAqL1xuICBjYXJ0YjogbnVtYmVyLFxuICAvKiogQ2Fyb3Rlbm9pZHMuICovXG4gIGNhcnRvaWQ6IG51bWJlcixcbiAgLyoqIEFsdW1pbml1bSAoQWwpLiAqL1xuICBhbDogbnVtYmVyLFxuICAvKiogQXJzZW5pYyAoQXMpLiAqL1xuICBhczogbnVtYmVyLFxuICAvKiogQ2FkbWl1bSAoQ2QpLiAqL1xuICBjZDogbnVtYmVyLFxuICAvKiogQ2FsY2l1bSAoQ2EpLiAqL1xuICBjYTogbnVtYmVyLFxuICAvKiogQ2hyb21pdW0gKENyKS4gKi9cbiAgY3I6IG51bWJlcixcbiAgLyoqIENvYmFsdCAoQ28pLiAqL1xuICBjbzogbnVtYmVyLFxuICAvKiogQ29wcGVyIChDdSkuICovXG4gIGN1OiBudW1iZXIsXG4gIC8qKiBJcm9uIChGZSkuICovXG4gIGZlOiBudW1iZXIsXG4gIC8qKiBMZWFkIChQYikuICovXG4gIHBiOiBudW1iZXIsXG4gIC8qKiBMaXRoaXVtIChMaSkuICovXG4gIGxpOiBudW1iZXIsXG4gIC8qKiBNYWduZXNpdW0gKE1nKS4gKi9cbiAgbWc6IG51bWJlcixcbiAgLyoqIE1hbmdhbmVzZSAoTW4pLiAqL1xuICBtbjogbnVtYmVyLFxuICAvKiogTWVyY3VyeSAoSGcpLiAqL1xuICBoZzogbnVtYmVyLFxuICAvKiogTW9seWJkZW51bSAoTW8pLiAqL1xuICBtbzogbnVtYmVyLFxuICAvKiogTmlja2VsIChOaSkuICovXG4gIG5pOiBudW1iZXIsXG4gIC8qKiBQaG9zcGhvcnVzIChQKS4gKi9cbiAgcDogbnVtYmVyLFxuICAvKiogUG90YXNzaXVtIChLKS4gKi9cbiAgazogbnVtYmVyLFxuICAvKiogU2VsZW5pdW0gKFNlKS4gKi9cbiAgc2U6IG51bWJlcixcbiAgLyoqIFNvZGl1bSAoTmEpLiAqL1xuICBuYTogbnVtYmVyLFxuICAvKiogWmluYyAoWm4pLiAqL1xuICB6bjogbnVtYmVyLFxuICAvKiogQXZhaWxhYmxlIENITy4gKi9cbiAgY2hvOiBudW1iZXIsXG4gIC8qKiBTdGFyY2guICovXG4gIHN0YXJjaDogbnVtYmVyLFxuICAvKiogRnJ1Y3Rvc2UuICovXG4gIGZydXM6IG51bWJlcixcbiAgLyoqIEdsdWNvc2UuICovXG4gIGdsdXM6IG51bWJlcixcbiAgLyoqIFN1Y3Jvc2UuICovXG4gIHN1Y3M6IG51bWJlcixcbiAgLyoqIE1hbHRvc2UuICovXG4gIG1hbHM6IG51bWJlcixcbiAgLyoqIEZyZWUgU3VnYXJzLiAqL1xuICBmc3VnYXI6IG51bWJlcixcbiAgLyoqIExhY3Rvc2UuICovXG4gIGxhY3Rvc2U6IG51bWJlcixcbiAgLyoqIEJ1dHlyaWMgYWNpZCAoQzQ6MCkuICovXG4gIGY0ZDA6IG51bWJlcixcbiAgLyoqIENhcHJvaWMgYWNpZCAoQzY6MCkuICovXG4gIGY2ZDA6IG51bWJlcixcbiAgLyoqIENhcHJ5bGljIGFjaWQgKEM4OjApLiAqL1xuICBmOGQwOiBudW1iZXIsXG4gIC8qKiBDYXByaWMgYWNpZCAoQzEwOjApLiAqL1xuICBmMTBkMDogbnVtYmVyLFxuICAvKiogVW5kZWNhbm9pYyBhY2lkIChDMTE6MCkuICovXG4gIGYxMWQwOiBudW1iZXIsXG4gIC8qKiBMYXVyaWMgYWNpZCAoQzEyOjApLiAqL1xuICBmMTJkMDogbnVtYmVyLFxuICAvKiogTXlyaXN0aWMgYWNpZCAoQzE0OjApLiAqL1xuICBmMTRkMDogbnVtYmVyLFxuICAvKiogUGVudGFkZWNhbm9pYyBhY2lkIChDMTU6MCkuICovXG4gIGYxNWQwOiBudW1iZXIsXG4gIC8qKiBQYWxtaXRpYyBhY2lkIChDMTY6MCkuICovXG4gIGYxNmQwOiBudW1iZXIsXG4gIC8qKiBTdGVhcmljIGFjaWQgKEMxODowKS4gKi9cbiAgZjE4ZDA6IG51bWJlcixcbiAgLyoqIEFyYWNoaWRpYyBhY2lkIChDMjA6MCkuICovXG4gIGYyMGQwOiBudW1iZXIsXG4gIC8qKiBCZWhlbmljIGFjaWQgKEMyMjowKS4gKi9cbiAgZjIyZDA6IG51bWJlcixcbiAgLyoqIExpZ25vY2VyaWMgYWNpZCAoQzI0OjApLiAqL1xuICBmMjRkMDogbnVtYmVyLFxuICAvKiogTXlyaXN0b2xlaWMgYWNpZCAoQzE0OjEpLiAqL1xuICBmMTRkMWNuNTogbnVtYmVyLFxuICAvKiogUGFsbWl0b2xlaWMgYWNpZCAoQzE2OjEpLiAqL1xuICBmMTZkMWNuNzogbnVtYmVyLFxuICAvKiogT2xlaWMgYWNpZCAoQzE4OjFuOSkuICovXG4gIGYxOGQxY245OiBudW1iZXIsXG4gIC8qKiBFbGFpZGljIGFjaWQgKEMxODoxbjl0KS4gKi9cbiAgZjE4ZDF0bjk6IG51bWJlcixcbiAgLyoqIEVpY29zZW5vaWMgYWNpZCAoQzIwOjFuOSkuICovXG4gIGYyMGQxY245OiBudW1iZXIsXG4gIC8qKiBFcnVjaWMgYWNpZCAoQzIyOjFuOSkuICovXG4gIGYyMmQxY245OiBudW1iZXIsXG4gIC8qKiBOZXJ2b25pYyBhY2lkIChDMjQ6MW45KS4gKi9cbiAgZjI0ZDFjbjk6IG51bWJlcixcbiAgLyoqIExpbm9sZWljIGFjaWQgKEMxODoybjYpLiAqL1xuICBmMThkMmNuNjogbnVtYmVyLFxuICAvKiogRWljb3NhZGllbm9pYyBhY2lkIChDMjA6MikuICovXG4gIGYyMGQybjY6IG51bWJlcixcbiAgLyoqIERvY29zYWRpZW5vaWMgYWNpZCAoQzIyOjIpLiAqL1xuICBmMjJkMm42OiBudW1iZXIsXG4gIC8qKiDOsS1MaW5vbGVuaWMgYWNpZCAoQzE4OjNuMykuICovXG4gIGYxOGQzbjM6IG51bWJlcixcbiAgLyoqIEVpY29zYXRyaWVub2ljIGFjaWQgKEMyMDozbjYpLiAqL1xuICBmMjBkM242OiBudW1iZXIsXG4gIC8qKiBBcmFjaGlkb25pYyBhY2lkIChDMjA6NG42KS4gKi9cbiAgZjIwZDRuNjogbnVtYmVyLFxuICAvKiogRWljb3NhcGVudGFlbm9pYyBhY2lkIChDMjA6NW4zKS4gKi9cbiAgZjIwZDVuMzogbnVtYmVyLFxuICAvKiogRG9jb3NhcGVudGFlbm9pYyBhY2lkIChDMjI6NW4zKS4gKi9cbiAgZjIyZDVuMzogbnVtYmVyLFxuICAvKiogRG9jb3NhaGV4YWVub2ljIGFjaWQgKEMyMjo2bjMpLiAqL1xuICBmMjJkNm4zOiBudW1iZXIsXG4gIC8qKiBTYXR1cmF0ZWQgRmF0dHkgYWNpZHMuICovXG4gIGZhc2F0OiBudW1iZXIsXG4gIC8qKiBNb25vdW5zYXR1cmF0ZWQgRmF0dHkgYWNpZHMuICovXG4gIGZhbXM6IG51bWJlcixcbiAgLyoqIFBvbHl1bnNhdHVyYXRlZCBGYXR0eSBhY2lkcy4gKi9cbiAgZmFwdTogbnVtYmVyLFxuICAvKiogQ2hvbGVzdGVyb2wuICovXG4gIGNob2xjOiBudW1iZXIsXG4gIC8qKiBIaXN0aWRpbmUuICovXG4gIGhpczogbnVtYmVyLFxuICAvKiogSXNvbGV1Y2luZS4gKi9cbiAgaWxlOiBudW1iZXIsXG4gIC8qKiBMZXVjaW5lLiAqL1xuICBsZXU6IG51bWJlcixcbiAgLyoqIEx5c2luZS4gKi9cbiAgbHlzOiBudW1iZXIsXG4gIC8qKiBNZXRoaW9uaW5lLiAqL1xuICBtZXQ6IG51bWJlcixcbiAgLyoqIEN5c3RlaW5lLiAqL1xuICBjeXM6IG51bWJlcixcbiAgLyoqIFBoZW55bGFsYW5pbmUuICovXG4gIHBoZTogbnVtYmVyLFxuICAvKiogVGhyZW9uaW5lLiAqL1xuICB0aHI6IG51bWJlcixcbiAgLyoqIFRyeXB0b3BoYW4uICovXG4gIHRycDogbnVtYmVyLFxuICAvKiogVmFsaW5lLiAqL1xuICB2YWw6IG51bWJlcixcbiAgLyoqIEFsYW5pbmUuICovXG4gIGFsYTogbnVtYmVyLFxuICAvKiogQXJnaW5pbmUuICovXG4gIGFyZzogbnVtYmVyLFxuICAvKiogQXNwYXJ0aWMgYWNpZC4gKi9cbiAgYXNwOiBudW1iZXIsXG4gIC8qKiBHbHV0YW1pYyBhY2lkLiAqL1xuICBnbHU6IG51bWJlcixcbiAgLyoqIEdseWNpbmUuICovXG4gIGdseTogbnVtYmVyLFxuICAvKiogUHJvbGluZS4gKi9cbiAgcHJvOiBudW1iZXIsXG4gIC8qKiBTZXJpbmUuICovXG4gIHNlcjogbnVtYmVyLFxuICAvKiogVHlyb3NpbmUuICovXG4gIHR5cjogbnVtYmVyLFxuICAvKiogT3hhbGF0ZXMuICovXG4gIG94YWx0OiBudW1iZXIsXG4gIC8qKiBTb2x1YmxlIE94YWxhdGUuICovXG4gIG94YWxzOiBudW1iZXIsXG4gIC8qKiBJbnNvbHVibGUgT3hhbGF0ZS4gKi9cbiAgb3hhbGk6IG51bWJlcixcbiAgLyoqIENpcy1BY29uaXRpYyBhY2lkLiAqL1xuICBjYWNvbmFjOiBudW1iZXIsXG4gIC8qKiBDaXRyaWMgYWNpZC4gKi9cbiAgY2l0YWM6IG51bWJlcixcbiAgLyoqIEZ1bWFyaWMgYWNpZC4gKi9cbiAgZnVtYWM6IG51bWJlcixcbiAgLyoqIE1hbGljIGFjaWQuICovXG4gIG1hbGFjOiBudW1iZXIsXG4gIC8qKiBRdWluaWMgYWNpZC4gKi9cbiAgcXVpbmFjOiBudW1iZXIsXG4gIC8qKiBTdWNjaW5pYyBhY2lkLiAqL1xuICBzdWNhYzogbnVtYmVyLFxuICAvKiogVGFydGFyaWMgYWNpZC4gKi9cbiAgdGFyYWM6IG51bWJlcixcbiAgLyoqIFwiMy4gKi9cbiAgZGhiZW56YWMzNDogbnVtYmVyLFxuICAvKiogMy1IeWRyb3h5IEJlbnphbGRlaHlkZS4gKi9cbiAgaGJlbnphbDM6IG51bWJlcixcbiAgLyoqIFByb3RvY2F0ZWNodWljIGFjaWQuICovXG4gIHBjYXRoYWM6IG51bWJlcixcbiAgLyoqIFZhbmlsbGljIGFjaWQuICovXG4gIHZhbmxhYzogbnVtYmVyLFxuICAvKiogR2FsbGljIGFjaWQuICovXG4gIGdhbGxhYzogbnVtYmVyLFxuICAvKiogQ2lubmFtaWMgYWNpZC4gKi9cbiAgY2lubWFjOiBudW1iZXIsXG4gIC8qKiBvLUNvdW1hcmljIGFjaWQuICovXG4gIGNvdW1hY286IG51bWJlcixcbiAgLyoqIHAtQ291bWFyaWMgYWNpZC4gKi9cbiAgY291bWFjcDogbnVtYmVyLFxuICAvKiogQ2FmZmVpYyBhY2lkLiAqL1xuICBjYWZmYWM6IG51bWJlcixcbiAgLyoqIENobG9yb2dlbmljIGFjaWQuICovXG4gIGNobHJhYzogbnVtYmVyLFxuICAvKiogRmVydWxpYyBhY2lkLiAqL1xuICBmZXJhYzogbnVtYmVyLFxuICAvKiogQXBpZ2VuaW4uICovXG4gIGFwaWdlbjogbnVtYmVyLFxuICAvKiogQXBpZ2VuaW4tNi1DLWdsdW9zaWRlLiAqL1xuICBhcGlnZW42Y2dsczogbnVtYmVyLFxuICAvKiogQXBpZ2VuaW4tNy1PLW5lb2hlc3Blcmlkb3NpZGUuICovXG4gIGFwaWdlbjdvbnNocHM6IG51bWJlcixcbiAgLyoqIEx1dGVvbGluLiAqL1xuICBsdXRlb2w6IG51bWJlcixcbiAgLyoqIEthZW1wZmVyb2wuICovXG4gIGthZW1mOiBudW1iZXIsXG4gIC8qKiBRdWVyY2V0aW4uICovXG4gIHF1ZXJjZTogbnVtYmVyLFxuICAvKiogUXVlcmNldGluLTMtzrItRC1nbHVjb3NpZGUuICovXG4gIHF1ZXJjZTNiZGdsczogbnVtYmVyLFxuICAvKiogUXVlcmNldGluLTMtTy1ydXRpbm9zaWRlLiAqL1xuICBxdWVyY2Uzb3J0bnM6IG51bWJlcixcbiAgLyoqIFF1ZXJjZXRpbi0zLc6yLWdhbGFjdG9zaWRlLiAqL1xuICBxdWVyY2UzYmdsczogbnVtYmVyLFxuICAvKiogSXNvcmhhbW5ldGluLiAqL1xuICBpc29ybXQ6IG51bWJlcixcbiAgLyoqIE15cmljZXRpbi4gKi9cbiAgbXlyY3Q6IG51bWJlcixcbiAgLyoqIFJlc3ZlcnRyb2wuICovXG4gIHJzdnJ0b2w6IG51bWJlcixcbiAgLyoqIEhlc3BlcmV0aW4uICovXG4gIGhlc3B0OiBudW1iZXIsXG4gIC8qKiBOYXJpbmdlbmluLiAqL1xuICBuYXJuZzogbnVtYmVyLFxuICAvKiogSGVzcGVyZGluLiAqL1xuICBoZXNwZDogbnVtYmVyLFxuICAvKiogRGFpZHplaW4uICovXG4gIGRhaWR6bjogbnVtYmVyLFxuICAvKiogR2VuaXN0ZWluLiAqL1xuICBnbnN0ZWluOiBudW1iZXIsXG4gIC8qKiAoLSktRXBpY2F0ZWNoaW4uICovXG4gIGVwaWNhdGVjOiBudW1iZXIsXG4gIC8qKiAoLSktRXBpZ2FsbG8gY2F0ZWNoaW4uICovXG4gIGVwaWNhdGVnYzogbnVtYmVyLFxuICAvKiogKC0pLUVwaWdhbGxvIGNhdGVjaGluIDMtZ2FsbGF0ZS4gKi9cbiAgZXBpY2F0Z2MzZ2FsOiBudW1iZXIsXG4gIC8qKiAoKyktQ2F0ZWNoaW4uICovXG4gIGNhdGVjOiBudW1iZXIsXG4gIC8qKiAoLSktR2FsbG9jYXRlY2hpbiBnYWxsYXRlLiAqL1xuICBnYWxjYXRlY2dhbDogbnVtYmVyLFxuICAvKiogKC0pLUdhbGxvY2F0ZWNoaW4uICovXG4gIGdhbGNhdGVjOiBudW1iZXIsXG4gIC8qKiBTeXJpbmdpYyBhY2lkLiAqL1xuICBzeXJnYWM6IG51bWJlcixcbiAgLyoqIFNpbmFwaW5pYyBhY2lkLiAqL1xuICBzaW5wYWM6IG51bWJlcixcbiAgLyoqIEVsbGFnaWMgYWNpZC4gKi9cbiAgZWxsZ2FjOiBudW1iZXIsXG4gIC8qKiBQb2x5cGhlbm9scy4gKi9cbiAgcG9seXBoOiBudW1iZXIsXG4gIC8qKiBSYWZmaW5vc2UuICovXG4gIHJhZnM6IG51bWJlcixcbiAgLyoqIFN0YWNoeW9zZS4gKi9cbiAgc3RhczogbnVtYmVyLFxuICAvKiogVmVyYmFzY29zZS4gKi9cbiAgdmVyczogbnVtYmVyLFxuICAvKiogQWp1Z29zZS4gKi9cbiAgYWpnczogbnVtYmVyLFxuICAvKiogQ2FtcGVzdGVyb2wuICovXG4gIGNhbXQ6IG51bWJlcixcbiAgLyoqIFN0aWdtYXN0ZXJvbC4gKi9cbiAgc3Rnc3RyOiBudW1iZXIsXG4gIC8qKiDOsi1TaXRvc3Rlcm9sLiAqL1xuICBzdG9zdHJiOiBudW1iZXIsXG4gIC8qKiBQaHl0YXRlLiAqL1xuICBwaHl0YWM6IG51bWJlcixcbiAgLyoqIFNhcG9uaW5zLiAqL1xuICBzYXBvbjogbnVtYmVyLFxuICAvKiogVml0YW1pbiBCLiAqL1xuICB2aXRiOiBudW1iZXIsXG4gIC8qKiBWaXRhbWluIEQuICovXG4gIHZpdGQ6IG51bWJlcixcbiAgLyoqIFZpdGFtaW4gSy4gKi9cbiAgdml0azogbnVtYmVyLFxuICAvKiogVG9jb3BoZXJvbHMuICovXG4gIHRvY3BoOiBudW1iZXIsXG4gIC8qKiBUb2NvdHJpZW5vbHMuICovXG4gIHRvY3RyOiBudW1iZXIsXG4gIC8qKiBFc3NlbnRpYWwgQW1pbm8gYWNpZHMuICovXG4gIGFtaWFjZTogbnVtYmVyLFxuICAvKiogQ29uZGl0aW9uYWxseSBlc3NlbnRpYWwgQW1pbm8gYWNpZHMuICovXG4gIGFtaWFjY2U6IG51bWJlcixcbiAgLyoqIE5vbi1lc3NlbnRpYWwgQW1pbm8gYWNpZHMuICovXG4gIGFtaWFjbmU6IG51bWJlcixcbiAgLyoqIEFtaW5vIGFjaWRzLiAqL1xuICBhbWlhYzogbnVtYmVyLFxuICAvKiogT3JnYW5pYyBhY2lkcy4gKi9cbiAgb3JnYWM6IG51bWJlcixcbiAgLyoqIFVuc2F0dXJhdGVkIEZhdHR5IGFjaWRzLiAqL1xuICBmYXVuczogbnVtYmVyLFxuICAvKiogRXNzZW50aWFsIEZhdHR5IGFjaWRzLiAqL1xuICBmYWVzczogbnVtYmVyLFxuICAvKiogQ2lzIM+JLTMgRmF0dHkgYWNpZHMuICovXG4gIGZhY24zOiBudW1iZXIsXG4gIC8qKiBDaXMgz4ktNiBGYXR0eSBhY2lkcy4gKi9cbiAgZmFjbjY6IG51bWJlcixcbiAgLyoqIENpcyDPiS05IEZhdHR5IGFjaWRzLiAqL1xuICBmYWNuOTogbnVtYmVyLFxuICAvKiogQ2lzIM+JLTUgRmF0dHkgYWNpZHMuICovXG4gIGZhY241OiBudW1iZXIsXG4gIC8qKiBDaXMgz4ktNyBGYXR0eSBhY2lkcy4gKi9cbiAgZmFjbjc6IG51bWJlcixcbiAgLyoqIENpcyBGYXR0eSBhY2lkcy4gKi9cbiAgZmFjaXM6IG51bWJlcixcbiAgLyoqIFRyYW5zIEZhdHR5IGFjaWRzLiAqL1xuICBmYXRybjogbnVtYmVyLFxuICAvKiogT2xpZ29zYWNjaGFyaWRlcy4gKi9cbiAgb2xzYWM6IG51bWJlcixcbiAgLyoqIFBoeXRvc3Rlcm9scy4gKi9cbiAgcGh5c3RyOiBudW1iZXIsXG4gIC8qKiBFc3NlbnRpYWwgUXVhbnRpdHkgTWluZXJhbHMuICovXG4gIG1ucmxlcTogbnVtYmVyLFxuICAvKiogRXNzZW50aWFsIFRyYWNlIE1pbmVyYWxzLiAqL1xuICBtbnJsZXQ6IG51bWJlcixcbiAgLyoqIFBvc3NpYmx5IGVzc2VudGlhbCBUcmFjZSBNaW5lcmFscy4gKi9cbiAgbW5ybHBldDogbnVtYmVyLFxuICAvKiogTm9uLWVzc2VudGlhbCBUcmFjZSBNaW5lcmFscy4gKi9cbiAgbW5ybG5ldDogbnVtYmVyLFxuICAvKiogVG94aWMgTWluZXJhbHMuICovXG4gIG1ucmx0eDogbnVtYmVyLFxuICAvKiogQ2Fyb3RlbmVzLiAqL1xuICBjYXJvdDogbnVtYmVyLFxuICAvKiogWGFudGhvcGh5bGxzLiAqL1xuICB4YW50cDogbnVtYmVyLFxuICAvKiogzrItQ2Fyb3RlbmUgZXF1aXZhbGVudHMuICovXG4gIGNhcnRiZXE6IG51bWJlcixcbiAgLyoqIFZpdGFtaW4gQS4gKi9cbiAgdml0YTogbnVtYmVyLFxuICAvKiogVml0YW1pbnMuICovXG4gIHZpdDogbnVtYmVyLFxufTtcbi8vI2VuZHJlZ2lvblxuXG5cblxuXG4vLyNyZWdpb24gQ09OU1RBTlRTXG5jb25zdCBURVhUQ09MUyA9IG5ldyBTZXQoWydjb2RlJywgJ25hbWUnLCAnc2NpZScsICdsYW5nJywgJ2dydXAnLCAndGFncyddKTtcbi8vI2VuZHJlZ2lvblxuXG5cblxuXG4vLyNyZWdpb24gR0xPQkFMU1xubGV0IGNvcnB1czogTWFwPHN0cmluZywgQ29tcG9zaXRpb24+IHwgbnVsbCA9IG51bGw7XG5sZXQgaW5kZXg6IGx1bnIuSW5kZXggfCBudWxsID0gbnVsbDtcbi8vI2VuZHJlZ2lvblxuXG5cblxuXG4vLyNyZWdpb24gRlVOQ1RJT05TXG4vLyBQYXJzZSBhIHJvdyBmcm9tIHRoZSBDU1YgZmlsZS5cbmZ1bmN0aW9uIHBhcnNlUm93KHJvdzogUmVjb3JkPHN0cmluZywgc3RyaW5nPikge1xuICBjb25zdCBhOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmcgfCBudW1iZXI+ID0ge307XG4gIGZvciAoY29uc3QgayBpbiByb3cpIHtcbiAgICAvLyBOYW1lIG9mIGNvbHVtbiBpcyBhZnRlciB0aGUgbGFzdCBzZW1pY29sb24uXG4gICAgY29uc3QgbCA9IGsuc3Vic3RyaW5nKGsubGFzdEluZGV4T2YoJzsnKSsxKS50cmltKCk7XG4gICAgYVtsXSA9IFRFWFRDT0xTLmhhcyhsKT8gcm93W2tdIDogcGFyc2VGbG9hdChyb3dba10pO1xuICB9XG4gIHJldHVybiBhO1xufVxuXG5cbi8qKlxuICogTG9hZCB0aGUgY29tcG9zaXRpb25zIGNvcnB1cyBmcm9tIENTViBmaWxlLlxuICogQHBhcmFtIGZpbGUgQ1NWIGZpbGUgcGF0aFxuICogQHJldHVybnMgY29tcG9zaXRpb25zIGNvcnB1c1xuICovXG5hc3luYyBmdW5jdGlvbiBsb2FkRnJvbUNzdihmaWxlOiBzdHJpbmcpIHtcbiAgY29uc3QgbWFwICA9IG5ldyBNYXA8c3RyaW5nLCBDb21wb3NpdGlvbj4oKTtcbiAgY29uc3QgZGF0YSA9IGF3YWl0IChhd2FpdCBmZXRjaChmaWxlKSkudGV4dCgpO1xuICBjb25zdCByZWNvcmRzID0gY3N2LnBhcnNlKGRhdGEsIHtza2lwRmlyc3RSb3c6IHRydWUsIGNvbW1lbnQ6IFwiI1wifSk7XG4gIGZvciAoY29uc3QgciBvZiByZWNvcmRzKVxuICAgIG1hcC5zZXQoci5jb2RlLCBwYXJzZVJvdyhyKSBhcyB1bmtub3duIGFzIENvbXBvc2l0aW9uKTtcbiAgcmV0dXJuIG1hcDtcbn1cblxuXG4vKipcbiAqIFNldHVwIHRoZSBsdW5yIGluZGV4IGZvciB0aGUgY29tcG9zaXRpb25zIGNvcnB1cy5cbiAqIEByZXR1cm5zIGx1bnIgaW5kZXhcbiAqL1xuZnVuY3Rpb24gc2V0dXBJbmRleChjb3JwdXM6IE1hcDxzdHJpbmcsIENvbXBvc2l0aW9uPikge1xuICByZXR1cm4gbHVucihmdW5jdGlvbih0aGlzOiBsdW5yLkJ1aWxkZXIpIHtcbiAgICB0aGlzLnJlZignY29kZScpO1xuICAgIHRoaXMuZmllbGQoJ2NvZGUnKTtcbiAgICB0aGlzLmZpZWxkKCduYW1lJyk7XG4gICAgdGhpcy5maWVsZCgnc2NpZScpO1xuICAgIHRoaXMuZmllbGQoJ2xhbmcnKTtcbiAgICB0aGlzLmZpZWxkKCdncnVwJyk7XG4gICAgdGhpcy5maWVsZCgndGFncycpO1xuICAgIGZvciAoY29uc3QgciBvZiBjb3JwdXMudmFsdWVzKCkpIHtcbiAgICAgIGxldCB7Y29kZSwgbmFtZSwgc2NpZSwgbGFuZywgZ3J1cCwgdGFnc30gPSByO1xuICAgICAgbmFtZSA9IG5hbWUucmVwbGFjZSgvXihcXHcrKSwvZywgJyQxICQxICQxICQxLCcpO1xuICAgICAgbGFuZyA9IGxhbmcucmVwbGFjZSgvXFxbLio/XFxdL2csICcnKTtcbiAgICAgIGxhbmcgPSBsYW5nLnJlcGxhY2UoL1xcdytcXC5cXHMoW1xcd1xcJyxcXC9cXChcXClcXC0gXSspWztcXC5dPy9nLCAnJDEnKTtcbiAgICAgIGxhbmcgPSBsYW5nLnJlcGxhY2UoL1ssXFwvXFwoXFwpXFwtIF0rL2csICcgJyk7XG4gICAgICB0aGlzLmFkZCh7Y29kZSwgbmFtZSwgc2NpZSwgbGFuZywgZ3J1cCwgdGFnc30pO1xuICAgIH1cbiAgfSk7XG59XG5cblxuLyoqXG4gKiBMb2FkIHRoZSBjb21wb3NpdGlvbnMgY29ycHVzIGZyb20gdGhlIGZpbGUuXG4gKiBAcmV0dXJucyBjb21wb3NpdGlvbnMgY29ycHVzXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBsb2FkQ29tcG9zaXRpb25zKCk6IFByb21pc2U8TWFwPHN0cmluZywgQ29tcG9zaXRpb24+PiB7XG4gIGlmIChjb3JwdXMpIHJldHVybiBjb3JwdXM7XG4gIGNvcnB1cyA9IGF3YWl0IGxvYWRGcm9tQ3N2KGNvbXBvc2l0aW9uc0NzdigpKTtcbiAgaW5kZXggID0gc2V0dXBJbmRleChjb3JwdXMpO1xuICByZXR1cm4gY29ycHVzO1xufVxuXG5cbi8qKlxuICogR2V0IHRoZSBwYXRoIHRvIHRoZSBjb21wb3NpdGlvbnMgQ1NWIGZpbGUuXG4gKiBAcmV0dXJucyBDU1YgZmlsZSBVUkxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbXBvc2l0aW9uc0NzdigpOiBzdHJpbmcge1xuICByZXR1cm4gaW1wb3J0Lm1ldGEucmVzb2x2ZSgnLi9pbmRleC5jc3YnKTtcbn1cblxuXG5mdW5jdGlvbiB0c3ZlY3Rvcih0YWI6IHN0cmluZywgY29sczogUmVjb3JkPHN0cmluZywgc3RyaW5nPikge1xuICBjb25zdCB7Y29kZSwgbmFtZSwgc2NpZSwgbGFuZywgZ3J1cCwgdGFnc30gPSBjb2xzO1xuICByZXR1cm4gYHNldHdlaWdodCh0b190c3ZlY3RvcignZW5nbGlzaCcsIFwiY29kZVwiKSwgJyR7Y29kZX0nKXx8YCtcbiAgYHNldHdlaWdodCh0b190c3ZlY3RvcignZW5nbGlzaCcsIGxlZnQoXCJuYW1lXCIsIHN0cnBvcyhcIm5hbWVcIiwgJywnKSkpLCAnJHtjb2RlfScpfHxgK1xuICBgc2V0d2VpZ2h0KHRvX3RzdmVjdG9yKCdlbmdsaXNoJywgXCJuYW1lXCIpLCAnJHtuYW1lfScpfHxgK1xuICBgc2V0d2VpZ2h0KHRvX3RzdmVjdG9yKCdlbmdsaXNoJywgXCJzY2llXCIpLCAnJHtzY2llfScpfHxgK1xuICBgc2V0d2VpZ2h0KHRvX3RzdmVjdG9yKCdlbmdsaXNoJywgJHt0YWJ9X2xhbmdfdGFncyhcImxhbmdcIikpLCAnJHtsYW5nfScpfHxgK1xuICBgc2V0d2VpZ2h0KHRvX3RzdmVjdG9yKCdlbmdsaXNoJywgXCJncnVwXCIpLCAnJHtncnVwfScpfHxgK1xuICBgc2V0d2VpZ2h0KHRvX3RzdmVjdG9yKCdlbmdsaXNoJywgXCJ0YWdzXCIpLCAnJHt0YWdzfScpYDtcbn1cblxuXG5mdW5jdGlvbiBjcmVhdGVGdW5jdGlvbkxhbmdUYWdzKHRhYjogc3RyaW5nKSB7XG4gIHJldHVybiBgQ1JFQVRFIE9SIFJFUExBQ0UgRlVOQ1RJT04gXCIke3RhYn1fbGFuZ190YWdzXCIgKFRFWFQpIFJFVFVSTlMgVEVYVCBBUyAkJGArXG4gIGAgU0VMRUNUIGxvd2VyKHJlZ2V4cF9yZXBsYWNlKHJlZ2V4cF9yZXBsYWNlKHJlZ2V4cF9yZXBsYWNlKCQxLCBgK1xuICBgICdcXFxcWy4qP1xcXFxdJywgJycsICdnJyksICdcXFxcdytcXFxcLlxcXFxzKFtcXFxcd1xcXFwnJyxcXFxcL1xcXFwoXFxcXClcXFxcLSBdKylbO1xcXFwuXT8nLCAnXFxcXDEnLCAnZycpLGArXG4gIGAgJ1ssXFxcXC9cXFxcKFxcXFwpXFxcXC0gXSsnLCAnICcsICdnJykpICQkYCtcbiAgYCBMQU5HVUFHRSBTUUwgSU1NVVRBQkxFIFJFVFVSTlMgTlVMTCBPTiBOVUxMIElOUFVUO1xcbmA7XG59XG5cblxuZnVuY3Rpb24gY3JlYXRlVGFibGUodGFiOiBzdHJpbmcsIGNvbHM6IENvbXBvc2l0aW9uLCBvcHQ6IFNldHVwVGFibGVPcHRpb25zPXt9LCBhPScnKSB7XG4gIGNvbnN0IHByZSA9IFsnY29kZScsICduYW1lJywgJ3NjaWUnLCAnbGFuZycsICdncnVwJywgJ3JlZ24nLCAndGFncyddO1xuICBhICs9IGBDUkVBVEUgVEFCTEUgSUYgTk9UIEVYSVNUUyBcIiR7dGFifVwiIChgO1xuICBmb3IgKGNvbnN0IGMgb2YgcHJlKSB7XG4gICAgY29uc3QgdHlwID0gYz09PSdyZWduJz8gJ0lOVCc6J1RFWFQnO1xuICAgIGEgKz0gYCBcIiR7Y31cIiAke3R5cH0gTk9UIE5VTEwsYDtcbiAgfVxuICBmb3IgKGNvbnN0IGMgaW4gY29scykge1xuICAgIGlmIChwcmUuaW5jbHVkZXMoYykpIGNvbnRpbnVlO1xuICAgIGEgKz0gYCBcIiR7Y31cIiBSRUFMIE5PVCBOVUxMLGA7XG4gIH1cbiAgaWYgKG9wdC5waykgYSArPSBgIFBSSU1BUlkgS0VZIChcImNvZGVcIiksIGA7XG4gIGEgPSBhLmVuZHNXaXRoKCcsICcpPyBhLnN1YnN0cmluZygwLCBhLmxlbmd0aC0yKSA6IGE7XG4gIGEgKz0gYCk7XFxuYDtcbiAgcmV0dXJuIGE7XG59XG5cbmZ1bmN0aW9uIGluc2VydEludG9CZWdpbih0YWI6IHN0cmluZywgY29sczogQ29tcG9zaXRpb24sIGE9JycpIHtcbiAgYSArPSBgSU5TRVJUIElOVE8gXCIke3RhYn1cIiAoYDtcbiAgZm9yIChjb25zdCBjIGluIGNvbHMpXG4gICAgYSArPSBgXCIke2N9XCIsIGA7XG4gIGEgPSBhLmVuZHNXaXRoKCcsICcpPyBhLnN1YnN0cmluZygwLCBhLmxlbmd0aC0yKSA6IGE7XG4gIGEgKz0gJykgVkFMVUVTXFxuKCc7XG4gIHJldHVybiBhO1xufVxuXG5mdW5jdGlvbiBpbnNlcnRJbnRvTWlkKHZhbDogUmVjb3JkPHN0cmluZywgc3RyaW5nIHwgbnVtYmVyPiwgYT0nJykge1xuICBmb3IgKGNvbnN0IGsgaW4gdmFsKVxuICAgIGEgKz0gYCQkJHt2YWxba119JCQsIGA7XG4gIGEgPSBhLmVuZHNXaXRoKCcsICcpPyBhLnN1YnN0cmluZygwLCBhLmxlbmd0aC0yKSA6IGE7XG4gIGEgKz0gYCksXFxuKGA7XG4gIHJldHVybiBhO1xufVxuXG5mdW5jdGlvbiBpbnNlcnRJbnRvRW5kKGE9JycpIHtcbiAgYSA9IGEuZW5kc1dpdGgoJyxcXG4oJyk/IGEuc3Vic3RyaW5nKDAsIGEubGVuZ3RoLTMpIDogYTtcbiAgYSArPSAnO1xcbic7XG4gIHJldHVybiBhO1xufVxuXG5cblxuLyoqXG4gKiBPYnRhaW4gU1FMIGNvbW1hbmQgdG8gY3JlYXRlIGFuZCBwb3B1bGF0ZSB0aGUgY29tcG9zaXRpb25zIHRhYmxlLlxuICogQHBhcmFtIHRhYiB0YWJsZSBuYW1lXG4gKiBAcGFyYW0gb3B0IG9wdGlvbnMgZm9yIHRoZSB0YWJsZVxuICogQHJldHVybnMgQ1JFQVRFIFRBQkxFLCBJTlNFUlQsIENSRUFURSBWSUVXLCBDUkVBVEUgSU5ERVggc3RhdGVtZW50c1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY29tcG9zaXRpb25zU3FsKHRhYjogc3RyaW5nPVwiY29tcG9zaXRpb25zXCIsIG9wdDogU2V0dXBUYWJsZU9wdGlvbnM9e30pOiBQcm9taXNlPHN0cmluZz4ge1xuICBjb25zdCB0c3YgPSB0c3ZlY3Rvcih0YWIsIHtjb2RlOiAnQScsIG5hbWU6ICdCJywgc2NpZTogJ0InLCBsYW5nOiAnQicsIGdydXA6ICdDJywgdGFnczogJ0MnfSk7XG4gIG9wdCA9IE9iamVjdC5hc3NpZ24oe3BrOiAnY29kZScsIGluZGV4OiB0cnVlfSwgb3B0KTtcbiAgY29uc3QgbWFwICA9IGF3YWl0IGxvYWRDb21wb3NpdGlvbnMoKTtcbiAgY29uc3QgY29scyA9IG1hcC5nZXQoXCJBMDAxXCIpIGFzIENvbXBvc2l0aW9uO1xuICBsZXQgYSA9IGNyZWF0ZVRhYmxlKHRhYiwgY29scywgb3B0LCAnJyk7XG4gIGEgPSBpbnNlcnRJbnRvQmVnaW4odGFiLCBjb2xzLCBhKTtcbiAgZm9yIChjb25zdCBbLCByb3ddIG9mIG1hcClcbiAgICBhID0gaW5zZXJ0SW50b01pZChyb3cgYXMgdW5rbm93biBhcyBSZWNvcmQ8c3RyaW5nLCBzdHJpbmcgfCBudW1iZXI+LCBhKTtcbiAgYSA9IGluc2VydEludG9FbmQoYSk7XG4gIGEgKz0gY3JlYXRlRnVuY3Rpb25MYW5nVGFncyh0YWIpO1xuICBhICs9IGNyZWF0ZVZpZXcoYCR7dGFifV90c3ZlY3RvcmAsIGBTRUxFQ1QgKiwgJHt0c3Z9IEFTIFwidHN2ZWN0b3JcIiBGUk9NIFwiJHt0YWJ9XCJgKTtcbiAgYSArPSBjcmVhdGVJbmRleChgJHt0YWJ9X3RzdmVjdG9yX2lkeGAsIHRhYiwgYCgke3Rzdn0pYCwge21ldGhvZDogJ0dJTid9KTtcbiAgYSAgPSBzZXR1cFRhYmxlSW5kZXgodGFiLCBjb2xzIGFzIHVua25vd24gYXMgQ29sdW1uVHlwZXMsIG9wdCwgYSk7XG4gIHJldHVybiBhO1xufVxuXG5cbi8qKlxuICogRmluZCBtYXRjaGluZyBjb21wb3NpdGlvbnMgb2YgYSBjb2RlL25hbWUvc2NpZS9sYW5nL2dydXAvdGFncyBxdWVyeS5cbiAqIEBwYXJhbSB0eHQgY29kZS9uYW1lL3NjaWUvbGFuZy9ncnVwL3RhZ3MgcXVlcnlcbiAqIEByZXR1cm5zIG1hdGNoZXMgYFt7Y29kZSwgbmFtZSwgc2NpZSwgbGFuZywgZ3J1cCwgcmVnbiwgdGFncywgLi4ufV1gXG4gKiBAZXhhbXBsZVxuICogYGBgamF2YXNjcmlwdFxuICogaWZjdDIwMTcuY29tcG9zaXRpb25zKCdwaW5lYXBwbGUnKTtcbiAqIGlmY3QyMDE3LmNvbXBvc2l0aW9ucygnYW5hbmFzIGNvbW9zdXMnKTtcbiAqIC8vIOKGkiBbIHsgY29kZTogJ0UwNTMnLFxuICogLy8g4oaSICAgICBuYW1lOiAnUGluZWFwcGxlJyxcbiAqIC8vIOKGkiAgICAgc2NpZTogJ0FuYW5hcyBjb21vc3VzJyxcbiAqIC8vIOKGkiAgICAgbGFuZzogJ0EuIEFobmFyb3M7IEIuIEFuYXJhc2E7IEcuIEFuZW5hczsgSC4gQW5hbmFzOyBLYW4uIEFuYW5hczsgS2FzaC4gUHVuY2hpdGlwdWw7IEtoLiBTb2ggdHJ1bjsgS29uLiBBbmFzOyBNYWwuIEtheWlyaGEgY2hha2thOyBNLiBLaWhvbSBBbmFuYXM7IE8uIFNhcHVyaTsgUC4gQW5hbmFzOyBUYW0uIEFubmFzaSBwYXpoYW07IFRlbC4gQW5hc2EgcGFuZHU7IFUuIEFuYW5hcy4nLFxuICogLy8g4oaSICAgICAuLi4gfSBdXG4gKlxuICogaWZjdDIwMTcuY29tcG9zaXRpb25zKCd0ZWxsIG1lIGFib3V0IGNvdyBtaWxrLicpO1xuICogaWZjdDIwMTcuY29tcG9zaXRpb25zKCdnYWkga2EgZG9vZGggZGV0YWlscy4nKTtcbiAqIC8vIOKGkiBbIHsgY29kZTogJ0wwMDInLFxuICogLy8g4oaSICAgICBuYW1lOiAnTWlsaywgQ293JyxcbiAqIC8vIOKGkiAgICAgc2NpZTogJycsXG4gKiAvLyDihpIgICAgIGxhbmc6ICdBLiBHYXJvb3IgZ2FraGlyOyBCLiBEb29kaCAoZ2FydSk7IEcuIEdhaSBudSBkaHVkaDsgSC4gR2FpIGthIGRvb2RoOyBLYW4uIEhhc3V2aW5hIGhhbHU7IEthc2guIERvb2RoOyBLaC4gRHVkIG1hc2k7IE0uIFNhbiBTYW5naG9tOyBNYXIuIERvb2RoIChnYXkpOyBPLiBHYWkgZHVkaGE7IFAuIEdhYW4gZGEgZG9vZGg7IFMuIEdvdyBrc2hpcmFtOyBUYW0uIFBhc3VtcGFhbDsgVGVsLiBBYXZ1IHBhYWx1LicsXG4gKiAvLyDihpIgICAgIC4uLiB9IF1cbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gY29tcG9zaXRpb25zKHR4dDogc3RyaW5nKTogQ29tcG9zaXRpb25bXSB7XG4gIGlmIChpbmRleCA9PSBudWxsKSByZXR1cm4gW107XG4gIGNvbnN0IGE6IENvbXBvc2l0aW9uW10gPSBbXTsgdHh0ID0gdHh0LnJlcGxhY2UoL1xcVy9nLCAnICcpO1xuICBjb25zdCBtYXRzID0gaW5kZXguc2VhcmNoKHR4dCk7IGxldCBtYXggPSAwO1xuICBmb3IgKGNvbnN0IG1hdCBvZiBtYXRzKVxuICAgIG1heCA9IE1hdGgubWF4KG1heCwgT2JqZWN0LmtleXMobWF0Lm1hdGNoRGF0YS5tZXRhZGF0YSkubGVuZ3RoKTtcbiAgZm9yIChjb25zdCBtYXQgb2YgbWF0cylcbiAgICBpZiAoT2JqZWN0LmtleXMobWF0Lm1hdGNoRGF0YS5tZXRhZGF0YSkubGVuZ3RoID09PSBtYXgpIGEucHVzaChjb3JwdXM/LmdldChtYXQucmVmKSB8fCB7fSBhcyBDb21wb3NpdGlvbik7XG4gIHJldHVybiBhO1xufVxuLy8jZW5kcmVnaW9uXG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsc0NBQXNDO0FBQ3RDLDZDQUE2QztBQUM3Qyw2QkFBNkI7QUFDN0IsWUFBWSxTQUFVLFdBQVc7QUFDakMsT0FBTyxVQUFVLE9BQU8sQ0FBRSxzQ0FBc0M7QUFDaEUsU0FBa0QsVUFBVSxFQUFFLFdBQVcsRUFBRSxlQUFlLFFBQU8sbUJBQW1CO0FBcWJwSCxZQUFZO0FBS1osbUJBQW1CO0FBQ25CLE1BQU0sV0FBVyxJQUFJLElBQUk7RUFBQztFQUFRO0VBQVE7RUFBUTtFQUFRO0VBQVE7Q0FBTztBQUN6RSxZQUFZO0FBS1osaUJBQWlCO0FBQ2pCLElBQUksU0FBMEM7QUFDOUMsSUFBSSxRQUEyQjtBQUMvQixZQUFZO0FBS1osbUJBQW1CO0FBQ25CLGlDQUFpQztBQUNqQyxTQUFTLFNBQVMsR0FBMkI7RUFDM0MsTUFBTSxJQUFxQyxDQUFDO0VBQzVDLElBQUssTUFBTSxLQUFLLElBQUs7SUFDbkIsOENBQThDO0lBQzlDLE1BQU0sSUFBSSxFQUFFLFNBQVMsQ0FBQyxFQUFFLFdBQVcsQ0FBQyxPQUFLLEdBQUcsSUFBSTtJQUNoRCxDQUFDLENBQUMsRUFBRSxHQUFHLFNBQVMsR0FBRyxDQUFDLEtBQUksR0FBRyxDQUFDLEVBQUUsR0FBRyxXQUFXLEdBQUcsQ0FBQyxFQUFFO0VBQ3BEO0VBQ0EsT0FBTztBQUNUO0FBR0E7Ozs7Q0FJQyxHQUNELGVBQWUsWUFBWSxJQUFZO0VBQ3JDLE1BQU0sTUFBTyxJQUFJO0VBQ2pCLE1BQU0sT0FBTyxNQUFNLENBQUMsTUFBTSxNQUFNLEtBQUssRUFBRSxJQUFJO0VBQzNDLE1BQU0sVUFBVSxJQUFJLEtBQUssQ0FBQyxNQUFNO0lBQUMsY0FBYztJQUFNLFNBQVM7RUFBRztFQUNqRSxLQUFLLE1BQU0sS0FBSyxRQUNkLElBQUksR0FBRyxDQUFDLEVBQUUsSUFBSSxFQUFFLFNBQVM7RUFDM0IsT0FBTztBQUNUO0FBR0E7OztDQUdDLEdBQ0QsU0FBUyxXQUFXLE1BQWdDO0VBQ2xELE9BQU8sS0FBSztJQUNWLElBQUksQ0FBQyxHQUFHLENBQUM7SUFDVCxJQUFJLENBQUMsS0FBSyxDQUFDO0lBQ1gsSUFBSSxDQUFDLEtBQUssQ0FBQztJQUNYLElBQUksQ0FBQyxLQUFLLENBQUM7SUFDWCxJQUFJLENBQUMsS0FBSyxDQUFDO0lBQ1gsSUFBSSxDQUFDLEtBQUssQ0FBQztJQUNYLElBQUksQ0FBQyxLQUFLLENBQUM7SUFDWCxLQUFLLE1BQU0sS0FBSyxPQUFPLE1BQU0sR0FBSTtNQUMvQixJQUFJLEVBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUMsR0FBRztNQUMzQyxPQUFPLEtBQUssT0FBTyxDQUFDLFlBQVk7TUFDaEMsT0FBTyxLQUFLLE9BQU8sQ0FBQyxZQUFZO01BQ2hDLE9BQU8sS0FBSyxPQUFPLENBQUMscUNBQXFDO01BQ3pELE9BQU8sS0FBSyxPQUFPLENBQUMsa0JBQWtCO01BQ3RDLElBQUksQ0FBQyxHQUFHLENBQUM7UUFBQztRQUFNO1FBQU07UUFBTTtRQUFNO1FBQU07TUFBSTtJQUM5QztFQUNGO0FBQ0Y7QUFHQTs7O0NBR0MsR0FDRCxPQUFPLGVBQWU7RUFDcEIsSUFBSSxRQUFRLE9BQU87RUFDbkIsU0FBUyxNQUFNLFlBQVk7RUFDM0IsUUFBUyxXQUFXO0VBQ3BCLE9BQU87QUFDVDtBQUdBOzs7Q0FHQyxHQUNELE9BQU8sU0FBUztFQUNkLE9BQU8sWUFBWSxPQUFPLENBQUM7QUFDN0I7QUFHQSxTQUFTLFNBQVMsR0FBVyxFQUFFLElBQTRCO0VBQ3pELE1BQU0sRUFBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBQyxHQUFHO0VBQzdDLE9BQU8sQ0FBQywyQ0FBMkMsRUFBRSxLQUFLLElBQUksQ0FBQyxHQUMvRCxDQUFDLHNFQUFzRSxFQUFFLEtBQUssSUFBSSxDQUFDLEdBQ25GLENBQUMsMkNBQTJDLEVBQUUsS0FBSyxJQUFJLENBQUMsR0FDeEQsQ0FBQywyQ0FBMkMsRUFBRSxLQUFLLElBQUksQ0FBQyxHQUN4RCxDQUFDLGlDQUFpQyxFQUFFLElBQUksc0JBQXNCLEVBQUUsS0FBSyxJQUFJLENBQUMsR0FDMUUsQ0FBQywyQ0FBMkMsRUFBRSxLQUFLLElBQUksQ0FBQyxHQUN4RCxDQUFDLDJDQUEyQyxFQUFFLEtBQUssRUFBRSxDQUFDO0FBQ3hEO0FBR0EsU0FBUyx1QkFBdUIsR0FBVztFQUN6QyxPQUFPLENBQUMsNEJBQTRCLEVBQUUsSUFBSSxxQ0FBcUMsQ0FBQyxHQUNoRixDQUFDLCtEQUErRCxDQUFDLEdBQ2pFLENBQUMsbUZBQW1GLENBQUMsR0FDckYsQ0FBQyxtQ0FBbUMsQ0FBQyxHQUNyQyxDQUFDLHFEQUFxRCxDQUFDO0FBQ3pEO0FBR0EsU0FBUyxZQUFZLEdBQVcsRUFBRSxJQUFpQixFQUFFLE1BQXVCLENBQUMsQ0FBQyxFQUFFLElBQUUsRUFBRTtFQUNsRixNQUFNLE1BQU07SUFBQztJQUFRO0lBQVE7SUFBUTtJQUFRO0lBQVE7SUFBUTtHQUFPO0VBQ3BFLEtBQUssQ0FBQyw0QkFBNEIsRUFBRSxJQUFJLEdBQUcsQ0FBQztFQUM1QyxLQUFLLE1BQU0sS0FBSyxJQUFLO0lBQ25CLE1BQU0sTUFBTSxNQUFJLFNBQVEsUUFBTTtJQUM5QixLQUFLLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLElBQUksVUFBVSxDQUFDO0VBQ2pDO0VBQ0EsSUFBSyxNQUFNLEtBQUssS0FBTTtJQUNwQixJQUFJLElBQUksUUFBUSxDQUFDLElBQUk7SUFDckIsS0FBSyxDQUFDLEVBQUUsRUFBRSxFQUFFLGdCQUFnQixDQUFDO0VBQy9CO0VBQ0EsSUFBSSxJQUFJLEVBQUUsRUFBRSxLQUFLLENBQUMsdUJBQXVCLENBQUM7RUFDMUMsSUFBSSxFQUFFLFFBQVEsQ0FBQyxRQUFPLEVBQUUsU0FBUyxDQUFDLEdBQUcsRUFBRSxNQUFNLEdBQUMsS0FBSztFQUNuRCxLQUFLLENBQUMsSUFBSSxDQUFDO0VBQ1gsT0FBTztBQUNUO0FBRUEsU0FBUyxnQkFBZ0IsR0FBVyxFQUFFLElBQWlCLEVBQUUsSUFBRSxFQUFFO0VBQzNELEtBQUssQ0FBQyxhQUFhLEVBQUUsSUFBSSxHQUFHLENBQUM7RUFDN0IsSUFBSyxNQUFNLEtBQUssS0FDZCxLQUFLLENBQUMsQ0FBQyxFQUFFLEVBQUUsR0FBRyxDQUFDO0VBQ2pCLElBQUksRUFBRSxRQUFRLENBQUMsUUFBTyxFQUFFLFNBQVMsQ0FBQyxHQUFHLEVBQUUsTUFBTSxHQUFDLEtBQUs7RUFDbkQsS0FBSztFQUNMLE9BQU87QUFDVDtBQUVBLFNBQVMsY0FBYyxHQUFvQyxFQUFFLElBQUUsRUFBRTtFQUMvRCxJQUFLLE1BQU0sS0FBSyxJQUNkLEtBQUssQ0FBQyxFQUFFLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUM7RUFDeEIsSUFBSSxFQUFFLFFBQVEsQ0FBQyxRQUFPLEVBQUUsU0FBUyxDQUFDLEdBQUcsRUFBRSxNQUFNLEdBQUMsS0FBSztFQUNuRCxLQUFLLENBQUMsS0FBSyxDQUFDO0VBQ1osT0FBTztBQUNUO0FBRUEsU0FBUyxjQUFjLElBQUUsRUFBRTtFQUN6QixJQUFJLEVBQUUsUUFBUSxDQUFDLFVBQVMsRUFBRSxTQUFTLENBQUMsR0FBRyxFQUFFLE1BQU0sR0FBQyxLQUFLO0VBQ3JELEtBQUs7RUFDTCxPQUFPO0FBQ1Q7QUFJQTs7Ozs7Q0FLQyxHQUNELE9BQU8sZUFBZSxnQkFBZ0IsTUFBWSxjQUFjLEVBQUUsTUFBdUIsQ0FBQyxDQUFDO0VBQ3pGLE1BQU0sTUFBTSxTQUFTLEtBQUs7SUFBQyxNQUFNO0lBQUssTUFBTTtJQUFLLE1BQU07SUFBSyxNQUFNO0lBQUssTUFBTTtJQUFLLE1BQU07RUFBRztFQUMzRixNQUFNLE9BQU8sTUFBTSxDQUFDO0lBQUMsSUFBSTtJQUFRLE9BQU87RUFBSSxHQUFHO0VBQy9DLE1BQU0sTUFBTyxNQUFNO0VBQ25CLE1BQU0sT0FBTyxJQUFJLEdBQUcsQ0FBQztFQUNyQixJQUFJLElBQUksWUFBWSxLQUFLLE1BQU0sS0FBSztFQUNwQyxJQUFJLGdCQUFnQixLQUFLLE1BQU07RUFDL0IsS0FBSyxNQUFNLEdBQUcsSUFBSSxJQUFJLElBQ3BCLElBQUksY0FBYyxLQUFtRDtFQUN2RSxJQUFJLGNBQWM7RUFDbEIsS0FBSyx1QkFBdUI7RUFDNUIsS0FBSyxXQUFXLEdBQUcsSUFBSSxTQUFTLENBQUMsRUFBRSxDQUFDLFVBQVUsRUFBRSxJQUFJLHFCQUFxQixFQUFFLElBQUksQ0FBQyxDQUFDO0VBQ2pGLEtBQUssWUFBWSxHQUFHLElBQUksYUFBYSxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQyxFQUFFO0lBQUMsUUFBUTtFQUFLO0VBQ3ZFLElBQUssZ0JBQWdCLEtBQUssTUFBZ0MsS0FBSztFQUMvRCxPQUFPO0FBQ1Q7QUFHQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztDQXNCQyxHQUNELE9BQU8sU0FBUyxhQUFhLEdBQVc7RUFDdEMsSUFBSSxTQUFTLE1BQU0sT0FBTyxFQUFFO0VBQzVCLE1BQU0sSUFBbUIsRUFBRTtFQUFFLE1BQU0sSUFBSSxPQUFPLENBQUMsT0FBTztFQUN0RCxNQUFNLE9BQU8sTUFBTSxNQUFNLENBQUM7RUFBTSxJQUFJLE1BQU07RUFDMUMsS0FBSyxNQUFNLE9BQU8sS0FDaEIsTUFBTSxLQUFLLEdBQUcsQ0FBQyxLQUFLLE9BQU8sSUFBSSxDQUFDLElBQUksU0FBUyxDQUFDLFFBQVEsRUFBRSxNQUFNO0VBQ2hFLEtBQUssTUFBTSxPQUFPLEtBQ2hCLElBQUksT0FBTyxJQUFJLENBQUMsSUFBSSxTQUFTLENBQUMsUUFBUSxFQUFFLE1BQU0sS0FBSyxLQUFLLEVBQUUsSUFBSSxDQUFDLFFBQVEsSUFBSSxJQUFJLEdBQUcsS0FBSyxDQUFDO0VBQzFGLE9BQU87QUFDVCxFQUNBLFlBQVkifQ==
@@ -0,0 +1,103 @@
1
+ import * as path from "@std/path";
2
+ import * as csv from "@std/csv";
3
+
4
+
5
+ const BASE = ['code', 'name', 'scie', 'lang', 'grup', 'regn', 'tags'];
6
+
7
+
8
+ /** Round a number to up to 12 significant digits. */
9
+ function round(val: number) {
10
+ return Math.round(val * 1e+12) / 1e+12;
11
+ }
12
+
13
+
14
+ /** Add the composition of one row to a sum row. */
15
+ function addCompositionRow(sum: Record<string, string | number>, row: Record<string, string | number>) {
16
+ for (const k in row) {
17
+ if (typeof row[k] !== "number") continue;
18
+ (sum[k] as number) += row[k];
19
+ }
20
+ }
21
+
22
+
23
+ /** Update the minimum composition after comparing with one row. */
24
+ function minCompositionRow(min: Record<string, string | number>, row: Record<string, string | number>) {
25
+ for (const k in row) {
26
+ if (typeof row[k] !== "number") continue;
27
+ if ((min[k] as number) > row[k]) min[k] = row[k];
28
+ }
29
+ }
30
+
31
+
32
+ /** Update the maximum composition after comparing with one row. */
33
+ function maxCompositionRow(max: Record<string, string | number>, row: Record<string, string | number>) {
34
+ for (const k in row) {
35
+ if (typeof row[k] !== "number") continue;
36
+ if ((max[k] as number) < row[k]) max[k] = row[k];
37
+ }
38
+ }
39
+
40
+ /** Multiply a factor to the composition of one row. */
41
+ function multiplyCompositionRow(row: Record<string, string | number>, n: number) {
42
+ for (const k in row) {
43
+ if (typeof row[k] !== "number") continue;
44
+ row[k] = row[k] * n;
45
+ }
46
+ }
47
+
48
+
49
+ /** Format a specific composition row. */
50
+ function formatCompositionRow(row: Record<string, string | number>, code: string, name: string) {
51
+ row.code = code;
52
+ row.name = name;
53
+ row.scie = "";
54
+ row.lang = "";
55
+ row.grup = "";
56
+ row.regn = 0;
57
+ row.tags = "";
58
+ }
59
+
60
+
61
+ /** Get the minimum, maximum and average composition of all foods. */
62
+ async function minMaxAvgComposition() {
63
+ // Load the compositions of all foods.
64
+ const data = await Deno.readTextFile(path.join(import.meta.dirname || "", "../compositions/index.csv"));
65
+ const records: Record<string, string | number>[] = csv.parse(data, {skipFirstRow: true, comment: "#"});
66
+ for (const row of records) {
67
+ for (const k in row) {
68
+ if (BASE.includes(k) && k!=="regn") continue;
69
+ row[k] = parseFloat(row[k] as string);
70
+ }
71
+ }
72
+ // Find the mean composition of all foods.
73
+ const avg = Object.assign({}, records[0]);
74
+ const min = Object.assign({}, records[0]);
75
+ const max = Object.assign({}, records[0]);
76
+ for (const row of records.slice(1)) {
77
+ addCompositionRow(avg, row);
78
+ minCompositionRow(min, row);
79
+ maxCompositionRow(max, row);
80
+ }
81
+ multiplyCompositionRow(avg, 1 / records.length);
82
+ // Format the mean composition, and return it.
83
+ formatCompositionRow(min, "XMIN", "Minimum composition of all foods");
84
+ formatCompositionRow(max, "XMAX", "Maximum composition of all foods");
85
+ formatCompositionRow(avg, "XAVG", "Average composition of all foods");
86
+ return [min, max, avg];
87
+ }
88
+
89
+
90
+ /** Generate the stats CSV file. */
91
+ async function writeIndex() {
92
+ const [min, max, avg] = await minMaxAvgComposition();
93
+ const keys = Object.keys(min);
94
+ const data = keys.join(",") + "\n" + [min, max, avg].map(row => {
95
+ return keys.map(k => typeof row[k] === "number"? `${round(row[k] as number)}` : `"${row[k]}"`);
96
+ }).join("\n") + "\n";
97
+ await Deno.writeTextFile(path.join(import.meta.dirname || "", "index.csv"), data);
98
+ }
99
+
100
+
101
+ export async function build() {
102
+ await writeIndex();
103
+ }
@@ -0,0 +1,4 @@
1
+ code,name,scie,lang,grup,regn,tags,enerc,enerc_e,water,water_e,ash,ash_e,vit,vit_e,fatce,fatce_e,cholc,cholc_e,fibtg,fibtg_e,choavldf,choavldf_e,protcnt,protcnt_e,amiac,amiac_e,cartoid,cartoid_e,polyph,polyph_e,phystr,phystr_e,tocph,tocph_e,toctr,toctr_e,orgac,orgac_e,phytac,phytac_e,sapon,sapon_e,mnrleq,mnrleq_e,mnrlet,mnrlet_e,mnrlpet,mnrlpet_e,mnrlnet,mnrlnet_e,mnrltx,mnrltx_e,vita,vita_e,vitb,vitb_e,vitc,vitc_e,vitd,vitd_e,vite,vite_e,vitk,vitk_e,fasat,fasat_e,fauns,fauns_e,faess,faess_e,facis,facis_e,fatrn,fatrn_e,fams,fams_e,fapu,fapu_e,facn3,facn3_e,facn6,facn6_e,facn9,facn9_e,facn5,facn5_e,facn7,facn7_e,fibins,fibins_e,fibsol,fibsol_e,cho,cho_e,starch,starch_e,olsac,olsac_e,fsugar,fsugar_e,amiace,amiace_e,amiacce,amiacce_e,amiacne,amiacne_e,retol,retol_e,thia,thia_e,ribf,ribf_e,nia,nia_e,pantac,pantac_e,vitb6c,vitb6c_e,biot,biot_e,folsum,folsum_e,ergcal,ergcal_e,chocal,chocal_e,doh25,doh25_e,tocpha,tocpha_e,tocphb,tocphb_e,tocphg,tocphg_e,tocphd,tocphd_e,toctra,toctra_e,toctrb,toctrb_e,toctrg,toctrg_e,toctrd,toctrd_e,vitk1,vitk1_e,vitk2,vitk2_e,lutn,lutn_e,zea,zea_e,lycpn,lycpn_e,crypxb,crypxb_e,cartg,cartg_e,carta,carta_e,cartb,cartb_e,al,al_e,as,as_e,cd,cd_e,ca,ca_e,cr,cr_e,co,co_e,cu,cu_e,fe,fe_e,pb,pb_e,li,li_e,mg,mg_e,mn,mn_e,hg,hg_e,mo,mo_e,ni,ni_e,p,p_e,k,k_e,se,se_e,na,na_e,zn,zn_e,frus,frus_e,glus,glus_e,sucs,sucs_e,mals,mals_e,lactose,lactose_e,f4d0,f4d0_e,f6d0,f6d0_e,f8d0,f8d0_e,f10d0,f10d0_e,f12d0,f12d0_e,f14d0,f14d0_e,f16d0,f16d0_e,f18d0,f18d0_e,f20d0,f20d0_e,f22d0,f22d0_e,f24d0,f24d0_e,f14d1cn5,f14d1cn5_e,f16d1cn7,f16d1cn7_e,f18d1cn9,f18d1cn9_e,f18d1tn9,f18d1tn9_e,f20d1cn9,f20d1cn9_e,f22d1cn9,f22d1cn9_e,f24d1cn9,f24d1cn9_e,f18d2cn6,f18d2cn6_e,f20d2n6,f20d2n6_e,f18d3n3,f18d3n3_e,f20d4n6,f20d4n6_e,f11d0,f11d0_e,f15d0,f15d0_e,f20d3n6,f20d3n6_e,f20d5n3,f20d5n3_e,f22d6n3,f22d6n3_e,f22d2n6,f22d2n6_e,f22d5n3,f22d5n3_e,his,his_e,ile,ile_e,leu,leu_e,lys,lys_e,met,met_e,cys,cys_e,phe,phe_e,thr,thr_e,trp,trp_e,val,val_e,ala,ala_e,arg,arg_e,asp,asp_e,glu,glu_e,gly,gly_e,pro,pro_e,ser,ser_e,tyr,tyr_e,oxalt,oxalt_e,oxals,oxals_e,oxali,oxali_e,caconac,caconac_e,citac,citac_e,fumac,fumac_e,malac,malac_e,quinac,quinac_e,sucac,sucac_e,tarac,tarac_e,dhbenzac34,dhbenzac34_e,hbenzal3,hbenzal3_e,pcathac,pcathac_e,vanlac,vanlac_e,gallac,gallac_e,cinmac,cinmac_e,coumaco,coumaco_e,coumacp,coumacp_e,caffac,caffac_e,chlrac,chlrac_e,ferac,ferac_e,apigen,apigen_e,apigen6cgls,apigen6cgls_e,apigen7onshps,apigen7onshps_e,luteol,luteol_e,kaemf,kaemf_e,querce,querce_e,querce3bdgls,querce3bdgls_e,querce3ortns,querce3ortns_e,querce3bgls,querce3bgls_e,isormt,isormt_e,myrct,myrct_e,rsvrtol,rsvrtol_e,hespt,hespt_e,narng,narng_e,hespd,hespd_e,daidzn,daidzn_e,gnstein,gnstein_e,epicatec,epicatec_e,epicategc,epicategc_e,epicatgc3gal,epicatgc3gal_e,catec,catec_e,galcatecgal,galcatecgal_e,galcatec,galcatec_e,syrgac,syrgac_e,sinpac,sinpac_e,ellgac,ellgac_e,rafs,rafs_e,stas,stas_e,vers,vers_e,ajgs,ajgs_e,camt,camt_e,stgstr,stgstr_e,stostrb,stostrb_e,carot,carot_e,xantp,xantp_e,cartbeq,cartbeq_e
2
+ "XMIN","Minimum composition of all foods","","","",0,"",0,0,0,0,0,0,0,0,0.03,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
3
+ "XMAX","Maximum composition of all foods","","","",0,"",2809,86,95.77,2.78,8.18,0.58,0.32140922,0.03055704,100.01,6.74,1.668,0.0708,47.55,3.04,84.87,2.64,37.8,3.65,36.46188,3.371856,0.101812,0.007172,2.986,0.0277,0.3836,0.00616,0.04922,0.01087,0.01036,0.00016,4.0742,0.82922,1.974,0.0707,88.76,4.5,3.713,0.5461,0.07306875,0.01744046,0.004383,0.000402,0.01384,0.00352,0.01289896,0.00138569,0.017542,0.001836,0.320771,0.023911,0.252,0.0304,0.000118,0.0000051,0.03509,0.00713,0.000574,0.0000373,90.86,4.13,94.28,3.87,76.71,2.17,94.28,3.89,4.68,0.92,67.09,1.88,76.78,2.16,12.956,0.467,76.58,1.94,66.93,1.75,0.95,0.17,2.225,0.436,35.64,2.29,19.92,2.42,84.32,5.71,76.14,5.73,5.05,0.965,84.32,3.22,15.16158,1.566528,19.922544,1.088958,14.03514,1.323576,0.015655,0.000972,0.00098,0.000144,0.00083,0.00012,0.01566,0.0022,0.00932,0.0007,0.316,0.0233,0.002875,0.000305,0.001032,0.0000296,0.000118,0.0000051,0.00000903,6e-7,0.00000798,0.000001,0.03174,0.00684,0.00588,0.00069,0.00962,0.00319,0.0027,0.00023,0.01036,0.00016,0.00112,0.00002,0.00047,0.00009,0.00074,0.00004,0.000574,0.0000373,0.000297,0.00000652,0.01558,0.00376,0.002712,0.000789,0.002843,0.000495,0.001599,0.000203,0.00000937,0.00000116,0.002654,0.000524,0.017542,0.001836,0.01384,0.00352,0.00001101,0.00001033,0.003591,0.000021,1.664,0.329,0.001227,0.000072,0.001501,0.000093,0.00672,0.00199,0.05311,0.01721,0.009301,0.001381,0.004383,0.000402,0.442,0.0693,0.06186,0.00579,0.00001458,0.00000483,0.000839,0.000447,0.005183,0.001461,0.804,0.139,2.374,0.425,0.000206,0.0000476,0.849,0.0384,0.00867,0.00197,26.54,1.92,16.22,2.03,58.23,2.94,0.31,0.18,12.86,1.03,0.22,0.08,0.3,0.13,2.76,0.37,5.18,0.34,49.57,0.81,21.12,0.67,53.1,1.55,13.89,1.17,1.39,0.51,2.66,0.32,1.25,0.13,0.95,0.17,2.225,0.436,53.89,1.75,4.68,0.92,5.45,0.25,51.3,0.96,0.644,0.0336,76.58,1.94,0.301,0.104,12.956,0.467,0.889,0.277,0.0012,0,0.09084,0.01609,0.07414,0.02347,0.925,0.12,1.192,0.286,0.104,0.0281,0.329,0.0464,1.42096,0.19355,1.73502,0.265068,3.07692,0.250428,2.728986,0.256536,1.523914,0.166953,2.982123,0.17808,1.90092,0.308259,1.519,0.46134,0.63504,0.164082,2.09034,0.305664,2.335168,0.24738,16.270848,0.463294,4.3092,0.646848,6.500466,0.548504,2.131922,0.480792,2.922609,0.335101,1.746978,0.316647,1.374676,0.24745,2.472,0.794,1.471,0.619,2.078,0.792,0.44,0.00775,3.49,0.176,0.111,0.04184,0.436,0.113,0.651,0.0405,0.652,0.0738,0.382,0.0759,0.0067,0.00086,0.00044,0.00002,0.0097,0.00117,0.0049,0.00087,0.09312,0.00437,0.00336,0.00115,0.00047,0.00015,0.00742,0.00144,0.01604,0.00116,0.04823,0.00477,0.03633,0.00234,0.01614,0.00342,0.00256,0.00036,0.03049,0.00419,0.0059,0.00096,0.03568,0.00305,0.08633,0.0026,0.01237,0.00095,0.03283,0.00221,0.00436,0.00054,0.01221,0.00186,0.00885,0.00256,0.00182,0.00061,0.03719,0.02106,0.01273,0.00122,0.02413,0.00265,0.03171,0.00194,0.0563,0.00241,0.03805,0.00213,0.00279,0.00062,0.00301,0.00121,0.01663,0.00262,0.00055,0.00012,0.0097,0.0001,0.01097,0.00219,0.06572,0.0017,0.03477,0.00157,4.21,0.741,5,0.565,1.57,0.308,0.06,0.03,0.06385,0.00285,0.04617,0.00238,0.369,0.0051,0.017542,0.001836,0.015815,0.0037794,0.017542,0.001836
4
+ "XAVG","Average composition of all foods","","","",0,"",531.675276752768,7.411439114391,66.378210332103,0.321881918819,1.346992619926,0.054114391144,0.045441580498,0.001786161937,6.820830258303,0.167103321033,0.057157675277,0.000985405904,3.881236162362,0.125129151292,10.822177121771,0.28241697417,10.685313653137,0.208819188192,10.379116704797,0.359198186347,0.001322534889,0.00011182928,0.062296531365,0.001389667897,0.023685387454,0.000523708487,0.001070848708,0.000105940959,0.000058653137,0.000004132841,0.221295498155,0.016719538745,0.101828523985,0.00298601476,0.592029520295,0.039778597786,0.6885899631,0.045871660517,0.00511559941,0.000643575972,0.000025867159,0.000001774908,0.000650793358,0.00013,0.000053346827,0.000006094151,0.000504881624,0.000045787768,0.031501549945,0.000470124114,0.012677804428,0.001200129151,0.000005355886,2.6452e-7,0.000720442804,0.000068523985,0.000031545812,0.000001332399,1.928454483395,0.077401291513,4.084778487085,0.131894704797,1.995236402214,0.062700405904,4.076256826568,0.142752177122,0.009446494465,0.001863468635,2.074504686347,0.071975202952,2.010273800738,0.059919501845,0.247640405904,0.014237822878,1.762464667897,0.049977103321,1.982053118081,0.071972675277,0.002050719557,0.000327250923,0.082047915129,0.006237324723,3.040184501845,0.109833948339,0.854040590406,0.079870848708,9.184483394834,0.307306273063,6.712896678967,0.245719557196,0.132546125461,0.019031365314,2.468025830258,0.083966789668,4.409193750923,0.146951557196,2.821761088561,0.09404050738,3.148161865314,0.118206121771,0.000123341494,0.000006584982,0.000106621771,0.000010206642,0.000092553506,0.000007678967,0.001724391144,0.000082749077,0.000816143911,0.000037287823,0.028447607011,0.000324987085,0.000280367196,0.000004970406,0.000033865406,0.000002244114,0.000004832878,2.54723e-7,4.50074e-7,6.605e-9,7.2934e-8,3.192e-9,0.000711199262,0.000064594096,0.000053357934,0.000008154982,0.000273413284,0.000030202952,0.000032878229,0.00000298893,0.000038265683,0.000002490775,0.000005535055,3.50554e-7,0.000005940959,9.04059e-7,0.000008911439,3.87454e-7,0.000027419391,0.000001220701,0.000004126421,1.11697e-7,0.000307164742,0.000040320554,0.000018195424,0.000003349465,0.000021637288,0.000003903137,0.000005545461,7.13173e-7,4.1494e-8,4.576e-9,0.000009908542,0.000001636162,0.000366044631,0.000036848875,0.000650793358,0.00013,5.9048e-7,1.42066e-7,0.000021645756,3.32103e-7,0.070913597786,0.006830719557,0.000015725092,0.000003038745,0.000009756458,0.000001228782,0.000313431734,0.000047675277,0.002745608856,0.00037297048,0.000030828413,0.0000055369,0.000025867159,0.000001774908,0.053817785978,0.005219335793,0.000761900369,0.000098154982,2.82177e-7,8.3081e-8,0.00001797048,0.000005787823,0.000048230627,0.000010876384,0.155343800738,0.009320424354,0.370008265683,0.022572933579,0.000018031144,0.00000181398,0.038506512915,0.001928247232,0.001184944649,0.00010202952,1.026254612546,0.042011070111,0.55979704797,0.031439114391,0.822988929889,0.036143911439,0.003653136531,0.000848708487,0.056051660517,0.002712177122,0.000405904059,0.000147601476,0.000553505535,0.000239852399,0.005959409594,0.001051660517,0.022592841328,0.00125501845,0.178900645756,0.004242343173,0.153351217712,0.010136088561,1.106489335793,0.043110664207,0.389203726937,0.029667841328,0.029211826568,0.003809095941,0.023087564576,0.002236845018,0.013980295203,0.002050313653,0.002050719557,0.000327250923,0.082047915129,0.006237324723,1.82366097786,0.065656660517,0.009446494465,0.001863468635,0.032746826568,0.002678634686,0.12198704797,0.003324926199,0.003658265683,0.000312453875,1.711569151292,0.043806660517,0.004728247232,0.000749391144,0.163575701107,0.009347638376,0.043867177122,0.005162121771,0.000011439114,0,0.002214907749,0.000160092251,0.00187097786,0.000207084871,0.020172084871,0.001227804428,0.056052287823,0.003156180812,0.000429114391,0.000051845018,0.007840332103,0.000506199262,0.380198062731,0.013782265683,0.422405129151,0.017036332103,0.776190909594,0.018097686347,0.68905852583,0.016283725092,0.377521158672,0.012562291513,0.42550998524,0.0115624631,0.590004437269,0.027339854244,0.507943354244,0.016019658672,0.123840125461,0.006893795203,0.54203204797,0.018935948339,0.483470437269,0.021421059041,0.961419872694,0.027794542435,0.913836976015,0.037126964945,1.244438809963,0.040532719557,0.543566933579,0.019496407749,0.477433852399,0.018595780443,0.506415642066,0.019125378229,0.413830444649,0.016591313653,0.079901605166,0.010360295203,0.023037878229,0.002893191882,0.056048634686,0.008533800738,0.002785092251,0.000140221402,0.059689944649,0.001642416974,0.00487298893,0.000508228782,0.028648745387,0.001501383764,0.014982177122,0.000609815498,0.021770774908,0.001118690037,0.008644169742,0.000838487085,0.000102896679,0.000011568266,0.000001734317,1.10701e-7,0.000246346863,0.000027933579,0.000121771218,0.000018892989,0.000335811808,0.000029815498,0.000029317343,0.000008708487,0.000003726937,3.13653e-7,0.000386199262,0.00004204797,0.000466199262,0.000049077491,0.000750571956,0.000082490775,0.000331180812,0.000034520295,0.000286900369,0.000042232472,0.000008782288,0.000001309963,0.000402140221,0.00004204797,0.000166107011,0.000018782288,0.000398339483,0.000033763838,0.000554538745,0.000028099631,0.000269372694,0.000022158672,0.000307859779,0.000028911439,0.000050738007,0.000005350554,0.00011202952,0.000010793358,0.000145608856,0.000018118081,0.000008745387,0.000001678967,0.000132066421,0.000049594096,0.000039409594,0.000003782288,0.000102878229,0.000006771218,0.0001149631,0.000004169742,0.000194630996,0.000004723247,0.000281328413,0.000018653137,0.000023505535,0.000002490775,0.00004302583,0.000003892989,0.000370332103,0.000030516605,0.000001586716,2.95203e-7,0.000019667897,3.50554e-7,0.000106143911,0.000010830258,0.0002000369,0.000007490775,0.000103413284,0.000006365314,0.058450184502,0.009239852399,0.058763837638,0.006922509225,0.015055350554,0.002704797048,0.000276752768,0.000164206642,0.002187416974,0.000063450185,0.002283690037,0.000066715867,0.019214280443,0.000393542435,0.000397631956,0.000042392749,0.000330905627,0.000044383192,0.000381540129,0.000039202786