File size: 16,124 Bytes
aaa634c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
# System Design Document: AlgoSpaced

A cloud-native, mobile-responsive Spaced Repetition System (SRS) designed to help software engineering candidates master the LeetCode 150 patterns. Rather than rote memorization, **AlgoSpaced** optimizes the retention of algorithmic paradigms using dynamic intervals, cloud syncing, an automated LLM Code Reviewer, a gamified Daily Streak System, and an automated Google Drive Ingestion Pipeline.

## 1. System Architecture Overview

The system is designed with a lightweight, cross-platform approach to ensure seamless transition between desktop (IDE practice) and mobile (on-the-go review) views.

```
+--------------------------------------------------------------+
|                        Client Tier                           |
|      (Mobile Browser / Desktop Browser - Streamlit App)      |
+------------------------------+-------------------------------+
                               |
                        HTTPS (JSON / REST)
                               |
                               v
+------------------------------+-------------------------------+
|                        Application Tier                      |
|                  (Python Serverless/Streamlit)                |
+-------+----------------------+-----------------------+-------+
        |                      |                       |
        | Secure API           | Sync Data             | Database Queries
        | (gemini-2.5-flash)   | Google Drive & Docs   | (SSL/TLS Connection)
        v                      v                       v
+-------+--------------------+ +--------------------+ +-------+-------+
|        External AI Engine  | | Google Workspace   | | Database Tier |
|  (Google Gemini API)       | | (Drive & Docs APIs)| | (Supabase/PG) |
+----------------------------+ +--------------------+ +---------------+

```

### Components

1.  **Client Tier (Frontend):** A unified, responsive web interface built using **Streamlit**. It automatically handles fluid widths and touch-friendly target sizes for mobile screens, adapting beautifully between viewports.
    
2.  **Application Tier (Backend Logic):** Python logic running the core Spaced Repetition engine (calculating intervals), processing user code inputs, calculating daily active streaks, coordinating Google Drive folder scans, and structuring payloads for the LLM evaluation.
    
3.  **External AI Engine (Gemini API):** An intelligent grading agent utilizing `gemini-2.5-flash-preview-09-2025` to evaluate candidate code for logical correctness, time/space complexity, and pattern edge-cases.
    
4.  **Database Tier (Cloud Database):** A managed PostgreSQL instance (e.g., Supabase) storing user progress, problem history, review queues, and user streak statistics.
    

## 2. Spaced Repetition & Streak Algorithms

### 2.1 Leitner System Spaced Repetition

To avoid linear burnout, AlgoSpaced implements a customized **Leitner System** optimized for algorithmic patterns. Problems transition between 5 "Boxes", where each box represents a distinct revision interval.

Let the next review date $D_{next}$ for a problem $p$ be defined as:

$$D_{next} = D_{last} + I(b)$$

Where $D_{last}$ is the date of the last review, and $I(b)$ is the interval (in days) associated with the problem's current Box level $b \in \{1, 2, 3, 4, 5\}$:

$$I(b) = \begin{cases} 1 \text{ day} & \text{if } b = 1 \text{ (Forgot / Hard)} \\ 3 \text{ days} & \text{if } b = 2 \\ 7 \text{ days} & \text{if } b = 3 \\ 14 \text{ days} & \text{if } b = 4 \\ 30 \text{ days} & \text{if } b = 5 \text{ (Mastered)} \end{cases}$$

### 2.2 SRS State Transitions

-   **On Correct Evaluation (Easy / AI Approved):**
    
    $$b_{new} = \min(b_{current} + 1, 5)$$
-   **On Mixed Evaluation (Medium / Minor Bugs):**
    
    $$b_{new} = b_{current}$$
    
    _(No change in Box level, but resets the countdown interval to_ $I(b_{current})$ _days from today)_
    
-   **On Incorrect/Forgotten Evaluation (Hard):**
    
    $$b_{new} = 1$$
    
    _(Resets to Box 1 immediately to build retention)_
    

### 2.3 Daily Streak Mathematical Model

To keep motivation high, the system maintains a running daily streak tracking active participation. A streak increments when the user completes at least **one** practice session (submitting code or passing a review) within a calendar day.

Let $T_{now}$ be the current timestamp in the user's localized timezone, and let $Date(T)$ be the calendar date portion of a timestamp. Let $D_{last\_active}$ be the date of the user's last logged review session.

When a review session is completed, the system evaluates the state of the streak:

$$\text{Streak Status} = \begin{cases} \text{No Change} & \text{if } Date(T_{now}) = D_{last\_active} \\ \text{Increment Streak} & \text{if } Date(T_{now}) = D_{last\_active} + 1 \text{ day} \\ \text{Reset Streak to 1} & \text{if } Date(T_{now}) > D_{last\_active} + 1 \text{ day} \end{cases}$$

#### Lazy Streak Verification on Login

To ensure the visual streak updates immediately even before the user starts a session, the frontend runs a checking routine whenever the application loads:

$$\text{Current Streak} = \begin{cases} 0 & \text{if } Date(T_{now}) > D_{last\_active} + 1 \text{ day} \\ \text{Unchanged} & \text{otherwise} \end{cases}$$

## 3. Google Drive Ingestion Pipeline

To make registration friction-free, users only need to drop their LeetCode notes as Google Docs into a dedicated Google Drive folder (e.g., named `LeetCode-150-Reviews`). The system will parse and sync them automatically.

### 3.1 Authentication Workflow

The background sync worker uses a secure Google Cloud service account with specific read-only permissions:

-   **Scope Required:** `https://www.googleapis.com/auth/drive.readonly` and `https://www.googleapis.com/auth/documents.readonly`
    

### 3.2 Document Structured Parsing Rules

Your notes are structured inside the Google Doc in a human-friendly format. The ingestion script parses the Google Doc's JSON structural elements (`body.content`) and applies regex matching to dynamically extract fields:

```
+--------------------------------------------------------------+
|                     Google Doc Layout                        |
+--------------------------------------------------------------+
| Document Title: [Problem Name] (e.g. "Two Sum")              |
|                                                              |
| Pattern: [Pattern Name]                                      |
| Complexity: Time: [O(N)], Space: [O(N)]                      |
|                                                              |
| ---                                                          |
| [Optional: Aha! Moment Line / Key insight]                  |
|                                                              |
| Code:                                                        |
| ```python                                                    |
| ... python code solution ...                                 |
| ```                                                          |
+--------------------------------------------------------------+

```

1.  **Problem Name:** Extracted directly from the Doc filename.
    
2.  **Pattern Name:** Found via Regex search for line: `Pattern:\s*(.*)`. Default to `Unassigned` if not found.
    
3.  **Complexities:** Found via Regex matching: `Time:\s*(\S+)\s*,\s*Space:\s*(\S+)`.
    
4.  **Correct Working Code Block:** Parsed by grabbing all texts following a `Code:` delimiter or inside formatted monospace blocks.
    

## 4. Data Models & Database Schema

The database must be hosted in the cloud to sync perfectly between your phone and laptop. Below is the relational schema designed for **PostgreSQL**.

### PostgreSQL Schema Initialization Script

```
-- Enable UUID extension
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

-- Table: problems
CREATE TABLE problems (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    name VARCHAR(255) NOT NULL UNIQUE,
    pattern VARCHAR(100) NOT NULL,
    difficulty VARCHAR(20) NOT NULL DEFAULT 'Medium' CHECK (difficulty IN ('Easy', 'Medium', 'Hard')),
    google_doc_url TEXT,
    google_doc_id VARCHAR(100) UNIQUE, -- Tracks file to prevent duplicates
    optimal_time VARCHAR(50) NOT NULL DEFAULT 'O(N)',
    optimal_space VARCHAR(50) NOT NULL DEFAULT 'O(N)',
    reference_code TEXT, -- Stores reference code synced from Doc
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

-- Table: user_reviews
CREATE TABLE user_reviews (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    problem_id UUID NOT NULL REFERENCES problems(id) ON DELETE CASCADE,
    box_level INTEGER NOT NULL DEFAULT 1 CHECK (box_level BETWEEN 1 AND 5),
    last_reviewed TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    next_review TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
    times_correct INTEGER NOT NULL DEFAULT 0,
    total_attempts INTEGER NOT NULL DEFAULT 0,
    CONSTRAINT unique_problem_review UNIQUE (problem_id)
);

-- Table: user_streaks
CREATE TABLE user_streaks (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    current_streak INTEGER NOT NULL DEFAULT 0 CHECK (current_streak >= 0),
    longest_streak INTEGER NOT NULL DEFAULT 0 CHECK (longest_streak >= 0),
    last_active_date DATE,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

```

### Table Properties & Metadata

#### Table: `problems` (Modified for Google Sync)

Column Name

Data Type

Constraints

Description

`id`

`UUID`

Primary Key, Default: `uuid_generate_v4()`

Unique problem identifier

`name`

`VARCHAR(255)`

Not Null, Unique

LeetCode title (e.g., "3Sum")

`pattern`

`VARCHAR(100)`

Not Null

Core paradigm (e.g., "Two Pointers")

`google_doc_url`

`TEXT`

Nullable

Hyperlink to personal Google Doc notes

`google_doc_id`

`VARCHAR(100)`

Unique

Unique identifier of file in Google Drive

`reference_code`

`TEXT`

Nullable

The ideal source code extracted from your Doc

## 5. AI Code Reviewer Integration (Gemini API)

To evaluate handwritten code on a mobile device without compiler dependencies, heavy runtimes, or strict test harnesses, the system integrates the Gemini API using `gemini-2.5-flash-preview-09-2025`.

### API Payload Schema Configuration

```
import google.generativeai as genai
from google.genai import types

# Define JSON Schema to guarantee structural correctness of the AI response
response_schema = {
    "type": "OBJECT",
    "properties": {
        "is_correct": {"type": "BOOLEAN"},
        "detected_complexity": {
            "type": "OBJECT",
            "properties": {
                "time": {"type": "STRING"},
                "space": {"type": "STRING"}
            },
            "required": ["time", "space"]
        },
        "bugs": {
            "type": "ARRAY",
            "items": {"type": "STRING"}
        },
        "key_suggestion": {"type": "STRING"}
    },
    "required": ["is_correct", "detected_complexity", "bugs", "key_suggestion"]
}

```

### System & Prompt Prompts

```
system_instruction = """
You are an expert technical interviewer evaluating a candidate's LeetCode code written from memory.
Your primary objective is to review code correctness, algorithmic efficiency, and potential edge-case failures.
Be highly forgiving of minor visual/syntax typos (e.g., off-by-one indentation, minor spelling mistakes in variables, or missing colons)
which would be caught in 1 second by a standard IDE. Focus on raw algorithmic correctness.
"""

user_prompt_template = """
Problem Name: {problem_name}
Target Pattern: {pattern_name}
Expected Complexity: {target_complexities}

Candidate's Code Submission:
{candidate_code}

Evaluate the code logic and return the structured JSON output.
"""

```

## 6. System Execution Workflows

### Daily Queue Retrieval Workflow

The system minimizes burnout by limiting the daily workload to problems scheduled for _on or before_ the current timestamp.

```
[User Opens App] 
       |
       v
[Query Database] 
  1. Retrieve Active Streak -> SELECT * FROM user_streaks LIMIT 1;
  2. Lazy Check: If CURRENT_DATE > last_active_date + 1, reset current_streak to 0 in DB.
  3. Query Daily Cards -> SELECT * FROM user_reviews 
                           JOIN problems ON user_reviews.problem_id = problems.id
                           WHERE next_review <= NOW()
                           ORDER BY next_review ASC;
       |
       v
[Render Streamlit Mobile-Responsive Cards & Streak Banner]

```

### Google Drive Ingest Sync (Triggered via UI Button or Cron)

The user can tap "Sync Folder" in the app interface, executing the background sync worker:

```
                      [User Taps "Sync Google Folder"]
                                     |
                                     v
                        [Read Files from Folder]
             Call Google Drive API: List files inside target FolderID
                                     |
                                     v
                       [Filter New Google Doc IDs]
         Identify Doc IDs not present in problems.google_doc_id DB column
                                     |
                                     v
                  +------------------+------------------+
                  |                                     |
         [No New Docs Found]                    [New Docs Found]
                  |                                     |
                  v                                     v
          Complete Sync Task                    For each new doc:
                                                - Call Google Docs API
                                                - Parse name, patterns, code
                                                - INSERT INTO problems
                                                - INSERT INTO user_reviews 
                                                  (Default Box = 1, next_review = now())
                                                        |
                                                        v
                                                Refresh Review Queue

```

## 7. Portability, Accessibility & Performance

### 1. Fully Responsive Fluid Layouts

-   **Framework Adaptation:** All Streamlit elements are configured using native block components (`st.columns`, `st.container`) that transition seamlessly from a dual-pane desktop view to a single-stack layout on iOS/Android devices.
    
-   **Typographic Scaling:** Markdown blocks use standard relative heading levels (`###` and body text) to remain highly readable on varying screen resolutions.
    
-   **Streak Visual Integration:** The app features a high-visibility, fluid CSS indicator displaying the user's current streak count (e.g., "🔥 14 Days Active") pinned to the top of both mobile and desktop screens.
    
-   **Touch Target Optimization:** Touch elements such as "Submit", "Forgot", and "Easy" use high-contrast primary colors with custom internal padding so they can be clicked reliably with a single thumb tap.
    

### 2. Manual Offline Fallback Mode (No Connection Option)

Traveling frequently results in spotty network connections. To prevent missed study days and protect your active streak:

-   **The "Self-Grade" Toggle:** If connection to the Gemini API is lost or latency is too high, users can toggle a "Manual Grade" override.
    
-   **Mechanism:** The app displays the user's stored Google Doc code and asks the user to manually rate themselves ("Forgot", "Struggled", "Smashed It").
    
-   **Local Synchronization:** The review state transition calculates intervals locally, registers the streak daily increment, and pushes the DB update asynchronously, guaranteeing zero study gaps.
    

### 3. Data Protection & Sync Security

-   **Encrypted Cloud Connect:** All DB calls are encrypted via TLS/SSL.
    
-   **Personal Space Partitioning:** The Supabase endpoint utilizes Row-Level Security (RLS) to ensure that only you can view, create, or alter your saved algorithmic problem queues and personal study metrics.