File size: 12,560 Bytes
2b62b0c
99d1f6e
 
 
2b62b0c
 
99d1f6e
 
 
 
 
 
2b62b0c
 
99d1f6e
2b62b0c
 
 
99d1f6e
2b62b0c
99d1f6e
 
 
 
2b62b0c
 
 
 
 
 
 
 
 
 
 
 
99d1f6e
 
 
2b62b0c
 
 
 
 
 
99d1f6e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2b62b0c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
ο»Ώ# PRD: Pram β€” AI-Powered CPNS Test Practice Platform

## Problem Statement

Calon Pegawai Negeri Sipil (CPNS) di Indonesia kesulitan menemukan soal latihan yang:
- **Bervariasi** dan mencakup format soal spesifik (TWK, TIU, TKP)
- **Terjangkau** β€” platform existing biasanya berbayar dan tidak fleksibel
- **Relevan** dengan kelemahan personal β€” tidak ada analisis per-section yang memberi rekomendasi perbaikan
- **Terbuka** β€” tidak ada platform open-source "bring your own key" untuk generasi soal AI

## Solution

**Pram** adalah platform open-source yang menyediakan:
1. **AI Question Generator** β€” generate soal CPNS pakai OpenAI-compatible API (BYOK). Dua mode: quick (single prompt) dan agentic (multi-step validation)
2. **Question Bank** β€” kumpulan soal publik/privat yang bisa di-browse, di-rating, dan digunakan ulang
3. **Package Builder** β€” susun paket soal dari kombinasi soal existing + AI-generated
4. **Exam Interface** β€” antarmuka ujian simulasi CAT (Computer Assisted Test)
5. **Deep Analytics** β€” evaluasi per-section (TWK, TIU, TKP), identifikasi kelemahan, rekomendasi paket soal

Target pengguna: Calon Pegawai Negeri Sipil (CPNS) Indonesia.

## User Stories

### AI Generation
1. Sebagai peserta, saya ingin generate soal CPNS dengan AI menggunakan API key saya sendiri
2. Sebagai peserta, saya ingin memilih section (TWK, TIU, TKP) dan tingkat kesulitan sebelum generate
3. Sebagai peserta, saya ingin memilih topik spesifik (Pancasila, Deret Angka, Pelayanan Publik, dll.)
4. Sebagai power user, saya ingin menggunakan mode "agentic" untuk validasi kualitas soal yang lebih tinggi

## Exam Sections Supported

| Section | Type | Focus Areas |
|---------|------|-------------|
| TWK | Tes Wawasan Kebangsaan | Nasionalisme, Integritas, Bela Negara, Pilar Negara, Bahasa Indonesia |
| TIU | Tes Intelegensia Umum | Analogi, Silogisme, Analitis, Deret Angka, Perbandingan, Soal Cerita, Figural |
| TKP | Tes Karakteristik Pribadi | Pelayanan Publik, Jejaring Kerja, Sosial Budaya, TIK, Profesionalisme, Anti Radikalisme |

## Question Formats

Semua soal CPNS menggunakan format **Multiple Choice** dengan 5 pilihan jawaban (A, B, C, D, E). Beberapa format tambahan untuk latihan:
- Multiple Choice (Standard)
- Benar / Salah (Latihan Konsep)
- Melengkapi Kalimat (Bahasa Indonesia)
- Analogi & Silogisme (TIU)
- Deret Angka (TIU)

## Implementation Decisions

### Tech Stack
- **Frontend**: React 19 + TanStack Router (SPA) + TanStack Query + Tailwind CSS 4 + shadcn/ui
- **Backend**: Hono + tRPC
- **Auth**: Better Auth (email/password)
- **Database**: PostgreSQL + Drizzle ORM
- **AI**: OpenAI-compatible API (generic interface, user-provided keys)
- **Monorepo**: Turborepo + Bun workspaces
- **Theme**: Light default, dark toggle (system preference aware via next-themes)

### Architecture

```
apps/web/            React SPA frontend
  routes/            File-based routes (TanStack Router)
    index.tsx        Landing / Home
    generate.tsx     AI Generator wizard
    bank.tsx         Question Bank browse
    bank/$id.tsx     Package / Question detail
    builder.tsx      Test Builder (craft package)
    builder/combo.tsx Package Combiner
    exam/$id.tsx     Exam Interface
    exam/$id/result.tsx  Exam Results
    analytics.tsx    Deep Analytics dashboard
    settings.tsx     Settings (API keys, profile)

apps/server/         Hono backend
  Mounts Better Auth + tRPC

packages/
  ai/                AI generation pipeline (new)
  api/               tRPC routers + context
    routers/
      ai.ts          generateQuestions (streaming)
      question.ts    CRUD questions, search, filter
      package.ts     CRUD packages, sections
      combo.ts       Combo package creation
      exam.ts        Attempts, grading, results
      analytics.ts   Stats, trends, recommendations
      settings.ts    API key management
  auth/              Better Auth config
  db/                Drizzle ORM schema
  ui/                shadcn/ui shared components
  env/               Environment validation
```

### Deep Modules (testable in isolation)

- **`packages/ai/`** β€” AI generation pipeline
  - Interface: `generateQuestions(input: GenerationInput) => GenerationResult`
  - Two pipelines: `quick` (single call) and `agentic` (multi-step)
  - Zod schemas for all question formats (type-safe generation + validation)
  - OpenAI-compatible client abstraction

- **`packages/api/src/routers/`** β€” tRPC routers
  - Each router encapsulates one domain with clear procedures

### Database Schema (New Tables)

```
exam_type          id, name, language, description
section_type       id, name
question           id, exam_type_id, section_type_id, format, passage_text,
                   question_text, options_json, correct_answer, explanation,
                   difficulty (1-5), skill_tags[], source (ai|manual),
                   ai_model, creator_user_id, is_public, usage_count, avg_rating
package            id, title, description, exam_type_id, creator_user_id,
                   is_public, total_questions, usage_count, avg_rating
package_section    id, package_id, section_type_id, title, order_index
section_question   id, section_id, question_id, order_index
combo_package      id, title, description, creator_user_id, is_public
combo_section      id, combo_id, source_package_id, source_section_id, order_index
test_attempt       id, user_id, package_id_or_combo_id, started_at, finished_at, total_score
section_result     id, attempt_id, section_type, score, max_score, time_spent_sec
answer             id, section_result_id, question_id, user_answer, is_correct, time_spent_sec
user_api_key       id, user_id, provider, base_url, api_key_encrypted, model_name, is_active
question_rating    id, user_id, question_id, score (1-5), created_at
```

### Agentic AI Pipeline

```
Step 1: Passage Generator   β†’ Authentic reading passage sesuai level ujian
Step 2: Passage Validator   β†’ Validasi akurasi, difficulty, grammar, panjang
Step 3: Question Generator  β†’ Generate N questions dalam format yang diminta
Step 4: Self-Answer & Validate β†’ AI menjawab sendiri, flag ambigu, hitung confidence
Step 5: Quality Scorer      β†’ Overall score, needsHumanReview flag
```

### Weakness Analysis Algorithm

1. Group answers by `section_type` dan `skill_tag`
2. Hitung akurasi per group
3. Identifikasi skill tags dengan akurasi di bawah threshold (default 70%)
4. Sort by `total_attempts * (1 - accuracy)` β€” prioritize yang sering salah
5. Cari paket soal publik dengan skill tags yang match kelemahan user
6. Return top-N rekomendasi paket

---

## Implementation Phases

### Phase 1 β€” Foundation (Schema + Core Infrastructure)
**Goal:** Database siap, user bisa manage API key, AI pipeline dasar berjalan

| # | Task | Package |
|---|------|---------|
| 1.1 | Add application tables to Drizzle schema | `packages/db/` |
| 1.2 | Generate & run migrations | `packages/db/` |
| 1.3 | Create `packages/ai/` β€” OpenAI-compatible client + Zod schemas for all question formats | `packages/ai/` |
| 1.4 | AI key management tRPC router (encrypt/decrypt) | `packages/api/` |
| 1.5 | Settings page β†’ API key CRUD UI | `apps/web/` |
| 1.6 | Quick mode AI generation pipeline (single call) | `packages/ai/` |
| 1.7 | AI Generator router + basic UI page | `packages/api/` + `apps/web/` |

**User stories delivered:** 1, 2, 3, 4, 7, 31, 32, 33

### Phase 2 β€” Question Bank & Packages
**Goal:** Soal bisa disimpan, dipublikasikan, di-browse, dan dibundle

| # | Task | Package |
|---|------|---------|
| 2.1 | Question CRUD tRPC router (search, filter, publish/unpublish) | `packages/api/` |
| 2.2 | Package CRUD tRPC router (create, add sections, add questions) | `packages/api/` |
| 2.3 | Question Bank browse page (grid, search, filters) | `apps/web/` |
| 2.4 | Package detail page (preview soal, rating, stats) | `apps/web/` |
| 2.5 | AI Generator β†’ save result as question / package | `apps/web/` |
| 2.6 | Test Builder page (craft package from bank items) | `apps/web/` |
| 2.7 | Rating system for public questions/packages | `packages/api/` |

**User stories delivered:** 5, 8, 9, 10, 11, 12, 13, 14, 15, 17

### Phase 3 β€” Package Combiner + Agentic Mode
**Goal:** Pengguna bisa mix section dari berbagai paket; power user bisa pakai agentic generation

| # | Task | Package |
|---|------|---------|
| 3.1 | Combo package tRPC router | `packages/api/` |
| 3.2 | Package Combiner UI (select sections from different packages) | `apps/web/` |
| 3.3 | Agentic mode AI pipeline (multi-step) | `packages/ai/` |
| 3.4 | Agentic mode toggle + streaming progress in AI Generator UI | `apps/web/` |

**User stories delivered:** 6, 16

### Phase 4 β€” Exam Experience
**Goal:** Pengguna bisa mengerjakan ujian dengan antarmuka side-by-side, timer, auto-grade

| # | Task | Package |
|---|------|---------|
| 4.1 | Exam attempt + answer submission tRPC router | `packages/api/` |
| 4.2 | Auto-grade logic (untuk semua format objektif) | `packages/api/` |
| 4.3 | Exam Interface page (side-by-side passage + questions) | `apps/web/` |
| 4.4 | Timer component (client-side with periodic sync) | `apps/web/` |
| 4.5 | Question navigation (prev/next/jump, mark for review) | `apps/web/` |
| 4.6 | Auto-save answers | `apps/web/` |
| 4.7 | Exam Results page (per-section scores, answer review) | `apps/web/` |

**User stories delivered:** 18, 19, 20, 21, 22, 23, 24, 25

### Phase 5 β€” Analytics & Recommendations
**Goal:** User bisa melihat performa, kelemahan, dan rekomendasi perbaikan

| # | Task | Package |
|---|------|---------|
| 5.1 | Analytics tRPC router (stats, trends, skill breakdown) | `packages/api/` |
| 5.2 | Weakness identification + recommendation algorithm | `packages/api/` |
| 5.3 | Deep Analytics dashboard page (stats cards, line chart, radar chart) | `apps/web/` |
| 5.4 | Performance by Skill table | `apps/web/` |
| 5.5 | Recommended packages section on dashboard | `apps/web/` |

**User stories delivered:** 26, 27, 28, 29, 30

### Phase 6 β€” Community & Polish
**Goal:** Platform terasa hidup dengan konten komunitas, trending, PWA offline support

| # | Task | Package |
|---|------|---------|
| 6.1 | Trending / most-used packages endpoint | `packages/api/` |
| 6.2 | Staff pick / featured content | `apps/web/` |
| 6.3 | Creator stats (usage count, rating) on profile | `apps/web/` |
| 6.4 | Share link for public packages | `apps/web/` |
| 6.5 | PWA offline support for exam mode (cache questions) | `apps/web/` |
| 6.6 | UI polish, loading skeletons, empty states, error boundaries | `apps/web/` |
| 6.7 | i18n foundation (Bahasa Indonesia UI strings) | `apps/web/` |

**User stories delivered:** 34, 35, 36, 37

---

## Out of Scope

- Mobile app (React Native) β€” web-first, PWA covers mobile
- Writing essay auto-grading β€” terlalu kompleks dan unreliable untuk AI saat ini
- Speaking section generation β€” fokus ke reading comprehension dulu
- Listening audio generation β€” perlu TTS, terlalu kompleks untuk initial release
- Proctoring / anti-cheat
- Subscription / payment system β€” open-source, self-hosted
- Real-time multiplayer
- Social features (comments, following) beyond ratings
- Admin dashboard β€” semua management via DB langsung atau CLI
- Email verification & password reset flow (bisa ditambah nanti)
- OAuth login (Google, GitHub) β€” email/password saja untuk initial release

## Testing Strategy

- **AI package** (`packages/ai/`): Unit tests for Zod validation schemas, integration tests with mocked LLM responses
- **API routers** (`packages/api/src/routers/`): tRPC procedure tests against test database
- **Package Combiner**: Complex business logic β€” priority for testing
- **Auto-grade logic**: Must be correct β€” parametrized tests per format
- **Test structure**: `packages/*/__tests__/` (establishing fresh β€” codebase has no tests yet)

A good test:
- Tests external behavior (API contract), not implementation details
- Uses tRPC test client to call procedures end-to-end
- Isolates AI calls via mocking

## Further Notes

- Repo akan dijadikan open-source β€” semua API key di-skip dari git, dokumentasi jelas untuk self-hosting
- UI text dalam Bahasa Indonesia (target pengguna), kode dalam English
- Soal bisa bilingual (passage dalam bahasa target, instruksi dalam Bahasa Indonesia)
- Timer di exam interface harus client-side dengan periodic sync ke server
- PWA support sudah ada, perlu di-enhance untuk offline exam mode (cache soal)
- Default theme: light, dark toggle tetap ada
- Nama "Pram" dari "labs" + "bahasa"