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.
- package/LICENSE +661 -21
- package/README.md +1019 -71
- package/abbreviations/index.csv +78 -0
- package/abbreviations/index.d.ts +39 -0
- package/abbreviations/index.js +103 -0
- package/abbreviations/index.txt +12 -0
- package/about/build.ts +31 -0
- package/about/index.d.ts +47 -0
- package/about/index.js +110 -0
- package/about/index.txt +174 -0
- package/build.ts +115 -0
- package/carbohydrates/index.csv +8 -0
- package/carbohydrates/index.d.ts +42 -0
- package/carbohydrates/index.js +112 -0
- package/carbohydrates/index.txt +14 -0
- package/codes/index.csv +2904 -0
- package/codes/index.d.ts +36 -0
- package/codes/index.js +102 -0
- package/codes/index.txt +12 -0
- package/columndescriptions/build.ts +22 -0
- package/columndescriptions/index.csv +215 -0
- package/columndescriptions/index.d.ts +44 -0
- package/columndescriptions/index.js +119 -0
- package/columns/build.ts +23 -0
- package/columns/index.csv +215 -0
- package/columns/index.d.ts +39 -0
- package/columns/index.js +111 -0
- package/columns/index.txt +71 -0
- package/compositingcentres/index.csv +7 -0
- package/compositingcentres/index.d.ts +35 -0
- package/compositingcentres/index.js +103 -0
- package/compositingcentres/index.txt +13 -0
- package/compositions/build.ts +212 -0
- package/compositions/index.csv +543 -0
- package/compositions/index.d.ts +254 -0
- package/compositions/index.js +204 -0
- package/compositionstats/build.ts +103 -0
- package/compositionstats/index.csv +4 -0
- package/compositionstats/index.d.ts +31 -0
- package/compositionstats/index.js +97 -0
- package/contents/index.csv +21 -0
- package/contents/index.d.ts +39 -0
- package/contents/index.js +102 -0
- package/contents/index.txt +13 -0
- package/deno.lock +67 -0
- package/descriptions/index.csv +543 -0
- package/descriptions/index.d.ts +45 -0
- package/descriptions/index.js +124 -0
- package/descriptions/index.txt +15 -0
- package/energies/index.csv +6 -0
- package/energies/index.d.ts +34 -0
- package/energies/index.js +101 -0
- package/energies/index.txt +13 -0
- package/frequencydistribution/index.csv +10 -0
- package/frequencydistribution/index.d.ts +36 -0
- package/frequencydistribution/index.js +90 -0
- package/frequencydistribution/index.txt +14 -0
- package/groups/index.csv +21 -0
- package/groups/index.d.ts +46 -0
- package/groups/index.js +118 -0
- package/groups/index.txt +14 -0
- package/hierarchy/asset.csv +215 -0
- package/hierarchy/asset.txt +70 -0
- package/hierarchy/build.ts +73 -0
- package/hierarchy/index.csv +215 -0
- package/hierarchy/index.d.ts +39 -0
- package/hierarchy/index.js +100 -0
- package/hierarchy/index.txt +14 -0
- package/index.d.ts +24 -28
- package/index.js +28 -39
- package/index.test.ts +717 -0
- package/intakes/build.ts +28 -0
- package/intakes/index.csv +42 -0
- package/intakes/index.d.ts +66 -0
- package/intakes/index.js +113 -0
- package/intakes/index.txt +20 -0
- package/jonesfactors/index.csv +15 -0
- package/jonesfactors/index.d.ts +35 -0
- package/jonesfactors/index.js +105 -0
- package/jonesfactors/index.txt +12 -0
- package/languages/index.csv +22 -0
- package/languages/index.d.ts +39 -0
- package/languages/index.js +103 -0
- package/languages/index.txt +12 -0
- package/methods/build.ts +101 -0
- package/methods/index.csv +37 -0
- package/methods/index.d.ts +39 -0
- package/methods/index.js +196 -0
- package/methods/index.txt +13 -0
- package/package.json +15 -63
- package/regions/index.csv +7 -0
- package/regions/index.d.ts +36 -0
- package/regions/index.js +100 -0
- package/regions/index.txt +12 -0
- package/representations/build.ts +133 -0
- package/representations/index.csv +215 -0
- package/representations/index.d.ts +36 -0
- package/representations/index.js +91 -0
- package/retentionfactors/groups.csv +21 -0
- package/retentionfactors/index.csv +215 -0
- package/samplingunits/index.csv +36 -0
- package/samplingunits/index.d.ts +39 -0
- package/samplingunits/index.js +110 -0
- package/samplingunits/index.txt +14 -0
- package/yieldfactors/index.csv +543 -0
- package/yieldfactors/index.d.ts +57 -0
- package/yieldfactors/index.js +158 -0
- package/yieldfactors/index.txt +294 -0
- package/corpus.js +0 -6
- package/corpus.min.js +0 -1
- 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/LmdldChtYXQucmVmKSB8fCB7fSBhcyBDb21wb3NpdGlvbik7XG4gIHJldHVybiBhO1xufVxuLy8jZW5kcmVnaW9uXG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsc0NBQXNDO0FBQ3RDLDZDQUE2QztBQUM3Qyw2QkFBNkI7QUFDN0IsWUFBWSxTQUFVLFdBQVc7QUFDakMsT0FBTyxVQUFVLE9BQU8sQ0FBRSxzQ0FBc0M7QUFDaEUsU0FBa0QsVUFBVSxFQUFFLFdBQVcsRUFBRSxlQUFlLFFBQU8sbUJBQW1CO0FBcWJwSCxZQUFZO0FBS1osbUJBQW1CO0FBQ25CLE1BQU0sV0FBVyxJQUFJLElBQUk7RUFBQztFQUFRO0VBQVE7RUFBUTtFQUFRO0VBQVE7Q0FBTztBQUN6RSxZQUFZO0FBS1osaUJBQWlCO0FBQ2pCLElBQUksU0FBMEM7QUFDOUMsSUFBSSxRQUEyQjtBQUMvQixZQUFZO0FBS1osbUJBQW1CO0FBQ25CLGlDQUFpQztBQUNqQyxTQUFTLFNBQVMsR0FBMkI7RUFDM0MsTUFBTSxJQUFxQyxDQUFDO0VBQzVDLElBQUssTUFBTSxLQUFLLElBQUs7SUFDbkIsOENBQThDO0lBQzlDLE1BQU0sSUFBSSxFQUFFLFNBQVMsQ0FBQyxFQUFFLFdBQVcsQ0FBQyxPQUFLLEdBQUcsSUFBSTtJQUNoRCxDQUFDLENBQUMsRUFBRSxH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
|
|
@@ -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
|