bps-mcp-server 0.12.0 → 0.13.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/README.md +21 -5
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +5 -2
- package/dist/server.js.map +1 -1
- package/dist/tools/analysis.tools.d.ts +11 -0
- package/dist/tools/analysis.tools.d.ts.map +1 -0
- package/dist/tools/analysis.tools.js +434 -0
- package/dist/tools/analysis.tools.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ MCP (Model Context Protocol) server untuk data statistik BPS (Badan Pusat Statis
|
|
|
8
8
|
|
|
9
9
|
## Fitur
|
|
10
10
|
|
|
11
|
-
- **
|
|
11
|
+
- **39 tools** mencakup seluruh endpoint BPS WebAPI v1 + AllStats Search + AI-friendly shortcuts
|
|
12
12
|
- **AI-friendly** — tool `find_data` memungkinkan AI mendapat data dalam 1 langkah (tanpa perlu navigasi hierarki BPS)
|
|
13
13
|
- **Integrasi AllStats Search** — pencarian unified + full-text PDF search (tanpa API key)
|
|
14
14
|
- **Smart fallback** — WebAPI search otomatis fallback ke AllStats jika tidak ada hasil
|
|
@@ -163,16 +163,19 @@ File `~/.cursor/mcp.json` atau `.vscode/mcp.json`:
|
|
|
163
163
|
}
|
|
164
164
|
```
|
|
165
165
|
|
|
166
|
-
## Tools (
|
|
166
|
+
## Tools (39)
|
|
167
167
|
|
|
168
|
-
### AI-Friendly Smart Tools (
|
|
168
|
+
### AI-Friendly Smart Tools (5)
|
|
169
169
|
|
|
170
170
|
| Tool | Deskripsi |
|
|
171
171
|
|------|-----------|
|
|
172
172
|
| `find_data` | **Recommended** — Cari & ambil data dalam satu langkah (resolve wilayah + cari variabel + ambil data) |
|
|
173
173
|
| `find_variable` | Cari variabel data berdasarkan kata kunci |
|
|
174
|
+
| `compare_data` | Bandingkan data antar wilayah (2+ wilayah sekaligus dalam 1 panggilan) |
|
|
175
|
+
| `get_trend` | Ambil data time-series/tren multi-tahun dalam 1 panggilan |
|
|
176
|
+
| `get_ranking` | Ranking/peringkat provinsi berdasarkan indikator (top-N) |
|
|
174
177
|
|
|
175
|
-
> **Untuk AI:** Gunakan `find_data`
|
|
178
|
+
> **Untuk AI:** Gunakan `find_data` untuk data 1 wilayah, `compare_data` untuk perbandingan, `get_trend` untuk tren, `get_ranking` untuk peringkat. Jika hasilnya kurang spesifik, gunakan `find_variable` lalu `get_dynamic_data`.
|
|
176
179
|
|
|
177
180
|
### WebAPI Tools (32)
|
|
178
181
|
|
|
@@ -236,6 +239,15 @@ Jika find_data gagal, AI bisa:
|
|
|
236
239
|
- find_variable(keyword="miskin") → lihat variabel yang tersedia
|
|
237
240
|
- list_strategic_indicators() → data headline terbaru
|
|
238
241
|
- search(keyword="kemiskinan") → cari tabel/publikasi terkait
|
|
242
|
+
|
|
243
|
+
User: "Bandingkan kemiskinan Jawa Timur dan Jawa Barat"
|
|
244
|
+
AI menggunakan: compare_data(query="kemiskinan", regions="Jawa Timur, Jawa Barat")
|
|
245
|
+
|
|
246
|
+
User: "Tren pengangguran Indonesia 2019-2024"
|
|
247
|
+
AI menggunakan: get_trend(query="pengangguran", region="Indonesia", start_year="2019", end_year="2024")
|
|
248
|
+
|
|
249
|
+
User: "10 provinsi termiskin"
|
|
250
|
+
AI menggunakan: get_ranking(query="kemiskinan", top_n=10, order="highest")
|
|
239
251
|
```
|
|
240
252
|
|
|
241
253
|
## Contoh Query
|
|
@@ -243,6 +255,9 @@ Jika find_data gagal, AI bisa:
|
|
|
243
255
|
```
|
|
244
256
|
"Berapa jumlah penduduk miskin Indonesia tahun 2023?"
|
|
245
257
|
"Bandingkan angka kemiskinan Jawa Timur vs Jawa Barat 2020-2023"
|
|
258
|
+
"Tren pengangguran Indonesia dari 2019 sampai 2024"
|
|
259
|
+
"10 provinsi dengan kemiskinan tertinggi"
|
|
260
|
+
"Peringkat IPM seluruh provinsi 2023"
|
|
246
261
|
"Cari BRS terbaru tentang inflasi"
|
|
247
262
|
"Data ekspor kopi Indonesia tahun 2024"
|
|
248
263
|
"Cari publikasi tentang statistik telekomunikasi"
|
|
@@ -361,8 +376,9 @@ src/
|
|
|
361
376
|
├── prompts/ # MCP prompt templates
|
|
362
377
|
├── resources/ # MCP resources (domain lists)
|
|
363
378
|
├── services/ # Cache, domain resolver, data formatter
|
|
364
|
-
├── tools/ # MCP tool definitions (
|
|
379
|
+
├── tools/ # MCP tool definitions (39 tools)
|
|
365
380
|
│ ├── smart.tools.ts # find_data, find_variable (AI shortcuts)
|
|
381
|
+
│ ├── analysis.tools.ts # compare_data, get_trend, get_ranking
|
|
366
382
|
│ ├── dynamic-data.tools.ts # Core data tools
|
|
367
383
|
│ ├── search.tools.ts # Search with AllStats fallback
|
|
368
384
|
│ ├── allstats.tools.ts # AllStats search & deep search
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
2
3
|
import { loadConfig } from "./config/index.js";
|
|
3
4
|
import { createAuthProvider } from "./auth/factory.js";
|
|
4
5
|
import { InMemoryCache } from "./services/cache.js";
|
|
@@ -6,6 +7,7 @@ import { FileStore } from "./services/file-store.js";
|
|
|
6
7
|
import { createServer } from "./server.js";
|
|
7
8
|
import { startStdioTransport } from "./transport/stdio.js";
|
|
8
9
|
import { setLogLevel, logger } from "./utils/logger.js";
|
|
10
|
+
const pkg = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf-8"));
|
|
9
11
|
async function main() {
|
|
10
12
|
try {
|
|
11
13
|
const config = loadConfig();
|
|
@@ -21,7 +23,7 @@ async function main() {
|
|
|
21
23
|
const auth = createAuthProvider(config);
|
|
22
24
|
const cache = config.cacheEnabled ? new InMemoryCache(config.cacheMaxEntries) : null;
|
|
23
25
|
const store = new FileStore();
|
|
24
|
-
const { server } = createServer(config, auth, cache, store);
|
|
26
|
+
const { server } = createServer(config, auth, cache, store, pkg.version);
|
|
25
27
|
await startStdioTransport(server);
|
|
26
28
|
}
|
|
27
29
|
catch (error) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAExD,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;QAC5B,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAE7B,MAAM,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QAC1C,MAAM,CAAC,KAAK,CAAC,eAAe,EAAE;YAC5B,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,aAAa,EAAE,MAAM,CAAC,aAAa;YACnC,YAAY,EAAE,MAAM,CAAC,YAAY;SAClC,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;QACxC,MAAM,KAAK,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,aAAa,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACrF,MAAM,KAAK,GAAG,IAAI,SAAS,EAAE,CAAC;QAC9B,MAAM,EAAE,MAAM,EAAE,GAAG,YAAY,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAExD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,iBAAiB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AAE3F,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;QAC5B,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAE7B,MAAM,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QAC1C,MAAM,CAAC,KAAK,CAAC,eAAe,EAAE;YAC5B,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,aAAa,EAAE,MAAM,CAAC,aAAa;YACnC,YAAY,EAAE,MAAM,CAAC,YAAY;SAClC,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;QACxC,MAAM,KAAK,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,aAAa,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACrF,MAAM,KAAK,GAAG,IAAI,SAAS,EAAE,CAAC;QAC9B,MAAM,EAAE,MAAM,EAAE,GAAG,YAAY,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;QAEzE,MAAM,mBAAmB,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,gCAAgC,EAAE,KAAK,CAAC,CAAC;QACtD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC"}
|
package/dist/server.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import type { ICacheProvider } from "./services/cache.js";
|
|
|
5
5
|
import type { IPersistentStore } from "./services/persistent-store.js";
|
|
6
6
|
import { BpsClient } from "./client/bps-client.js";
|
|
7
7
|
import { DomainResolver } from "./services/domain-resolver.js";
|
|
8
|
-
export declare function createServer(config: Config, auth: IAuthProvider, cache: ICacheProvider | null, store?: IPersistentStore | null): {
|
|
8
|
+
export declare function createServer(config: Config, auth: IAuthProvider, cache: ICacheProvider | null, store?: IPersistentStore | null, version?: string): {
|
|
9
9
|
server: McpServer;
|
|
10
10
|
client: BpsClient;
|
|
11
11
|
resolver: DomainResolver;
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAEnD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAEnD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAoB/D,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,aAAa,EACnB,KAAK,EAAE,cAAc,GAAG,IAAI,EAC5B,KAAK,CAAC,EAAE,gBAAgB,GAAG,IAAI,EAC/B,OAAO,CAAC,EAAE,MAAM,GACf;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,cAAc,CAAA;CAAE,CA2CpE"}
|
package/dist/server.js
CHANGED
|
@@ -12,6 +12,7 @@ import { registerSearchTools } from "./tools/search.tools.js";
|
|
|
12
12
|
import { registerAllStatsTools } from "./tools/allstats.tools.js";
|
|
13
13
|
import { registerUtilityTools } from "./tools/utility.tools.js";
|
|
14
14
|
import { registerSmartTools } from "./tools/smart.tools.js";
|
|
15
|
+
import { registerAnalysisTools } from "./tools/analysis.tools.js";
|
|
15
16
|
import { registerInfographicTools } from "./tools/infographic.tools.js";
|
|
16
17
|
import { registerCensusTools } from "./tools/census.tools.js";
|
|
17
18
|
import { registerCsaTools } from "./tools/csa.tools.js";
|
|
@@ -19,10 +20,10 @@ import { registerNewsTools } from "./tools/news.tools.js";
|
|
|
19
20
|
import { registerGlossaryTools } from "./tools/glossary.tools.js";
|
|
20
21
|
import { registerResources } from "./resources/domain.resources.js";
|
|
21
22
|
import { registerPrompts } from "./prompts/analysis.prompts.js";
|
|
22
|
-
export function createServer(config, auth, cache, store) {
|
|
23
|
+
export function createServer(config, auth, cache, store, version) {
|
|
23
24
|
const server = new McpServer({
|
|
24
25
|
name: "bps-statistics",
|
|
25
|
-
version: "0.
|
|
26
|
+
version: version || "0.0.0",
|
|
26
27
|
});
|
|
27
28
|
const client = new BpsClient(auth, cache, config);
|
|
28
29
|
const allStatsClient = new AllStatsClient(cache, config.allStatsBaseUrl);
|
|
@@ -45,6 +46,8 @@ export function createServer(config, auth, cache, store) {
|
|
|
45
46
|
registerAllStatsTools(server, allStatsClient);
|
|
46
47
|
// Smart AI-friendly tools (one-shot data retrieval)
|
|
47
48
|
registerSmartTools(server, client, resolver, config, store ?? null);
|
|
49
|
+
// Analysis tools (compare, trend, ranking)
|
|
50
|
+
registerAnalysisTools(server, client, resolver, config, store ?? null);
|
|
48
51
|
// Utility
|
|
49
52
|
registerUtilityTools(server, cache);
|
|
50
53
|
// Resources & Prompts
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKpE,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAEhE,MAAM,UAAU,YAAY,CAC1B,MAAc,EACd,IAAmB,EACnB,KAA4B,EAC5B,KAA+B
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import type { BpsClient } from "../client/bps-client.js";
|
|
3
|
+
import type { Config } from "../config/index.js";
|
|
4
|
+
import type { DomainResolver } from "../services/domain-resolver.js";
|
|
5
|
+
import type { IPersistentStore } from "../services/persistent-store.js";
|
|
6
|
+
/**
|
|
7
|
+
* Multi-region comparison, trend, and ranking tools.
|
|
8
|
+
* Each handles a common multi-step query pattern in a single tool call.
|
|
9
|
+
*/
|
|
10
|
+
export declare function registerAnalysisTools(server: McpServer, client: BpsClient, resolver: DomainResolver, config: Config, store: IPersistentStore | null): void;
|
|
11
|
+
//# sourceMappingURL=analysis.tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analysis.tools.d.ts","sourceRoot":"","sources":["../../src/tools/analysis.tools.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAIxE;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,SAAS,EACjB,QAAQ,EAAE,cAAc,EACxB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,gBAAgB,GAAG,IAAI,GAC7B,IAAI,CAoUN"}
|
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
import { z } from "zod/v4";
|
|
2
|
+
import { appendAttribution } from "../services/attribution.js";
|
|
3
|
+
import { lookupVar, learnVar, normalizeKeyword } from "../services/learning.js";
|
|
4
|
+
/**
|
|
5
|
+
* Multi-region comparison, trend, and ranking tools.
|
|
6
|
+
* Each handles a common multi-step query pattern in a single tool call.
|
|
7
|
+
*/
|
|
8
|
+
export function registerAnalysisTools(server, client, resolver, config, store) {
|
|
9
|
+
// ---------- compare_data ----------
|
|
10
|
+
server.tool("compare_data", `Bandingkan data statistik antar wilayah dalam 1 langkah.
|
|
11
|
+
Gunakan tool ini ketika user ingin membandingkan data antara 2 atau lebih wilayah.
|
|
12
|
+
|
|
13
|
+
Contoh query user yang cocok untuk tool ini:
|
|
14
|
+
- "bandingkan kemiskinan Jawa Timur dan Jawa Barat"
|
|
15
|
+
- "IPM DKI Jakarta vs Banten vs Jawa Barat"
|
|
16
|
+
- "perbandingan pengangguran antar provinsi di Jawa"
|
|
17
|
+
- "mana yang lebih tinggi kemiskinan Jatim atau Jabar?"`, {
|
|
18
|
+
query: z.string().describe("Indikator yang dibandingkan (misal: kemiskinan, pengangguran, IPM, penduduk)"),
|
|
19
|
+
regions: z.string().describe("Nama wilayah dipisah koma (misal: 'Jawa Timur, Jawa Barat, Jawa Tengah')"),
|
|
20
|
+
year: z.string().optional().describe("Tahun data (misal: '2023'). Kosongkan untuk data terbaru."),
|
|
21
|
+
}, async ({ query, regions, year }) => {
|
|
22
|
+
try {
|
|
23
|
+
const regionList = regions.split(",").map(r => r.trim()).filter(Boolean);
|
|
24
|
+
if (regionList.length < 2) {
|
|
25
|
+
return { content: [{ type: "text", text: "Minimal 2 wilayah untuk perbandingan." }], isError: true };
|
|
26
|
+
}
|
|
27
|
+
const results = [];
|
|
28
|
+
for (const regionName of regionList) {
|
|
29
|
+
const resolved = await resolver.resolve(regionName);
|
|
30
|
+
if (!resolved) {
|
|
31
|
+
results.push({ region: regionName, domain: "?", value: "Wilayah tidak ditemukan", varTitle: "" });
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
const { domainId, domainName } = resolved;
|
|
35
|
+
const data = await fetchDataForDomain(client, store, query, domainId, year);
|
|
36
|
+
results.push({
|
|
37
|
+
region: domainName,
|
|
38
|
+
domain: domainId,
|
|
39
|
+
value: data.value,
|
|
40
|
+
varTitle: data.varTitle,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
// Format output
|
|
44
|
+
const varTitle = results.find(r => r.varTitle)?.varTitle || query;
|
|
45
|
+
const lines = [
|
|
46
|
+
`## Perbandingan: ${varTitle}`,
|
|
47
|
+
year ? `**Tahun:** ${year}` : "**Tahun:** Terbaru",
|
|
48
|
+
"",
|
|
49
|
+
"| Wilayah | Nilai |",
|
|
50
|
+
"| --- | --- |",
|
|
51
|
+
];
|
|
52
|
+
for (const r of results) {
|
|
53
|
+
lines.push(`| ${r.region} | ${r.value} |`);
|
|
54
|
+
}
|
|
55
|
+
// Add analysis hint
|
|
56
|
+
const numericResults = results.filter(r => !isNaN(parseFloat(r.value.replace(",", "."))));
|
|
57
|
+
if (numericResults.length >= 2) {
|
|
58
|
+
const values = numericResults.map(r => ({ region: r.region, val: parseFloat(r.value.replace(",", ".")) }));
|
|
59
|
+
values.sort((a, b) => b.val - a.val);
|
|
60
|
+
lines.push("");
|
|
61
|
+
lines.push(`**Tertinggi:** ${values[0].region} (${values[0].val})`);
|
|
62
|
+
lines.push(`**Terendah:** ${values[values.length - 1].region} (${values[values.length - 1].val})`);
|
|
63
|
+
}
|
|
64
|
+
return { content: [{ type: "text", text: appendAttribution(lines.join("\n")) }] };
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
return { content: [{ type: "text", text: error instanceof Error ? error.message : "Gagal membandingkan data" }], isError: true };
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
// ---------- get_trend ----------
|
|
71
|
+
server.tool("get_trend", `Ambil data time-series (tren multi-tahun) dalam 1 langkah.
|
|
72
|
+
Gunakan tool ini ketika user ingin melihat perkembangan/tren data dari tahun ke tahun.
|
|
73
|
+
|
|
74
|
+
Contoh query user yang cocok untuk tool ini:
|
|
75
|
+
- "tren kemiskinan Indonesia 2019-2023"
|
|
76
|
+
- "perkembangan IPM Jawa Timur 5 tahun terakhir"
|
|
77
|
+
- "bagaimana pengangguran dari 2020 sampai 2024?"
|
|
78
|
+
- "data kemiskinan Jawa Barat dari tahun ke tahun"`, {
|
|
79
|
+
query: z.string().describe("Indikator yang dianalisis (misal: kemiskinan, pengangguran, IPM)"),
|
|
80
|
+
region: z.string().default("Indonesia").describe("Nama wilayah"),
|
|
81
|
+
start_year: z.string().default("2019").describe("Tahun awal"),
|
|
82
|
+
end_year: z.string().default("2024").describe("Tahun akhir"),
|
|
83
|
+
}, async ({ query, region, start_year, end_year }) => {
|
|
84
|
+
try {
|
|
85
|
+
// Resolve domain
|
|
86
|
+
let domain = "0000";
|
|
87
|
+
let domainName = "Indonesia";
|
|
88
|
+
if (region.toLowerCase() !== "indonesia" && region !== "0000") {
|
|
89
|
+
const resolved = await resolver.resolve(region);
|
|
90
|
+
if (!resolved) {
|
|
91
|
+
return { content: [{ type: "text", text: `Wilayah "${region}" tidak ditemukan.` }], isError: true };
|
|
92
|
+
}
|
|
93
|
+
domain = resolved.domainId;
|
|
94
|
+
domainName = resolved.domainName;
|
|
95
|
+
}
|
|
96
|
+
// Find variable
|
|
97
|
+
const varData = await resolveVariable(client, store, query, domain);
|
|
98
|
+
if (!varData) {
|
|
99
|
+
return { content: [{ type: "text", text: appendAttribution(`Tidak ditemukan variabel "${query}" untuk ${domainName}.`) }] };
|
|
100
|
+
}
|
|
101
|
+
// Build year range
|
|
102
|
+
const startNum = parseInt(start_year);
|
|
103
|
+
const endNum = parseInt(end_year);
|
|
104
|
+
const years = [];
|
|
105
|
+
for (let y = startNum; y <= endNum; y++)
|
|
106
|
+
years.push(String(y));
|
|
107
|
+
// Get periods for all years
|
|
108
|
+
const periods = await client.listPeriods(domain, varData.var_id);
|
|
109
|
+
const yearToPeriod = {};
|
|
110
|
+
for (const p of periods) {
|
|
111
|
+
const pAny = p;
|
|
112
|
+
const label = String(pAny.th_name || pAny.th || pAny.label || "");
|
|
113
|
+
const id = String(p.th_id ?? pAny.val);
|
|
114
|
+
for (const y of years) {
|
|
115
|
+
if (label.includes(y))
|
|
116
|
+
yearToPeriod[y] = id;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
const periodIds = years.map(y => yearToPeriod[y]).filter(Boolean);
|
|
120
|
+
if (periodIds.length === 0) {
|
|
121
|
+
return { content: [{ type: "text", text: appendAttribution(`Tidak ada data periode ${start_year}-${end_year} untuk variabel ini.`) }] };
|
|
122
|
+
}
|
|
123
|
+
// Fetch data
|
|
124
|
+
const result = await client.getDynamicData(domain, String(varData.var_id), periodIds.join(","));
|
|
125
|
+
if (!result.datacontent || Object.keys(result.datacontent).length === 0) {
|
|
126
|
+
return { content: [{ type: "text", text: appendAttribution(`Data tidak tersedia untuk periode ${start_year}-${end_year}.`) }] };
|
|
127
|
+
}
|
|
128
|
+
// Parse datacontent — match period IDs to values
|
|
129
|
+
// Build period label map from response
|
|
130
|
+
const periodLabels = {};
|
|
131
|
+
if (result.tahun) {
|
|
132
|
+
for (const t of result.tahun) {
|
|
133
|
+
const tAny = t;
|
|
134
|
+
const id = String(t.th_id ?? tAny.val);
|
|
135
|
+
const label = String(t.th_name ?? tAny.label ?? id);
|
|
136
|
+
periodLabels[id] = label;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// Extract values — find entries matching the domain (for provincial data, filter by domain prefix)
|
|
140
|
+
const trendData = [];
|
|
141
|
+
for (const [key, value] of Object.entries(result.datacontent)) {
|
|
142
|
+
if (typeof value !== "number")
|
|
143
|
+
continue;
|
|
144
|
+
// Find which period this key belongs to
|
|
145
|
+
for (const pid of periodIds) {
|
|
146
|
+
if (key.includes(pid)) {
|
|
147
|
+
// For provincial data, only take the aggregate (key starts with domain or short key)
|
|
148
|
+
const label = periodLabels[pid] || pid;
|
|
149
|
+
// Avoid duplicates and take only the first match (aggregate)
|
|
150
|
+
if (!trendData.some(d => d.year === label)) {
|
|
151
|
+
trendData.push({ year: label, value });
|
|
152
|
+
}
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
trendData.sort((a, b) => a.year.localeCompare(b.year));
|
|
158
|
+
if (trendData.length === 0) {
|
|
159
|
+
return { content: [{ type: "text", text: appendAttribution(`Data tren tidak dapat di-parse.`) }] };
|
|
160
|
+
}
|
|
161
|
+
// Format output
|
|
162
|
+
const unit = varData.unit ? ` (${varData.unit})` : "";
|
|
163
|
+
const lines = [
|
|
164
|
+
`## Tren ${varData.title}${unit}`,
|
|
165
|
+
`**Wilayah:** ${domainName} | **Periode:** ${start_year}–${end_year}`,
|
|
166
|
+
"",
|
|
167
|
+
"| Tahun | Nilai | Perubahan |",
|
|
168
|
+
"| --- | --- | --- |",
|
|
169
|
+
];
|
|
170
|
+
for (let i = 0; i < trendData.length; i++) {
|
|
171
|
+
const d = trendData[i];
|
|
172
|
+
let change = "-";
|
|
173
|
+
if (i > 0) {
|
|
174
|
+
const diff = d.value - trendData[i - 1].value;
|
|
175
|
+
const pct = ((diff / trendData[i - 1].value) * 100).toFixed(1);
|
|
176
|
+
change = `${diff > 0 ? "+" : ""}${pct}%`;
|
|
177
|
+
}
|
|
178
|
+
lines.push(`| ${d.year} | ${d.value.toLocaleString("id-ID")} | ${change} |`);
|
|
179
|
+
}
|
|
180
|
+
// Summary
|
|
181
|
+
if (trendData.length >= 2) {
|
|
182
|
+
const first = trendData[0].value;
|
|
183
|
+
const last = trendData[trendData.length - 1].value;
|
|
184
|
+
const totalChange = ((last - first) / first * 100).toFixed(1);
|
|
185
|
+
const trend = last > first ? "naik" : last < first ? "turun" : "stabil";
|
|
186
|
+
lines.push("");
|
|
187
|
+
lines.push(`**Tren:** ${trend} ${totalChange}% dari ${trendData[0].year} ke ${trendData[trendData.length - 1].year}`);
|
|
188
|
+
}
|
|
189
|
+
return { content: [{ type: "text", text: appendAttribution(lines.join("\n")) }] };
|
|
190
|
+
}
|
|
191
|
+
catch (error) {
|
|
192
|
+
return { content: [{ type: "text", text: error instanceof Error ? error.message : "Gagal mengambil data tren" }], isError: true };
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
// ---------- get_ranking ----------
|
|
196
|
+
server.tool("get_ranking", `Ambil peringkat/ranking provinsi berdasarkan indikator tertentu dalam 1 langkah.
|
|
197
|
+
Gunakan tool ini ketika user ingin melihat peringkat, top-N, atau perbandingan seluruh provinsi.
|
|
198
|
+
|
|
199
|
+
Contoh query user yang cocok untuk tool ini:
|
|
200
|
+
- "10 provinsi termiskin di Indonesia"
|
|
201
|
+
- "peringkat IPM seluruh provinsi"
|
|
202
|
+
- "provinsi dengan pengangguran tertinggi"
|
|
203
|
+
- "ranking kemiskinan per provinsi 2023"
|
|
204
|
+
- "5 provinsi dengan penduduk terbanyak"`, {
|
|
205
|
+
query: z.string().describe("Indikator untuk ranking (misal: kemiskinan, pengangguran, IPM, penduduk)"),
|
|
206
|
+
top_n: z.number().default(10).describe("Jumlah data yang ditampilkan (default 10, max 34 untuk semua provinsi)"),
|
|
207
|
+
order: z.enum(["highest", "lowest"]).default("highest").describe("Urutan: 'highest' (tertinggi dulu) atau 'lowest' (terendah dulu)"),
|
|
208
|
+
year: z.string().optional().describe("Tahun data. Kosongkan untuk terbaru."),
|
|
209
|
+
}, async ({ query, top_n, order, year }) => {
|
|
210
|
+
try {
|
|
211
|
+
// For ranking, we need national-level data that breaks down by province
|
|
212
|
+
// Prefer variables with "Provinsi" in title for proper provincial breakdown
|
|
213
|
+
const varData = await resolveVariableForRanking(client, store, query);
|
|
214
|
+
if (!varData) {
|
|
215
|
+
return { content: [{ type: "text", text: appendAttribution(`Tidak ditemukan variabel "${query}" untuk ranking nasional.`) }] };
|
|
216
|
+
}
|
|
217
|
+
// Get latest period
|
|
218
|
+
let periodParam;
|
|
219
|
+
if (year) {
|
|
220
|
+
const periods = await client.listPeriods("0000", varData.var_id);
|
|
221
|
+
for (const p of periods) {
|
|
222
|
+
const pAny = p;
|
|
223
|
+
const label = String(pAny.th_name || pAny.th || pAny.label || "");
|
|
224
|
+
if (label.includes(year)) {
|
|
225
|
+
periodParam = String(p.th_id ?? pAny.val);
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
if (!periodParam) {
|
|
231
|
+
const periods = await client.listPeriods("0000", varData.var_id);
|
|
232
|
+
if (periods.length > 0) {
|
|
233
|
+
const pAny = periods[0];
|
|
234
|
+
periodParam = String(periods[0].th_id ?? pAny.val);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
const result = await client.getDynamicData("0000", String(varData.var_id), periodParam);
|
|
238
|
+
if (!result.datacontent || Object.keys(result.datacontent).length === 0) {
|
|
239
|
+
return { content: [{ type: "text", text: appendAttribution(`Data ranking tidak tersedia.`) }] };
|
|
240
|
+
}
|
|
241
|
+
// Build vervar (province) label map
|
|
242
|
+
const vervarLabels = {};
|
|
243
|
+
if (result.vervar) {
|
|
244
|
+
for (const v of result.vervar) {
|
|
245
|
+
const vAny = v;
|
|
246
|
+
const id = String(v.kode_vervar ?? vAny.val);
|
|
247
|
+
const label = String(v.label_vervar ?? vAny.label ?? id);
|
|
248
|
+
vervarLabels[id] = label;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
// Extract province-level data
|
|
252
|
+
const rankings = [];
|
|
253
|
+
for (const [key, value] of Object.entries(result.datacontent)) {
|
|
254
|
+
if (typeof value !== "number")
|
|
255
|
+
continue;
|
|
256
|
+
// Match vervar ID in the key
|
|
257
|
+
for (const [vId, vLabel] of Object.entries(vervarLabels)) {
|
|
258
|
+
if (key.includes(vId) && !rankings.some(r => r.province === vLabel)) {
|
|
259
|
+
rankings.push({ province: vLabel, value });
|
|
260
|
+
break;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
if (rankings.length === 0) {
|
|
265
|
+
return { content: [{ type: "text", text: appendAttribution(`Data ranking tidak dapat di-parse. Coba gunakan find_data untuk masing-masing wilayah.`) }] };
|
|
266
|
+
}
|
|
267
|
+
// Sort
|
|
268
|
+
rankings.sort((a, b) => order === "highest" ? b.value - a.value : a.value - b.value);
|
|
269
|
+
const display = rankings.slice(0, Math.min(top_n, rankings.length));
|
|
270
|
+
// Format
|
|
271
|
+
const unit = varData.unit ? ` (${varData.unit})` : "";
|
|
272
|
+
const lines = [
|
|
273
|
+
`## Ranking: ${varData.title}${unit}`,
|
|
274
|
+
`**Urutan:** ${order === "highest" ? "Tertinggi" : "Terendah"} | **Tahun:** ${year || "Terbaru"}`,
|
|
275
|
+
"",
|
|
276
|
+
"| # | Wilayah | Nilai |",
|
|
277
|
+
"| --- | --- | --- |",
|
|
278
|
+
];
|
|
279
|
+
for (let i = 0; i < display.length; i++) {
|
|
280
|
+
lines.push(`| ${i + 1} | ${display[i].province} | ${display[i].value.toLocaleString("id-ID")} |`);
|
|
281
|
+
}
|
|
282
|
+
if (rankings.length > display.length) {
|
|
283
|
+
lines.push("");
|
|
284
|
+
lines.push(`_Menampilkan ${display.length} dari ${rankings.length} wilayah._`);
|
|
285
|
+
}
|
|
286
|
+
return { content: [{ type: "text", text: appendAttribution(lines.join("\n")) }] };
|
|
287
|
+
}
|
|
288
|
+
catch (error) {
|
|
289
|
+
return { content: [{ type: "text", text: error instanceof Error ? error.message : "Gagal mengambil data ranking" }], isError: true };
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
// --- Helper functions ---
|
|
294
|
+
/** Resolve variable for a domain using learning store + full search fallback. */
|
|
295
|
+
async function resolveVariable(client, store, query, domain) {
|
|
296
|
+
// Try learning store first
|
|
297
|
+
const learned = await lookupVar(query, domain, store);
|
|
298
|
+
if (learned)
|
|
299
|
+
return learned;
|
|
300
|
+
// Full search
|
|
301
|
+
const kw = normalizeKeyword(query);
|
|
302
|
+
const KEYWORD_SUBJECTS = {
|
|
303
|
+
pengangguran: [6], tenaga: [6], kerja: [6], tpt: [6],
|
|
304
|
+
miskin: [23], kemiskinan: [23], gini: [23], ketimpangan: [23],
|
|
305
|
+
penduduk: [12], kependudukan: [12],
|
|
306
|
+
inflasi: [3], harga: [3], ihk: [3],
|
|
307
|
+
pdrb: [52], ekonomi: [52, 35], pertumbuhan: [52],
|
|
308
|
+
ipm: [26], pembangunan: [26],
|
|
309
|
+
ekspor: [8], impor: [8],
|
|
310
|
+
};
|
|
311
|
+
const subjectIds = [];
|
|
312
|
+
for (const [keyword, ids] of Object.entries(KEYWORD_SUBJECTS)) {
|
|
313
|
+
if (kw.includes(keyword))
|
|
314
|
+
subjectIds.push(...ids);
|
|
315
|
+
}
|
|
316
|
+
// Also match from subject titles
|
|
317
|
+
const subjects = await client.listSubjects(domain);
|
|
318
|
+
for (const s of subjects.data) {
|
|
319
|
+
if (kw.split(/\s+/).some(w => w.length > 2 && s.title.toLowerCase().includes(w))) {
|
|
320
|
+
if (!subjectIds.includes(s.sub_id))
|
|
321
|
+
subjectIds.push(s.sub_id);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
for (const subId of subjectIds.slice(0, 3)) {
|
|
325
|
+
const result = await client.listVariables(domain, subId, undefined, 1, 100);
|
|
326
|
+
if (!result.data)
|
|
327
|
+
continue;
|
|
328
|
+
for (const v of result.data) {
|
|
329
|
+
const titleLower = v.title.toLowerCase();
|
|
330
|
+
if (titleLower.includes(kw) || kw.split(/\s+/).some(w => w.length > 2 && titleLower.includes(w))) {
|
|
331
|
+
const found = { var_id: v.var_id, title: v.title, sub_name: v.sub_name, unit: v.unit };
|
|
332
|
+
await learnVar(query, domain, found, store);
|
|
333
|
+
return found;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
return null;
|
|
338
|
+
}
|
|
339
|
+
/** Fetch a single data value for a domain+query+year. */
|
|
340
|
+
async function fetchDataForDomain(client, store, query, domain, year) {
|
|
341
|
+
const varData = await resolveVariable(client, store, query, domain);
|
|
342
|
+
if (!varData)
|
|
343
|
+
return { value: "N/A", varTitle: "" };
|
|
344
|
+
// Resolve period
|
|
345
|
+
let periodParam;
|
|
346
|
+
const periods = await client.listPeriods(domain, varData.var_id);
|
|
347
|
+
if (year && periods.length > 0) {
|
|
348
|
+
for (const p of periods) {
|
|
349
|
+
const pAny = p;
|
|
350
|
+
const label = String(pAny.th_name || pAny.th || pAny.label || "");
|
|
351
|
+
if (label.includes(year)) {
|
|
352
|
+
periodParam = String(p.th_id ?? pAny.val);
|
|
353
|
+
break;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
if (!periodParam && periods.length > 0) {
|
|
358
|
+
const pAny = periods[0];
|
|
359
|
+
periodParam = String(periods[0].th_id ?? pAny.val);
|
|
360
|
+
}
|
|
361
|
+
const result = await client.getDynamicData(domain, String(varData.var_id), periodParam);
|
|
362
|
+
if (!result.datacontent || Object.keys(result.datacontent).length === 0) {
|
|
363
|
+
return { value: "N/A", varTitle: varData.title };
|
|
364
|
+
}
|
|
365
|
+
// Get the aggregate value (first entry or the one matching the domain)
|
|
366
|
+
const values = Object.values(result.datacontent).filter(v => typeof v === "number");
|
|
367
|
+
if (values.length === 0)
|
|
368
|
+
return { value: "N/A", varTitle: varData.title };
|
|
369
|
+
// First value is typically the aggregate for the domain
|
|
370
|
+
const val = values[0];
|
|
371
|
+
const unit = varData.unit ? ` ${varData.unit}` : "";
|
|
372
|
+
return { value: `${val.toLocaleString("id-ID")}${unit}`, varTitle: varData.title };
|
|
373
|
+
}
|
|
374
|
+
/** Resolve variable for ranking — prefer "Menurut Provinsi" variants at national level. */
|
|
375
|
+
async function resolveVariableForRanking(client, store, query) {
|
|
376
|
+
const kw = normalizeKeyword(query);
|
|
377
|
+
const kwWords = kw.split(/\s+/).filter(w => w.length > 2);
|
|
378
|
+
// Add root words for common Indonesian affixes: ke-...-an → root
|
|
379
|
+
const roots = [...kwWords];
|
|
380
|
+
for (const w of kwWords) {
|
|
381
|
+
if (w.startsWith("ke") && w.endsWith("an") && w.length > 6)
|
|
382
|
+
roots.push(w.slice(2, -2)); // kemiskinan → miskin
|
|
383
|
+
if (w.startsWith("pe") && w.endsWith("an") && w.length > 6)
|
|
384
|
+
roots.push(w.slice(2, -2)); // pengangguran → nganggur
|
|
385
|
+
if (w.endsWith("an") && w.length > 5)
|
|
386
|
+
roots.push(w.slice(0, -2)); // pengangguran → pengangguran (already), kemiskinan → kemiskina (not useful but harmless)
|
|
387
|
+
}
|
|
388
|
+
const matchesTitle = (t) => roots.some(r => t.includes(r));
|
|
389
|
+
const KEYWORD_SUBJECTS = {
|
|
390
|
+
miskin: [23], kemiskinan: [23], gini: [23],
|
|
391
|
+
pengangguran: [6], tpt: [6],
|
|
392
|
+
penduduk: [12], ipm: [26],
|
|
393
|
+
};
|
|
394
|
+
const subjectIds = [];
|
|
395
|
+
for (const [keyword, ids] of Object.entries(KEYWORD_SUBJECTS)) {
|
|
396
|
+
if (kw.includes(keyword))
|
|
397
|
+
subjectIds.push(...ids);
|
|
398
|
+
}
|
|
399
|
+
if (subjectIds.length === 0)
|
|
400
|
+
subjectIds.push(23, 6, 12, 26);
|
|
401
|
+
// Search for variables with "Provinsi" in title
|
|
402
|
+
for (const subId of subjectIds.slice(0, 3)) {
|
|
403
|
+
const result = await client.listVariables("0000", subId, undefined, 1, 100);
|
|
404
|
+
if (!result.data)
|
|
405
|
+
continue;
|
|
406
|
+
// First pass: find one with "Provinsi" AND matching keyword
|
|
407
|
+
for (const v of result.data) {
|
|
408
|
+
const t = v.title.toLowerCase();
|
|
409
|
+
if (t.includes("provinsi") && matchesTitle(t)) {
|
|
410
|
+
// Prefer "persentase" or "tingkat" variants (main indicators)
|
|
411
|
+
if (t.includes("persentase") || t.includes("tingkat") || t.includes("indeks")) {
|
|
412
|
+
return { var_id: v.var_id, title: v.title, sub_name: v.sub_name, unit: v.unit };
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
// Second pass: "Provinsi" + keyword match (any)
|
|
417
|
+
for (const v of result.data) {
|
|
418
|
+
const t = v.title.toLowerCase();
|
|
419
|
+
if (t.includes("provinsi") && matchesTitle(t)) {
|
|
420
|
+
return { var_id: v.var_id, title: v.title, sub_name: v.sub_name, unit: v.unit };
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
// Second pass: any match without "Provinsi" requirement
|
|
424
|
+
for (const v of result.data) {
|
|
425
|
+
const t = v.title.toLowerCase();
|
|
426
|
+
if (t.includes(kw) || kw.split(/\s+/).some(w => w.length > 2 && t.includes(w))) {
|
|
427
|
+
return { var_id: v.var_id, title: v.title, sub_name: v.sub_name, unit: v.unit };
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
// Fallback to general resolver
|
|
432
|
+
return resolveVariable(client, store, query, "0000");
|
|
433
|
+
}
|
|
434
|
+
//# sourceMappingURL=analysis.tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analysis.tools.js","sourceRoot":"","sources":["../../src/tools/analysis.tools.ts"],"names":[],"mappings":"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"}
|