Metadata-Version: 2.4
Name: dalang
Version: 0.2.0
Summary: Dalang (Data Analytics LANGuage): bahasa analisis data yang mudah dibaca, dengan konteks eksplisit. Versi 0.2.0: MODEL, measure, kalender, dan perbandingan waktu di atas DuckDB.
Author: Tim Dalang
License-Expression: Apache-2.0
Keywords: data analytics,language,dax,duckdb,bahasa indonesia
Classifier: Development Status :: 2 - Pre-Alpha
Classifier: Intended Audience :: Education
Classifier: Intended Audience :: Science/Research
Classifier: Natural Language :: Indonesian
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development :: Compilers
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: duckdb>=1.1
Provides-Extra: grafik
Requires-Dist: matplotlib>=3.7; extra == "grafik"
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Requires-Dist: matplotlib>=3.7; extra == "dev"
Dynamic: license-file

# Dalang (Data Analytics LANGuage)

Dalang adalah bahasa analisis data yang mudah dibaca, dirancang untuk pengguna DAX/Power BI dan analis data, dari pemula awam sampai mahir. Konteks perhitungan selalu tertulis eksplisit di kode, dan pesan error berbahasa Indonesia.

```basic
LET sales = LOAD CSV "penjualan.csv"

MODEL Store
    TABLES sales
    CALENDAR sales.tanggal
    MEASURE Omzet = SUM(sales.nilai)
    MEASURE Growth = (Omzet - Omzet PREVIOUS YEAR) / Omzet PREVIOUS YEAR
END MODEL

SHOW Omzet, Growth BY kota WHERE YEAR = 2025
EXPLAIN Omzet AT kota = "Jakarta", YEAR = 2025
```

## Status versi 0.2.0

Versi 0.2.0 menambahkan **MODEL**: measure yang dihitung ulang di dalam konteks, seperti DAX, tetapi semua konteksnya tertulis di kode. Kesepuluh Program Target (1–9 dan kasus error E1–E6) kini lolos sebagai golden test.

- **`dal run`**: menjalankan file `.dal` (diterjemahkan ke Python, lalu dijalankan di atas DuckDB).
  - `--set nama=nilai` mengganti nilai `PARAMETER` (boleh berulang).
  - `--show-python` menampilkan kode Python hasil terjemahan.
- **`dal check`**: memeriksa file `.dal` tanpa menjalankannya.
- **`dal parse`**: menampilkan cara Dalang membaca program, dengan setiap ekspresi berkurung lengkap.

### MODEL (baru di 0.2.0)

```basic
LET sales = LOAD CSV "penjualan.csv"
LET products = LOAD CSV "produk.csv"

MODEL Store
    TABLES sales, products
    RELATE sales.kode TO products.kode
    CALENDAR sales.tanggal
    MEASURE Omzet = SUM(sales.nilai)
    MEASURE Growth = (Omzet - Omzet PREVIOUS YEAR) / Omzet PREVIOUS YEAR
END MODEL

SHOW Omzet, Omzet PREVIOUS YEAR, Growth BY kota WHERE YEAR = 2025 WITH totals: TRUE
```

```text
kota     Omzet  Omzet PREVIOUS YEAR  Growth
-------  -----  -------------------  ------
Bandung    100                   50  100,0%
Jakarta    290                  170   70,6%
Total      390                  220   77,3%
```

- `RELATE`: filter mengalir dari tabel "satu" ke tabel "banyak" (`BY products.kategori` menyaring `sales`). Kunci sisi "satu" wajib unik. Baris tanpa pasangan masuk kelompok MISSING, disertai peringatan.
- `CALENDAR`: dimensi waktu `YEAR`, `QUARTER`, `MONTH`, `WEEK` (ISO), `DAY` tanpa tabel tanggal terpisah. Kalender hanya mencakup rentang data.
- Pengubah: `PREVIOUS YEAR`, `LAST 3 MONTH`, `YEAR TO DATE`, `IGNORE FILTER kota`, `AS SHARE OF kota`, `(Omzet WHERE kota = "Jakarta")` (irisan, tidak menimpa), `Omzet AT kota = "Jakarta", YEAR = 2025`.
- `MEAN(Omzet) FOR EACH ROW OF products`: iterasi dengan measure di dalamnya.
- `SHOW TOP 2 products BY Omzet`, `EXPLAIN Omzet AT …` (menunjukkan rumus, filter, dan jumlah baris), `TEST … EXPECT … END TEST`.
- `WITH totals: TRUE` dihitung ulang (bukan dijumlah); baris yang semua nilainya MISSING disembunyikan kecuali `WITH show_empty: TRUE`.
- Measure juga bisa dipakai di `IF`, `LET`, dan fungsi biasa: `IF (Growth WHERE kota = k AND YEAR = tahun) IS MISSING THEN …`.
- Tampilan persen otomatis: pembagian dua besaran yang sama (misalnya Omzet dibagi Omzet tahun lalu) dan `AS SHARE OF` ditampilkan sebagai `70,6%`. Nilai aslinya tetap 0,706.

### Yang sudah bisa dijalankan sejak 0.1.0

- `LOAD CSV` (pemisah `;`, `,`, tab, atau `|` dikenali otomatis), `SAVE ... AS CSV`;
- tabel: `WHERE`, `SELECT`, `SORT BY ... DESCENDING`, `TOP n tabel BY kolom`, kolom baru `LET sales.pajak = nilai * 0.11`, `RENAME`, `REMOVE`, `FILL`, `APPEND`;
- `SHOW` ringkasan `SUM`/`MEAN`/`MEDIAN`/`MIN`/`MAX`/`COUNT`/`COUNTDISTINCT`/`STDEV`/`VARIANCE` dengan `BY` dan `WHERE`, serta opsi `rows`, `totals`, `show_empty`;
- `PLOT ... BY ...`: grafik teks di layar, dan file PNG bila matplotlib terpasang;
- `LET`, `SET`, `PARAMETER`, `IF`, `FOR`, `FOR EACH`, `WHILE`, `EXIT`, `CONTINUE`, `FUNCTION`, `RETURN`, `TRY`/`CATCH`, `FAIL`;
- `USE PYTHON "paket" AS alias`;
- aturan MISSING dan angka format Indonesia (`1.250.000`, `42,9`).

Keamanan: nilai dari program tidak pernah disambung ke teks SQL. Semua nilai dikirim sebagai parameter kueri.

Belum didukung (pesan jelas, program tidak dijalankan sebagian): `RANK`, `JOIN`, `EXPORT`, `ASK`, `FORECAST`, `REGRESS`, `USE R`, modul `.dal`, `LOAD EXCEL`/`PARQUET`. Pengubah waktu belum bisa menggeser filter periodik seperti `WHERE MONTH = 3` (pakai `BY MONTH` atau `WHERE YEAR = …`).

Yang diperiksa `dal check`:

- seluruh susunan kalimat menurut Tata Bahasa v0.1 (misalnya `IF` tanpa `THEN`, `WHERE` tanpa kurung di dalam syarat `IF`/`EXPECT`, `MEASURE` di luar `MODEL`, kata kunci dipakai sebagai nama);
- teks yang belum ditutup, karakter tak dikenal, kurung tak berpasangan, `!=` (gunakan `<>`);
- bentuk lama yang tidak berlaku (`PRINT`, `REM`, `ELSEIF`, `NEXT` sebagai penutup `FOR`, `DESC`, satuan jamak seperti `MONTHS`);
- nama dan kolom yang tidak ada, dengan saran nama yang mirip (dibaca dari header CSV);
- aturan `MODEL`: `TABLES` wajib, kunci `RELATE` unik, `CALENDAR` bertipe tanggal, nama measure tidak sama dengan nama kolom;
- `PREVIOUS`, `LAST`, dan `... TO DATE` tanpa konteks waktu, termasuk lewat measure lain;
- operasi aritmetika pada teks, termasuk `WHERE` tanpa kurung yang menelan pembagian;
- `FOR EACH ROW OF` hanya untuk ekspresi berisi measure;
- `LET`/`SET`/`PARAMETER` (parameter hanya-baca), fungsi bawaan dan jumlah argumennya, nama fungsi lama seperti `AVERAGE`;
- keseimbangan blok `IF`/`FOR`/`WHILE`/`FUNCTION`/`MODEL`/`TEST`/`TRY` dengan `END` pasangannya;
- `USE` dan `PARAMETER` wajib di bagian atas file, dan `USE` wajib memakai `AS`;
- koma di dalam `WHERE` (syarat digabung dengan `AND`/`OR`);
- `TOP` tanpa `BY`.

## Pemasangan dan pemakaian

```bash
pip install dalang
dal --version
dal check analisis.dal
dal run analisis.dal
dal run analisis.dal --set tahun=2024
```

Untuk grafik PNG: `pip install "dalang[grafik]"`.

Contoh `dal run` (Program 2 di `examples/`):

```text
610
kota     SUM(sales.nilai)  COUNT(sales)
-------  ----------------  ------------
Bandung               150             3
Jakarta               460             5
```

Contoh keluaran `dal check`:

```text
Kesalahan di analisis.dal baris 1:
    PRINT Omzet
    ^^^^^
PRINT tidak ada di Dalang. Gunakan SHOW.

[GAGAL] analisis.dal: 1 kesalahan
```

## Pengembangan

```bash
pip install -e ".[dev]"
pytest
```

Folder `examples/` berisi Program Target 1–9 dan kasus error E1–E6 yang menjadi golden test. Program 1–4 diuji oleh `tests/test_run.py`, Program 5–9 oleh `tests/test_model.py`.

## Lisensi

Dalang dirilis di bawah [Apache License 2.0](LICENSE).
