ifct2017 2.0.15 → 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,35 @@
1
+ import { type SetupTableOptions } from "@nodef/extra-sql";
2
+ /** Regional compositing centre and sample size of each region. */ export interface CompositingCentre {
3
+ /** Region. */ region: string;
4
+ /** Regional Compositing centre. */ centre: string;
5
+ /** Sample size. */ samples: number;
6
+ }
7
+ /**
8
+ * Load the compositing centres corpus from the file.
9
+ * @returns compositing centres corpus
10
+ */ export declare function loadCompositingCentres(): Promise<Map<string, CompositingCentre>>;
11
+ /**
12
+ * Get the path to the compositing centres CSV file.
13
+ * @returns CSV file URL
14
+ */ export declare function compositingCentresCsv(): string;
15
+ /**
16
+ * Obtain SQL command to create and populate the compositing centres table.
17
+ * @param tab table name
18
+ * @param opt options for the table
19
+ * @returns CREATE TABLE, INSERT, CREATE VIEW, CREATE INDEX statements
20
+ */ export declare function compositingCentresSql(tab?: string, opt?: SetupTableOptions): Promise<string>;
21
+ /**
22
+ * Find matching compositing centres of a region/centre query.
23
+ * @param txt region/centre query
24
+ * @returns matches `[{region, centre, samples}]`
25
+ * @examples
26
+ * ```javascript
27
+ * ifct2017.compositingCentres('west');
28
+ * ifct2017.compositingCentres('Mumbai');
29
+ * // → [ { region: 'West', centre: 'Mumbai', samples: 12 } ]
30
+ *
31
+ * ifct2017.compositingCentres('what is compositing centre of north east?');
32
+ * ifct2017.compositingCentres('North East compositing centre');
33
+ * // → [ { region: 'North East', centre: 'Guwahati', samples: 11 } ]
34
+ * ```
35
+ */ export declare function compositingCentres(txt: string): CompositingCentre[];
@@ -0,0 +1,103 @@
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 { setupTable } from "@nodef/extra-sql";
7
+ //#endregion
8
+ //#region GLOBALS
9
+ let corpus = null;
10
+ let index = null;
11
+ //#endregion
12
+ //#region FUNCTIONS
13
+ /**
14
+ * Load the compositing centres corpus from CSV file.
15
+ * @param file CSV file path
16
+ * @returns compositing centres corpus
17
+ */ async function loadFromCsv(file) {
18
+ const map = new Map();
19
+ const data = await (await fetch(file)).text();
20
+ const records = csv.parse(data, {
21
+ skipFirstRow: true,
22
+ comment: "#"
23
+ });
24
+ for (const r of records){
25
+ const samples = parseFloat(r.samples);
26
+ map.set(r.region, {
27
+ region: r.region,
28
+ centre: r.centre,
29
+ samples
30
+ });
31
+ }
32
+ return map;
33
+ }
34
+ /**
35
+ * Setup the lunr index for the compositing centres corpus.
36
+ * @returns lunr index
37
+ */ function setupIndex(corpus) {
38
+ return lunr(function() {
39
+ this.ref('region');
40
+ this.field('region');
41
+ this.field('centre');
42
+ for (const r of corpus.values())this.add(r);
43
+ });
44
+ }
45
+ /**
46
+ * Load the compositing centres corpus from the file.
47
+ * @returns compositing centres corpus
48
+ */ export async function loadCompositingCentres() {
49
+ if (corpus) return corpus;
50
+ corpus = await loadFromCsv(compositingCentresCsv());
51
+ index = setupIndex(corpus);
52
+ return corpus;
53
+ }
54
+ /**
55
+ * Get the path to the compositing centres CSV file.
56
+ * @returns CSV file URL
57
+ */ export function compositingCentresCsv() {
58
+ return import.meta.resolve('./index.csv');
59
+ }
60
+ /**
61
+ * Obtain SQL command to create and populate the compositing centres table.
62
+ * @param tab table name
63
+ * @param opt options for the table
64
+ * @returns CREATE TABLE, INSERT, CREATE VIEW, CREATE INDEX statements
65
+ */ export async function compositingCentresSql(tab = "compositingcentres", opt = {}) {
66
+ return setupTable(tab, {
67
+ region: "TEXT",
68
+ centre: "TEXT",
69
+ samples: "INT"
70
+ }, (await loadCompositingCentres()).values(), Object.assign({
71
+ pk: "region",
72
+ index: true,
73
+ tsvector: {
74
+ region: "A",
75
+ centre: "B"
76
+ }
77
+ }, opt));
78
+ }
79
+ /**
80
+ * Find matching compositing centres of a region/centre query.
81
+ * @param txt region/centre query
82
+ * @returns matches `[{region, centre, samples}]`
83
+ * @examples
84
+ * ```javascript
85
+ * ifct2017.compositingCentres('west');
86
+ * ifct2017.compositingCentres('Mumbai');
87
+ * // → [ { region: 'West', centre: 'Mumbai', samples: 12 } ]
88
+ *
89
+ * ifct2017.compositingCentres('what is compositing centre of north east?');
90
+ * ifct2017.compositingCentres('North East compositing centre');
91
+ * // → [ { region: 'North East', centre: 'Guwahati', samples: 11 } ]
92
+ * ```
93
+ */ export function compositingCentres(txt) {
94
+ if (index == null) return [];
95
+ const a = [];
96
+ txt = txt.replace(/\W/g, ' ');
97
+ const mats = index.search(txt);
98
+ let max = 0;
99
+ for (const mat of mats)max = Math.max(max, Object.keys(mat.matchData.metadata).length);
100
+ for (const mat of mats)if (Object.keys(mat.matchData.metadata).length === max) a.push(corpus?.get(mat.ref) || {});
101
+ return a;
102
+ } //#endregion
103
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9pZmN0MjAxNy9pZmN0MjAxNy9jb21wb3NpdGluZ2NlbnRyZXMvaW5kZXgudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IChDKSAyMDI1LTI2IFN1Ymhhaml0IFNhaHVcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBR1BMLTMuMC1vci1sYXRlclxuLy8gU2VlIExJQ0VOU0UgZm9yIGZ1bGwgdGVybXNcbmltcG9ydCAqIGFzIGNzdiAgZnJvbSBcIkBzdGQvY3N2XCI7XG5pbXBvcnQgbHVuciBmcm9tIFwibHVuclwiOyAgLy8gQGRlbm8tdHlwZXM9XCJucG06QHR5cGVzL2x1bnJAMi4zLjdcIlxuaW1wb3J0IHt0eXBlIFJvd0RhdGEsIHR5cGUgU2V0dXBUYWJsZU9wdGlvbnMsIHNldHVwVGFibGV9IGZyb20gXCJAbm9kZWYvZXh0cmEtc3FsXCI7XG5cblxuXG5cbi8vI3JlZ2lvbiBUWVBFU1xuLyoqIFJlZ2lvbmFsIGNvbXBvc2l0aW5nIGNlbnRyZSBhbmQgc2FtcGxlIHNpemUgb2YgZWFjaCByZWdpb24uICovXG5leHBvcnQgaW50ZXJmYWNlIENvbXBvc2l0aW5nQ2VudHJlIHtcbiAgLyoqIFJlZ2lvbi4gKi9cbiAgcmVnaW9uOiBzdHJpbmcsXG4gIC8qKiBSZWdpb25hbCBDb21wb3NpdGluZyBjZW50cmUuICovXG4gIGNlbnRyZTogc3RyaW5nLFxuICAvKiogU2FtcGxlIHNpemUuICovXG4gIHNhbXBsZXM6IG51bWJlclxufTtcbi8vI2VuZHJlZ2lvblxuXG5cblxuXG4vLyNyZWdpb24gR0xPQkFMU1xubGV0IGNvcnB1czogTWFwPHN0cmluZywgQ29tcG9zaXRpbmdDZW50cmU+IHwgbnVsbCA9IG51bGw7XG5sZXQgaW5kZXg6IGx1bnIuSW5kZXggfCBudWxsID0gbnVsbDtcbi8vI2VuZHJlZ2lvblxuXG5cblxuXG4vLyNyZWdpb24gRlVOQ1RJT05TXG4vKipcbiAqIExvYWQgdGhlIGNvbXBvc2l0aW5nIGNlbnRyZXMgY29ycHVzIGZyb20gQ1NWIGZpbGUuXG4gKiBAcGFyYW0gZmlsZSBDU1YgZmlsZSBwYXRoXG4gKiBAcmV0dXJucyBjb21wb3NpdGluZyBjZW50cmVzIGNvcnB1c1xuICovXG5hc3luYyBmdW5jdGlvbiBsb2FkRnJvbUNzdihmaWxlOiBzdHJpbmcpIHtcbiAgY29uc3QgbWFwICA9IG5ldyBNYXA8c3RyaW5nLCBDb21wb3NpdGluZ0NlbnRyZT4oKTtcbiAgY29uc3QgZGF0YSA9IGF3YWl0IChhd2FpdCBmZXRjaChmaWxlKSkudGV4dCgpO1xuICBjb25zdCByZWNvcmRzID0gY3N2LnBhcnNlKGRhdGEsIHtza2lwRmlyc3RSb3c6IHRydWUsIGNvbW1lbnQ6IFwiI1wifSk7XG4gIGZvciAoY29uc3QgciBvZiByZWNvcmRzKSB7XG4gICAgY29uc3Qgc2FtcGxlcyA9IHBhcnNlRmxvYXQoci5zYW1wbGVzKTtcbiAgICBtYXAuc2V0KHIucmVnaW9uLCB7cmVnaW9uOiByLnJlZ2lvbiwgY2VudHJlOiByLmNlbnRyZSwgc2FtcGxlc30pO1xuICB9XG4gIHJldHVybiBtYXA7XG59XG5cblxuLyoqXG4gKiBTZXR1cCB0aGUgbHVuciBpbmRleCBmb3IgdGhlIGNvbXBvc2l0aW5nIGNlbnRyZXMgY29ycHVzLlxuICogQHJldHVybnMgbHVuciBpbmRleFxuICovXG5mdW5jdGlvbiBzZXR1cEluZGV4KGNvcnB1czogTWFwPHN0cmluZywgQ29tcG9zaXRpbmdDZW50cmU+KSB7XG4gIHJldHVybiBsdW5yKGZ1bmN0aW9uKHRoaXM6IGx1bnIuQnVpbGRlcikge1xuICAgIHRoaXMucmVmKCdyZWdpb24nKTtcbiAgICB0aGlzLmZpZWxkKCdyZWdpb24nKTtcbiAgICB0aGlzLmZpZWxkKCdjZW50cmUnKTtcbiAgICBmb3IgKGNvbnN0IHIgb2YgY29ycHVzLnZhbHVlcygpKVxuICAgICAgdGhpcy5hZGQocik7XG4gIH0pO1xufVxuXG5cbi8qKlxuICogTG9hZCB0aGUgY29tcG9zaXRpbmcgY2VudHJlcyBjb3JwdXMgZnJvbSB0aGUgZmlsZS5cbiAqIEByZXR1cm5zIGNvbXBvc2l0aW5nIGNlbnRyZXMgY29ycHVzXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBsb2FkQ29tcG9zaXRpbmdDZW50cmVzKCk6IFByb21pc2U8TWFwPHN0cmluZywgQ29tcG9zaXRpbmdDZW50cmU+PiB7XG4gIGlmIChjb3JwdXMpIHJldHVybiBjb3JwdXM7XG4gIGNvcnB1cyA9IGF3YWl0IGxvYWRGcm9tQ3N2KGNvbXBvc2l0aW5nQ2VudHJlc0NzdigpKTtcbiAgaW5kZXggID0gc2V0dXBJbmRleChjb3JwdXMpO1xuICByZXR1cm4gY29ycHVzO1xufVxuXG5cbi8qKlxuICogR2V0IHRoZSBwYXRoIHRvIHRoZSBjb21wb3NpdGluZyBjZW50cmVzIENTViBmaWxlLlxuICogQHJldHVybnMgQ1NWIGZpbGUgVVJMXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb21wb3NpdGluZ0NlbnRyZXNDc3YoKTogc3RyaW5nIHtcbiAgcmV0dXJuIGltcG9ydC5tZXRhLnJlc29sdmUoJy4vaW5kZXguY3N2Jyk7XG59XG5cblxuLyoqXG4gKiBPYnRhaW4gU1FMIGNvbW1hbmQgdG8gY3JlYXRlIGFuZCBwb3B1bGF0ZSB0aGUgY29tcG9zaXRpbmcgY2VudHJlcyB0YWJsZS5cbiAqIEBwYXJhbSB0YWIgdGFibGUgbmFtZVxuICogQHBhcmFtIG9wdCBvcHRpb25zIGZvciB0aGUgdGFibGVcbiAqIEByZXR1cm5zIENSRUFURSBUQUJMRSwgSU5TRVJULCBDUkVBVEUgVklFVywgQ1JFQVRFIElOREVYIHN0YXRlbWVudHNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNvbXBvc2l0aW5nQ2VudHJlc1NxbCh0YWI6IHN0cmluZz1cImNvbXBvc2l0aW5nY2VudHJlc1wiLCBvcHQ6IFNldHVwVGFibGVPcHRpb25zPXt9KTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgcmV0dXJuIHNldHVwVGFibGUodGFiLCB7cmVnaW9uOiBcIlRFWFRcIiwgY2VudHJlOiBcIlRFWFRcIiwgc2FtcGxlczogXCJJTlRcIn0sXG4gICAgKGF3YWl0IGxvYWRDb21wb3NpdGluZ0NlbnRyZXMoKSkudmFsdWVzKCkgYXMgSXRlcmFibGU8Um93RGF0YT4sXG4gICAgT2JqZWN0LmFzc2lnbih7cGs6IFwicmVnaW9uXCIsIGluZGV4OiB0cnVlLCB0c3ZlY3Rvcjoge3JlZ2lvbjogXCJBXCIsIGNlbnRyZTogXCJCXCJ9fSwgb3B0KSk7XG59XG5cblxuLyoqXG4gKiBGaW5kIG1hdGNoaW5nIGNvbXBvc2l0aW5nIGNlbnRyZXMgb2YgYSByZWdpb24vY2VudHJlIHF1ZXJ5LlxuICogQHBhcmFtIHR4dCByZWdpb24vY2VudHJlIHF1ZXJ5XG4gKiBAcmV0dXJucyBtYXRjaGVzIGBbe3JlZ2lvbiwgY2VudHJlLCBzYW1wbGVzfV1gXG4gKiBAZXhhbXBsZXNcbiAqIGBgYGphdmFzY3JpcHRcbiAqIGlmY3QyMDE3LmNvbXBvc2l0aW5nQ2VudHJlcygnd2VzdCcpO1xuICogaWZjdDIwMTcuY29tcG9zaXRpbmdDZW50cmVzKCdNdW1iYWknKTtcbiAqIC8vIOKGkiBbIHsgcmVnaW9uOiAnV2VzdCcsIGNlbnRyZTogJ011bWJhaScsIHNhbXBsZXM6IDEyIH0gXVxuICpcbiAqIGlmY3QyMDE3LmNvbXBvc2l0aW5nQ2VudHJlcygnd2hhdCBpcyBjb21wb3NpdGluZyBjZW50cmUgb2Ygbm9ydGggZWFzdD8nKTtcbiAqIGlmY3QyMDE3LmNvbXBvc2l0aW5nQ2VudHJlcygnTm9ydGggRWFzdCBjb21wb3NpdGluZyBjZW50cmUnKTtcbiAqIC8vIOKGkiBbIHsgcmVnaW9uOiAnTm9ydGggRWFzdCcsIGNlbnRyZTogJ0d1d2FoYXRpJywgc2FtcGxlczogMTEgfSBdXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbXBvc2l0aW5nQ2VudHJlcyh0eHQ6IHN0cmluZyk6IENvbXBvc2l0aW5nQ2VudHJlW10ge1xuICBpZiAoaW5kZXggPT0gbnVsbCkgcmV0dXJuIFtdO1xuICBjb25zdCBhOiBDb21wb3NpdGluZ0NlbnRyZVtdID0gW107IHR4dCA9IHR4dC5yZXBsYWNlKC9cXFcvZywgJyAnKTtcbiAgY29uc3QgbWF0cyA9IGluZGV4LnNlYXJjaCh0eHQpOyBsZXQgbWF4ID0gMDtcbiAgZm9yIChjb25zdCBtYXQgb2YgbWF0cylcbiAgICBtYXggPSBNYXRoLm1heChtYXgsIE9iamVjdC5rZXlzKG1hdC5tYXRjaERhdGEubWV0YWRhdGEpLmxlbmd0aCk7XG4gIGZvciAoY29uc3QgbWF0IG9mIG1hdHMpXG4gICAgaWYgKE9iamVjdC5rZXlzKG1hdC5tYXRjaERhdGEubWV0YWRhdGEpLmxlbmd0aCA9PT0gbWF4KSBhLnB1c2goY29ycHVzPy5nZXQobWF0LnJlZikgfHwge30gYXMgQ29tcG9zaXRpbmdDZW50cmUpO1xuICByZXR1cm4gYTtcbn1cbi8vI2VuZHJlZ2lvblxuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLHNDQUFzQztBQUN0Qyw2Q0FBNkM7QUFDN0MsNkJBQTZCO0FBQzdCLFlBQVksU0FBVSxXQUFXO0FBQ2pDLE9BQU8sVUFBVSxPQUFPLENBQUUsc0NBQXNDO0FBQ2hFLFNBQThDLFVBQVUsUUFBTyxtQkFBbUI7QUFlbEYsWUFBWTtBQUtaLGlCQUFpQjtBQUNqQixJQUFJLFNBQWdEO0FBQ3BELElBQUksUUFBMkI7QUFDL0IsWUFBWTtBQUtaLG1CQUFtQjtBQUNuQjs7OztDQUlDLEdBQ0QsZUFBZSxZQUFZLElBQVk7RUFDckMsTUFBTSxNQUFPLElBQUk7RUFDakIsTUFBTSxPQUFPLE1BQU0sQ0FBQyxNQUFNLE1BQU0sS0FBSyxFQUFFLElBQUk7RUFDM0MsTUFBTSxVQUFVLElBQUksS0FBSyxDQUFDLE1BQU07SUFBQyxjQUFjO0lBQU0sU0FBUztFQUFHO0VBQ2pFLEtBQUssTUFBTSxLQUFLLFFBQVM7SUFDdkIsTUFBTSxVQUFVLFdBQVcsRUFBRSxPQUFPO0lBQ3BDLElBQUksR0FBRyxDQUFDLEVBQUUsTUFBTSxFQUFFO01BQUMsUUFBUSxFQUFFLE1BQU07TUFBRSxRQUFRLEVBQUUsTUFBTTtNQUFFO0lBQU87RUFDaEU7RUFDQSxPQUFPO0FBQ1Q7QUFHQTs7O0NBR0MsR0FDRCxTQUFTLFdBQVcsTUFBc0M7RUFDeEQsT0FBTyxLQUFLO0lBQ1YsSUFBSSxDQUFDLEdBQUcsQ0FBQztJQUNULElBQUksQ0FBQyxLQUFLLENBQUM7SUFDWCxJQUFJLENBQUMsS0FBSyxDQUFDO0lBQ1gsS0FBSyxNQUFNLEtBQUssT0FBTyxNQUFNLEdBQzNCLElBQUksQ0FBQyxHQUFHLENBQUM7RUFDYjtBQUNGO0FBR0E7OztDQUdDLEdBQ0QsT0FBTyxlQUFlO0VBQ3BCLElBQUksUUFBUSxPQUFPO0VBQ25CLFNBQVMsTUFBTSxZQUFZO0VBQzNCLFFBQVMsV0FBVztFQUNwQixPQUFPO0FBQ1Q7QUFHQTs7O0NBR0MsR0FDRCxPQUFPLFNBQVM7RUFDZCxPQUFPLFlBQVksT0FBTyxDQUFDO0FBQzdCO0FBR0E7Ozs7O0NBS0MsR0FDRCxPQUFPLGVBQWUsc0JBQXNCLE1BQVksb0JBQW9CLEVBQUUsTUFBdUIsQ0FBQyxDQUFDO0VBQ3JHLE9BQU8sV0FBVyxLQUFLO0lBQUMsUUFBUTtJQUFRLFFBQVE7SUFBUSxTQUFTO0VBQUssR0FDcEUsQ0FBQyxNQUFNLHdCQUF3QixFQUFFLE1BQU0sSUFDdkMsT0FBTyxNQUFNLENBQUM7SUFBQyxJQUFJO0lBQVUsT0FBTztJQUFNLFVBQVU7TUFBQyxRQUFRO01BQUssUUFBUTtJQUFHO0VBQUMsR0FBRztBQUNyRjtBQUdBOzs7Ozs7Ozs7Ozs7OztDQWNDLEdBQ0QsT0FBTyxTQUFTLG1CQUFtQixHQUFXO0VBQzVDLElBQUksU0FBUyxNQUFNLE9BQU8sRUFBRTtFQUM1QixNQUFNLElBQXlCLEVBQUU7RUFBRSxNQUFNLElBQUksT0FBTyxDQUFDLE9BQU87RUFDNUQsTUFBTSxPQUFPLE1BQU0sTUFBTSxDQUFDO0VBQU0sSUFBSSxNQUFNO0VBQzFDLEtBQUssTUFBTSxPQUFPLEtBQ2hCLE1BQU0sS0FBSyxHQUFHLENBQUMsS0FBSyxPQUFPLElBQUksQ0FBQyxJQUFJLFNBQVMsQ0FBQyxRQUFRLEVBQUUsTUFBTTtFQUNoRSxLQUFLLE1BQU0sT0FBTyxLQUNoQixJQUFJLE9BQU8sSUFBSSxDQUFDLElBQUksU0FBUyxDQUFDLFFBQVEsRUFBRSxNQUFNLEtBQUssS0FBSyxFQUFFLElBQUksQ0FBQyxRQUFRLElBQUksSUFBSSxHQUFHLEtBQUssQ0FBQztFQUMxRixPQUFPO0FBQ1QsRUFDQSxZQUFZIn0=
@@ -0,0 +1,13 @@
1
+ Indian Food Composition Tables 2017
2
+ T. Longvah, R. Ananthan, K. Bhaskarachary and K. Venkaiah
3
+
4
+ Copyright © 2017 by National Institute of Nutrition
5
+ Indian Council of Medical Research
6
+ Department of Health Research Ministry of Health and Family Welfare, Government of India
7
+ Jamai Osmania (PO), Hyderabad – 500 007
8
+ Telangana, India Phone: +91 40 27197334, Fax: +91 40 27000339, Email: nin@ap.nic.in
9
+
10
+ REGIONAL COMPOSITING CENTRES AND SAMPLE SIZE OF EACH REGION
11
+ - Region
12
+ - Regional Compositing centre
13
+ - Sample size
@@ -0,0 +1,212 @@
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 path from "@std/path";
5
+ import * as csv from "@std/csv";
6
+ import {loadColumns} from "../columns/index.ts";
7
+ import {type Description, loadDescriptions} from "../descriptions/index.ts";
8
+ import {type Group, loadGroups} from "../groups/index.ts";
9
+
10
+
11
+
12
+
13
+ const BASE = ['code', 'name', 'scie', 'lang', 'grup', 'regn', 'tags'];
14
+
15
+
16
+
17
+
18
+ function round(val: number) {
19
+ return Math.round(val * 1e+12) / 1e+12;
20
+ }
21
+
22
+
23
+ // function significantDigits(n: number) {
24
+ // return n.toExponential().replace(/e[\+\-0-9]*$/, '').replace( /^0\.?0*|\./, '').length;
25
+ // }
26
+
27
+
28
+ type ReduceFn<V=string> = (acc: Map<string, V>, r: Record<string, string>) => void;
29
+
30
+
31
+ async function readCsv<V=string>(pth: string, fn: ReduceFn<V>, acc: Map<string, V>) {
32
+ const data = await Deno.readTextFile(pth);
33
+ const records = csv.parse(data, {skipFirstRow: true, comment: "#"});
34
+ for (const record of records)
35
+ fn(acc, record);
36
+ return acc;
37
+ }
38
+
39
+
40
+ interface Dat {
41
+ code: string[];
42
+ name: string[];
43
+ scie: string[];
44
+ lang: string[];
45
+ grup: string[];
46
+ regn: number[];
47
+ tags: string[];
48
+ [key: string]: unknown[];
49
+ };
50
+
51
+
52
+
53
+
54
+ async function writeIndex() {
55
+ let dat: Dat = {
56
+ code: [],
57
+ name: [],
58
+ scie: [],
59
+ lang: [],
60
+ grup: [],
61
+ regn: [],
62
+ tags: [],
63
+ };
64
+ let di = 0;
65
+ const map = new Map();
66
+ let factors = new Map<string, string>();
67
+ let renames = new Map<string, string>();
68
+ let sums = new Map<string, string>();
69
+ let orders = new Map<string, string[]>();
70
+ let descCorpus: Map<string, Description>;
71
+ let grupCorpus: Map<string, Group>;
72
+ await loadGroups();
73
+
74
+
75
+ function valParse(val: string, code: string, dat: Dat, i: number) {
76
+ const f = factors.get(code) as string;
77
+ const fn = parseFloat(f.replace(/\*.*/, ''));
78
+ const fi = f.indexOf('*');
79
+ const fk = fi>=0? f.substring(fi+1) : null;
80
+ const a = (parseFloat(val) || 0) * fn * (fk? parseFloat(dat[fk][i] as string) || 0 : 1);
81
+ // a = parseFloat(a.toExponential((significantDigits(parseFloat(val))||1)-1));
82
+ return round(a);
83
+ }
84
+
85
+
86
+ function nameSci(str: string) {
87
+ const bgn = str.lastIndexOf('(');
88
+ if (bgn<0) return '';
89
+ let end = str.lastIndexOf(')');
90
+ end = end<0? str.length : end;
91
+ const sci = str.substring(bgn+1, end).trim();
92
+ const spc = sci.search(/\s/g);
93
+ return spc>=0 && sci!=='small intestine'? sci : '';
94
+ }
95
+
96
+ function nameBas(str: string) {
97
+ const sci = nameSci(str);
98
+ if (!sci) return str.trim();
99
+ return str.replace(new RegExp(`\\(\\s*${sci}\\s*\\)`), '').trim();
100
+ }
101
+
102
+ function readAssetRow(row: Record<string, string>) {
103
+ const cod = row.code.trim();
104
+ const old = map.has(cod);
105
+ const nam = nameBas(row.name);
106
+ const sci = nameSci(row.name);
107
+ const i = old? map.get(cod) : map.set(cod, di) && di++;
108
+ dat.code[i] = cod;
109
+ dat.name[i] = old && dat.name[i].length > nam.length? dat.name[i] : nam;
110
+ dat.scie[i] = old && dat.scie[i].length > sci.length? dat.scie[i] : sci;
111
+ dat.lang[i] = (descCorpus.get(cod) || {desc: ''}).desc;
112
+ dat.grup[i] = (grupCorpus.get(cod[0]) as Group).group;
113
+ dat.regn[i] = parseInt(row.regn.trim(), 10);
114
+ dat.tags[i] = (grupCorpus.get(cod[0]) as Group).tags.trim();
115
+ dat.name[i] = (descCorpus.get(cod) || {name: dat.name[i]}).name;
116
+ dat.scie[i] = (descCorpus.get(cod) || {scie: dat.scie[i]}).scie;
117
+ for (const k in row) {
118
+ if (BASE.includes(k)) continue;
119
+ const val = row[k].trim().split('±');
120
+ const kt = renames.get(k) || k;
121
+ if (!dat[kt]) { dat[kt] = []; dat[kt+'_e'] = []; }
122
+ dat[kt][i] = valParse(val[0]||'0', k, dat, i);
123
+ dat[kt+'_e'][i] = valParse(val[1]||'0', k, dat, i);
124
+ }
125
+ }
126
+
127
+ async function readAsset(pth: string) {
128
+ const data = await Deno.readTextFile(pth);
129
+ const records = csv.parse(data, {skipFirstRow: true, comment: "#"});
130
+ for (const record of records)
131
+ readAssetRow(record);
132
+ }
133
+
134
+ function nullToZero(d: Dat) {
135
+ for (const k of Object.keys(d)) {
136
+ for (let i=0; i<di; i++)
137
+ d[k][i] = d[k][i]!=null? d[k][i] : 0;
138
+ }
139
+ }
140
+
141
+ function sumColumns(d: Dat, i: number, ks: string[]) {
142
+ let a = 0;
143
+ for (const k of ks)
144
+ a += d[k][i] as number;
145
+ return a;
146
+ }
147
+
148
+ function sumAll(d: Dat) {
149
+ for (const [k, exp] of sums) {
150
+ d[k] = d[k] || [];
151
+ const sumk = exp.replace(/\s/g, '').split('+');
152
+ for (let i=0; i<di; i++)
153
+ d[k][i] = d[k][i] || round(sumColumns(d, i, sumk));
154
+ }
155
+ }
156
+
157
+ function orderAll(d: Dat) {
158
+ const a: Record<string, unknown[]> = {};
159
+ for (const k in d) {
160
+ if (k in a) continue;
161
+ for (const ak of orders.get(k) || []) {
162
+ a[ak] = d[ak];
163
+ const ake = ak + '_e';
164
+ if (ake in d) a[ake] = d[ake];
165
+ }
166
+ a[k] = d[k];
167
+ }
168
+ return a;
169
+ }
170
+
171
+
172
+ async function writeIndexMain() {
173
+ await loadColumns();
174
+ grupCorpus = await loadGroups();
175
+ descCorpus = await loadDescriptions();
176
+ factors = await readCsv(path.join(import.meta.dirname || '', 'configs/factors.csv'), (acc, r) => acc.set(r.code, r.factor), new Map<string, string>());
177
+ renames = await readCsv(path.join(import.meta.dirname || '', 'configs/renames.csv'), (acc, r) => acc.set(r.code, r.actual), new Map<string, string>());
178
+ sums = await readCsv(path.join(import.meta.dirname || '', 'configs/sums.csv'), (acc, r) => acc.set(r.code, r.expression), new Map<string, string>());
179
+ orders = await readCsv(path.join(import.meta.dirname || '', 'configs/orders.csv'), (acc, r) => {
180
+ const arr = acc.get(r.before) || [];
181
+ acc.set(r.before, arr);
182
+ arr.push(r.code);
183
+ }, new Map<string, string[]>());
184
+ const assetsDir = path.join(import.meta.dirname || '', 'assets');
185
+ const assetsFiles = Array.from(Deno.readDirSync(assetsDir)).sort((a, b) => a.name.localeCompare(b.name));
186
+ for (const file of assetsFiles) {
187
+ if (!file.name.endsWith('.csv')) continue;
188
+ console.log(`Reading asset file: ${file.name}`);
189
+ await readAsset(path.join(import.meta.dirname || '', 'assets', file.name));
190
+ }
191
+ nullToZero(dat);
192
+ sumAll(dat);
193
+ dat = orderAll(dat) as Dat;
194
+ const ks = Object.keys(dat);
195
+ // let a = ks.map(k => `"${columns(k.replace(/_e$/, ''))[0].name}; ${k}"`).join() + '\n';
196
+ let a = ks.join() + '\n';
197
+ for (let i=0; i<di; i++) {
198
+ for (const k of ks) {
199
+ const v = dat[k][i];
200
+ a += JSON.stringify(v==null? 0:v) + ',';
201
+ }
202
+ a = a.substring(0, a.length-1) + '\n';
203
+ }
204
+ await Deno.writeTextFile(path.join(import.meta.dirname || '', 'index.csv'), a);
205
+ }
206
+ await writeIndexMain();
207
+ }
208
+
209
+
210
+ export async function build() {
211
+ await writeIndex();
212
+ }