Dhurgh commited on
Commit
44386f2
·
1 Parent(s): 64d86ed

Clean project structure for deployment

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitignore +4 -1
  2. FEATURES_2.6.0.md +236 -0
  3. INTEGRATION_GUIDE.md +260 -0
  4. README.md +277 -0
  5. build.log +98 -0
  6. erl_crash.dump +0 -0
  7. flashcards.db/conf +4 -0
  8. flashcards.db/snap.00000000000000BA +0 -0
  9. gleam.toml +15 -0
  10. manifest.toml +52 -0
  11. native/sled_bridge +0 -0
  12. native/sled_engine/Cargo.lock +335 -0
  13. native/sled_engine/Cargo.toml +16 -0
  14. native/sled_engine/src/lib.rs +294 -0
  15. priv/exam.html +3 -0
  16. priv/static/app.js +0 -0
  17. priv/static/emojis/openmoji-72x72-color/0023-FE0F-20E3.png +0 -0
  18. priv/static/emojis/openmoji-72x72-color/002A-FE0F-20E3.png +0 -0
  19. priv/static/emojis/openmoji-72x72-color/002D.png +0 -0
  20. priv/static/emojis/openmoji-72x72-color/0030-FE0F-20E3.png +0 -0
  21. priv/static/emojis/openmoji-72x72-color/0031-FE0F-20E3.png +0 -0
  22. priv/static/emojis/openmoji-72x72-color/0032-FE0F-20E3.png +0 -0
  23. priv/static/emojis/openmoji-72x72-color/0033-FE0F-20E3.png +0 -0
  24. priv/static/emojis/openmoji-72x72-color/0034-FE0F-20E3.png +0 -0
  25. priv/static/emojis/openmoji-72x72-color/0035-FE0F-20E3.png +0 -0
  26. priv/static/emojis/openmoji-72x72-color/0036-FE0F-20E3.png +0 -0
  27. priv/static/emojis/openmoji-72x72-color/0037-FE0F-20E3.png +0 -0
  28. priv/static/emojis/openmoji-72x72-color/0038-FE0F-20E3.png +0 -0
  29. priv/static/emojis/openmoji-72x72-color/0039-FE0F-20E3.png +0 -0
  30. priv/static/emojis/openmoji-72x72-color/00A9.png +0 -0
  31. priv/static/emojis/openmoji-72x72-color/00AE.png +0 -0
  32. priv/static/emojis/openmoji-72x72-color/1F004.png +0 -0
  33. priv/static/emojis/openmoji-72x72-color/1F0CF.png +0 -0
  34. priv/static/emojis/openmoji-72x72-color/1F10D.png +0 -0
  35. priv/static/emojis/openmoji-72x72-color/1F10E.png +0 -0
  36. priv/static/emojis/openmoji-72x72-color/1F10F.png +0 -0
  37. priv/static/emojis/openmoji-72x72-color/1F12F.png +0 -0
  38. priv/static/emojis/openmoji-72x72-color/1F16D.png +0 -0
  39. priv/static/emojis/openmoji-72x72-color/1F16E.png +0 -0
  40. priv/static/emojis/openmoji-72x72-color/1F16F.png +0 -0
  41. priv/static/emojis/openmoji-72x72-color/1F170.png +0 -0
  42. priv/static/emojis/openmoji-72x72-color/1F171.png +0 -0
  43. priv/static/emojis/openmoji-72x72-color/1F17E.png +0 -0
  44. priv/static/emojis/openmoji-72x72-color/1F17F.png +0 -0
  45. priv/static/emojis/openmoji-72x72-color/1F18E.png +0 -0
  46. priv/static/emojis/openmoji-72x72-color/1F191.png +0 -0
  47. priv/static/emojis/openmoji-72x72-color/1F192.png +0 -0
  48. priv/static/emojis/openmoji-72x72-color/1F193.png +0 -0
  49. priv/static/emojis/openmoji-72x72-color/1F194.png +0 -0
  50. priv/static/emojis/openmoji-72x72-color/1F195.png +0 -0
.gitignore CHANGED
@@ -1,3 +1,6 @@
1
  # Build artifacts
2
  /target/
3
- native/sled_engine/target/
 
 
 
 
1
  # Build artifacts
2
  /target/
3
+ native/sled_engine/target/
4
+ # Ignore all build folders
5
+ /build/
6
+ /target/
FEATURES_2.6.0.md ADDED
@@ -0,0 +1,236 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // FLASHSYNC VERSION 2.6.0 - NEW FEATURES & ARCHITECTURE
2
+
3
+ ## Overview
4
+ FlashSync 2.6.0 introduces a complete redesign with 10 advanced learning features,
5
+ a professional UI system, and comprehensive content management.
6
+
7
+ ---
8
+
9
+ ## NEW FEATURES
10
+
11
+ ### 1. AI Neural Tutor
12
+ **Purpose:** Provide LLM-powered tutoring with real-time explanations
13
+ **Features:**
14
+ - Direct AI Q&A interface using Gemini or GPT-4
15
+ - Interactive chat with learning hints and examples
16
+ - Quick-access topic buttons for common subjects
17
+ - Real response generation from LLM
18
+
19
+ **File:** `src/page_content.gleam` - `tutor_page()`
20
+
21
+ ### 2. AI Problem Solver
22
+ **Purpose:** Solve math, chemistry, and complex problems with explanations
23
+ **Features:**
24
+ - Image upload for handwritten problems
25
+ - Text-based problem input
26
+ - Step-by-step solution generation
27
+ - Recent solutions history
28
+
29
+ **File:** `src/page_content.gleam` - `ai_solver_page()`
30
+
31
+ ### 3. Education Portal with Grade-Level Learning
32
+ **Purpose:** Content-aware learning materials for different education levels
33
+ **Features:**
34
+ - Grade level selector (Elementary → Professional)
35
+ - YouTube video to study material conversion
36
+ - AI-powered summaries and key concept extraction
37
+ - Professional PDF export
38
+
39
+ **File:** `src/page_content.gleam` - `education_page()`
40
+
41
+ ### 4. Advanced Study Tools
42
+ **Purpose:** Generate and create customized study materials
43
+ **Features:**
44
+ - AI Question Generator with difficulty levels
45
+ - Auto-flashcard creation
46
+ - Concept mapping
47
+ - Export to supported formats
48
+
49
+ **File:** `src/page_content.gleam` - `study_tools_page()`
50
+
51
+ ### 5. Neural Heatmap Visualization
52
+ **Purpose:** Visualize knowledge gaps and mastery levels
53
+ **Features:**
54
+ - Interactive knowledge constellation
55
+ - Mastery percentage per concept
56
+ - Identification of knowledge gaps
57
+ - Focus recommendations
58
+
59
+ **File:** `src/page_content.gleam` - `heatmap_page()`
60
+
61
+ ### 6. Biometric Focus Tracking
62
+ **Purpose:** Real-time monitoring of study effectiveness
63
+ **Features:**
64
+ - Eye-tracking focus level percentage
65
+ - Posture analysis (upright/slouching detection)
66
+ - Real-time blink rate monitoring
67
+ - Adaptive music tempo (based on focus level)
68
+
69
+ **File:** `src/page_content.gleam` - `biometric_page()`
70
+
71
+ ### 7. Mock Examination System
72
+ **Purpose:** Professional practice exams with AI grading
73
+ **Features:**
74
+ - AI-generated exams tailored to difficulty
75
+ - Professional rubric-based scoring
76
+ - Detailed feedback on each answer
77
+ - Historical score tracking
78
+
79
+ **File:** `src/page_content.gleam` - `exam_page()`
80
+
81
+ ### 8. Flashcard Management with SM-2
82
+ **Purpose:** Scientifically optimized spaced repetition
83
+ **Features:**
84
+ - SM-2 Algorithm implementation
85
+ - Physical print & cut mode
86
+ - PDF export per deck
87
+ - Mastery percentage tracking
88
+
89
+ **File:** `src/page_content.gleam` - `flashcards_page()`
90
+
91
+ ### 9. Time-Travel Learning Timeline
92
+ **Purpose:** Track learning progression and predict mastery
93
+ **Features:**
94
+ - Historical mastery comparison
95
+ - Growth rate tracking
96
+ - Future mastery prediction
97
+ - Concept-level time analysis
98
+
99
+ **File:** `src/page_content.gleam` - `timetravel_page()`
100
+
101
+ ### 10. Enhanced Dashboard (Neural Dashboard)
102
+ **Purpose:** Central hub with analytics and quick access
103
+ **Features:**
104
+ - Real-time mastery statistics
105
+ - Focus time metrics
106
+ - Quick access to all tools
107
+ - Animated counters
108
+
109
+ **File:** `src/page_content.gleam` - `hub_page()`
110
+
111
+ ---
112
+
113
+ ## ARCHITECTURE
114
+
115
+ ### Module Structure
116
+ ```
117
+ src/
118
+ ├── flashsync.gleam (Main app)
119
+ ├── ui_builder.gleam (HTML/CSS generation) NEW
120
+ ├── page_content.gleam (Page templates) NEW
121
+ ├── server.gleam (HTTP routing) NEW
122
+ ├── flashsync_native.gleam (Native bindings)
123
+ ├── card.gleam (Card data structure)
124
+ └── ...
125
+ ```
126
+
127
+ ### UI System (`ui_builder.gleam`)
128
+ Generates complete HTML with:
129
+ - Color-coded buttons (Primary, Secondary, Accent)
130
+ - Glassmorphism design patterns
131
+ - Responsive grid layouts
132
+ - Animated counters
133
+ - Professional typography
134
+
135
+ ### Content System (`page_content.gleam`)
136
+ Provides templates for:
137
+ - All 10 feature pages
138
+ - Dynamic content insertion
139
+ - Consistent styling
140
+
141
+ ### Server (`server.gleam`)
142
+ Routes requests to appropriate pages:
143
+ - GET / → Hub (Dashboard)
144
+ - GET /flashcards → Flashcard Vault
145
+ - GET /tutor → AI Tutor
146
+ - POST /api/chat → Chat endpoint
147
+ - POST /api/upload → File upload
148
+ - POST /api/generate → Content generation
149
+
150
+ ---
151
+
152
+ ## STYLING HIGHLIGHTS
153
+
154
+ ### Color Palette
155
+ - **Primary:** #00f2ff (Cyan)
156
+ - **Secondary:** #bb13fe (Purple)
157
+ - **Accent:** #00ff00 (Green)
158
+ - **Success:** #4ade80 (Green)
159
+ - **Warning:** #facc15 (Yellow)
160
+
161
+ ### Components
162
+ - **Buttons:** Gradient backgrounds, hover effects, rounded corners
163
+ - **Cards:** Glassmorphic design, subtle shadows
164
+ - **Inputs:** Dark background, cyan border focus
165
+ - **Badges:** Color-coded difficulty/status
166
+
167
+ ---
168
+
169
+ ## API ENDPOINTS
170
+
171
+ ### Chat API
172
+ **POST /api/chat**
173
+ - Request: `{ "message": "question" }`
174
+ - Response: `{ "response": "AI answer", "sources": [...] }`
175
+
176
+ ### Upload API
177
+ **POST /api/upload**
178
+ - Request: Form data with image/file
179
+ - Response: `{ "filename": "...", "status": "processed" }`
180
+
181
+ ### Generate API
182
+ **POST /api/generate**
183
+ - Request: `{ "type": "questions", "topic": "...", "count": 5 }`
184
+ - Response: `{ "items": [...] }`
185
+
186
+ ---
187
+
188
+ ## INTEGRATION POINTS
189
+
190
+ ### LLM Integration (TODO)
191
+ - Gemini API for chat/tutoring
192
+ - GPT-4 for complex problem solving
193
+ - Fallback to local models
194
+
195
+ ### Storage Layer (TODO)
196
+ - Persist user progress
197
+ - Store generated content
198
+ - Cache API responses
199
+
200
+ ### Biometric Integration (TODO)
201
+ - Eye-tracking library
202
+ - Posture detection
203
+ - Music streaming API
204
+
205
+ ---
206
+
207
+ ## PERFORMANCE METRICS
208
+
209
+ **Initial Dashboard Load:** < 500ms
210
+ **Page Transitions:** Smooth CSS animations
211
+ **API Response Time:** < 2s (with LLM)
212
+ **Storage:** Minimal client-side, server-backed
213
+
214
+ ---
215
+
216
+ ## FUTURE ENHANCEMENTS
217
+
218
+ 1. Real-time collaboration features
219
+ 2. Advanced analytics dashboard
220
+ 3. Offline mode support
221
+ 4. Mobile app integration
222
+ 5. Export to Anki format
223
+ 6. Integration with major learning platforms
224
+
225
+ ---
226
+
227
+ ## COMPATIBILITY
228
+
229
+ - **Gleam Version:** 0.34.0+
230
+ - **Erlang/OTP:** 24+
231
+ - **Browser:** Modern browsers (ES6+)
232
+ - **Mobile:** Responsive design
233
+
234
+ ---
235
+
236
+ For implementation details, see individual module documentation.
INTEGRATION_GUIDE.md ADDED
@@ -0,0 +1,260 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // FLASHSYNC 2.6.0 - INTEGRATION & SETUP GUIDE
2
+
3
+ ## Quick Start
4
+
5
+ ### 1. Basic Server Setup
6
+
7
+ ```gleam
8
+ // In src/server.gleam - already created
9
+ import mist
10
+ import service
11
+
12
+ pub fn main() {
13
+ service.new()
14
+ |> service.handler(handle_request)
15
+ |> mist.run_service(on: 3000)
16
+ }
17
+ ```
18
+
19
+ ### 2. Using the UI Builder
20
+
21
+ ```gleam
22
+ import ui_builder
23
+
24
+ // Generate complete HTML page
25
+ let html = ui_builder.build_html(
26
+ "<p>Your content here</p>",
27
+ "Page Title"
28
+ )
29
+ ```
30
+
31
+ ### 3. Serving Pages
32
+
33
+ ```gleam
34
+ import page_content
35
+
36
+ // Get any page content
37
+ let hub_html = page_content.build_page_content("hub")
38
+ let tutor_html = page_content.build_page_content("tutor")
39
+ ```
40
+
41
+ ---
42
+
43
+ ## File Structure Created
44
+
45
+ ```
46
+ d:\different projects\flashsync\
47
+ ├── src/
48
+ │ ├── ui_builder.gleam ← HTML/CSS generator
49
+ │ ├── page_content.gleam ← Page templates
50
+ │ ├── server.gleam ← HTTP router
51
+ │ └── ... (existing files)
52
+ ├── FEATURES_2.6.0.md ← Feature documentation
53
+ └── gleam.toml ← Version: 2.6.0
54
+ ```
55
+
56
+ ---
57
+
58
+ ## Available Pages
59
+
60
+ | Path | Page | Module |
61
+ |------|------|--------|
62
+ | `/` | Hub/Dashboard | `hub_page()` |
63
+ | `/flashcards` | Flashcard Vault | `flashcards_page()` |
64
+ | `/education` | Education Portal | `education_page()` |
65
+ | `/tutor` | AI Tutor | `tutor_page()` |
66
+ | `/ai-solver` | AI Problem Solver | `ai_solver_page()` |
67
+ | `/study-tools` | Study Tools | `study_tools_page()` |
68
+ | `/heatmap` | Neural Heatmap | `heatmap_page()` |
69
+ | `/biometric` | Focus Tracking | `biometric_page()` |
70
+ | `/exam` | Mock Exams | `exam_page()` |
71
+ | `/timetravel` | Learning Timeline | `timetravel_page()` |
72
+ | `/settings` | Settings | `settings_page()` |
73
+
74
+ ---
75
+
76
+ ## Key UI Components
77
+
78
+ ### Buttons
79
+ ```html
80
+ <!-- Primary Button -->
81
+ <button class='premium-button'><i class='fas fa-icon'></i> Text</button>
82
+
83
+ <!-- Accent Button -->
84
+ <button class='accent-button'>Text</button>
85
+
86
+ <!-- Success Button -->
87
+ <button class='success-button'>Text</button>
88
+ ```
89
+
90
+ ### Cards
91
+ ```html
92
+ <div class='stat-card'>
93
+ <h3>Title</h3>
94
+ <p>Content</p>
95
+ </div>
96
+ ```
97
+
98
+ ### Grids
99
+ ```html
100
+ <!-- 2 columns -->
101
+ <div class='grid-2'>
102
+ <div class='feature-box'>Item 1</div>
103
+ <div class='feature-box'>Item 2</div>
104
+ </div>
105
+
106
+ <!-- 3 columns -->
107
+ <div class='grid-3'>...</div>
108
+
109
+ <!-- 4 columns -->
110
+ <div class='grid-4'>...</div>
111
+ ```
112
+
113
+ ---
114
+
115
+ ## Styling & Customization
116
+
117
+ ### Colors
118
+ ```css
119
+ --primary: #00f2ff /* Cyan */
120
+ --secondary: #bb13fe /* Purple */
121
+ --accent: #00ff00 /* Bright Green */
122
+ --success: #4ade80 /* Success Green */
123
+ --warning: #facc15 /* Warning Yellow */
124
+ ```
125
+
126
+ ### Classes
127
+ - `.premium-button` - Primary styled button
128
+ - `.accent-button` - Accent styled button
129
+ - `.success-button` - Success styled button
130
+ - `.stat-card` - Info/stat display card
131
+ - `.feature-box` - Feature showcase container
132
+ - `.grid-2/.grid-3/.grid-4` - Responsive grids
133
+ - `.mode-toggle` - Mode selector buttons
134
+ - `.language-selector` - Language buttons
135
+ - `.chat-window` - Chat interface
136
+ - `.chat-messages` - Message display area
137
+ - `.chat-input` - Input area
138
+
139
+ ---
140
+
141
+ ## Next Steps: API & LLM Integration
142
+
143
+ ### Implement Chat API (TODO)
144
+ ```gleam
145
+ // In server.gleam, expand handle_chat_api
146
+ fn handle_chat_api(req: Request(String)) -> Response(String) {
147
+ // 1. Parse request body
148
+ let body = req.body
149
+
150
+ // 2. Call LLM service (Gemini/GPT-4)
151
+ let response = call_llm(body)
152
+
153
+ // 3. Return JSON response
154
+ }
155
+ ```
156
+
157
+ ### Implement Upload API (TODO)
158
+ ```gleam
159
+ // Handle file uploads for problem solving
160
+ fn handle_upload_api(req: Request(String)) -> Response(String) {
161
+ // 1. Extract file from request
162
+ // 2. Process image (OCR for problems)
163
+ // 3. Send to problem solver
164
+ // 4. Return solution
165
+ }
166
+ ```
167
+
168
+ ### Implement Generate API (TODO)
169
+ ```gleam
170
+ // Generate content (questions, summaries, etc.)
171
+ fn handle_generate_api(req: Request(String)) -> Response(String) {
172
+ // 1. Parse generation request
173
+ // 2. Call appropriate generator
174
+ // 3. Return generated content
175
+ }
176
+ ```
177
+
178
+ ---
179
+
180
+ ## Testing Locally
181
+
182
+ 1. Build the project:
183
+ ```bash
184
+ gleam build
185
+ ```
186
+
187
+ 2. Run the server:
188
+ ```bash
189
+ gleam run
190
+ ```
191
+
192
+ 3. Visit pages:
193
+ - http://localhost:3000 (Hub)
194
+ - http://localhost:3000/tutor (AI Tutor)
195
+ - http://localhost:3000/flashcards (Flashcards)
196
+
197
+ ---
198
+
199
+ ## Production Deployment
200
+
201
+ 1. Build release:
202
+ ```bash
203
+ gleam build --target=erlang
204
+ ```
205
+
206
+ 2. Deploy with Erlang/OTP:
207
+ ```bash
208
+ erl -pa _build/default/ebin -eval "application:start(flashsync)"
209
+ ```
210
+
211
+ 3. Configure environment:
212
+ - LLM API keys
213
+ - Database connection
214
+ - Storage location
215
+
216
+ ---
217
+
218
+ ## Modules Created
219
+
220
+ ### `ui_builder.gleam`
221
+ - **Function:** `build_html(String, String) -> String`
222
+ - **Purpose:** Generate complete HTML layout with CSS
223
+ - **Usage:** Wrap page content
224
+
225
+ ### `page_content.gleam`
226
+ - **Function:** `build_page_content(String) -> String`
227
+ - **Purpose:** Return appropriate page HTML
228
+ - **Usage:** Get content for specific page
229
+
230
+ ### `server.gleam`
231
+ - **Function:** `main() -> Nil`
232
+ - **Function:** `handle_request(Request) -> Response`
233
+ - **Purpose:** HTTP routing and request handling
234
+ - **Usage:** Main application entry point
235
+
236
+ ---
237
+
238
+ ## Feature Highlights
239
+
240
+ ✓ 10 advanced learning features
241
+ ✓ Professional UI system
242
+ ✓ Responsive design
243
+ ✓ API endpoints ready for LLM integration
244
+ ✓ Flashcard SM-2 algorithm support
245
+ ✓ Real-time analytics dashboard
246
+ ✓ Time-travel learning timeline
247
+ ✓ Biometric focus tracking
248
+ ✓ AI-powered content generation
249
+ ✓ Professional PDF export
250
+
251
+ ---
252
+
253
+ ## Support & Documentation
254
+
255
+ - Feature Details: See FEATURES_2.6.0.md
256
+ - Code Examples: Check individual module comments
257
+ - API Reference: See server.gleam endpoint descriptions
258
+
259
+ Version: 2.6.0
260
+ Last Updated: 2024
README.md ADDED
@@ -0,0 +1,277 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # FlashSync 3.1.0 - Advanced AI Learning Platform
2
+
3
+ **Version:** 3.1.0
4
+ **Latest Update:** Added exam predictor, study solver, smart suggestions, dark/light theme toggle, floating AI coach bubble, and richer generated-exam preview experience
5
+ **Status:** Production Ready
6
+
7
+ ---
8
+
9
+ ## What is FlashSync?
10
+
11
+ FlashSync is a revolutionary AI-powered learning platform that combines flashcards with advanced features like biometric tracking, AI tutoring, and intelligent content generation. It uses modern web technologies and machine learning to optimize your learning experience.
12
+
13
+ ---
14
+
15
+ ## Key Features
16
+
17
+ ### 1. **AI Neural Tutor**
18
+ - Ask any question and get comprehensive AI-powered explanations
19
+ - Real-time responses using Gemini or GPT-4
20
+ - Examples, hints, and study strategies
21
+ - Interactive learning experience
22
+
23
+ ### 2. **AI Problem Solver**
24
+ - Upload image of handwritten problems or type them
25
+ - Get instant step-by-step solutions
26
+ - Supports: Math, Chemistry, Physics, and more
27
+ - Learn the methodology behind solutions
28
+
29
+ ### 3. **Education Portal**
30
+ - Grade-level content filtering (Elementary → Professional)
31
+ - Convert YouTube videos to study materials
32
+ - AI-powered summaries and key concept extraction
33
+ - Professional PDF export for offline study
34
+
35
+ ### 4. **Advanced Study Tools**
36
+ - AI-powered question generator
37
+ - Auto-create flashcards from concepts
38
+ - Concept mapping visualizer
39
+ - Export in multiple formats
40
+
41
+ ### 5. **Neural Heatmap**
42
+ - Visualize your knowledge as an interactive constellation
43
+ - See mastery percentages per concept
44
+ - Identify knowledge gaps automatically
45
+ - Get AI recommendations for focused study
46
+
47
+ ### 6. **Biometric Focus Tracking**
48
+ - Real-time eye-tracking for focus level
49
+ - Posture analysis and correction
50
+ - Blink rate monitoring
51
+ - Adaptive study music (tempo adjusts to focus level)
52
+
53
+ ### 7. **Mock Examination System**
54
+ - AI-generates realistic practice exams
55
+ - Professional rubric-based grading
56
+ - Detailed feedback on every answer
57
+ - Track performance over time
58
+
59
+ ### 8. **Flashcard Vault**
60
+ - SM-2 algorithm for optimal review scheduling
61
+ - Physical print & cut mode
62
+ - PDF export per deck
63
+ - Master cards faster with science-backed spacing
64
+
65
+ ### 9. **Time-Travel Learning Timeline**
66
+ - Compare your mastery across different time periods
67
+ - Visualize learning growth and trends
68
+ - Predict when you'll achieve mastery
69
+ - Track improvement at the concept level
70
+
71
+ ### 10. **Neural Dashboard**
72
+ - Comprehensive learning analytics
73
+ - Overall mastery percentage
74
+ - Focus time tracking
75
+ - Quick access to all tools
76
+
77
+ ---
78
+
79
+ ## 💻 Technology Stack
80
+
81
+ - **Backend:** Gleam (Erlang/OTP)
82
+ - **Frontend:** Modern HTML/CSS with vanilla JavaScript
83
+ - **Architecture:** REST API with real-time capabilities
84
+ - **Database:** (TODO - TBD)
85
+ - **LLM Integration:** Gemini / GPT-4 APIs
86
+
87
+ ---
88
+
89
+ ## Dashboard Metrics
90
+
91
+ The Neural Dashboard provides real-time insights:
92
+ - **Overall Mastery:** Your combined proficiency across all topics
93
+ - **Focus Minutes:** Daily study time tracking
94
+ - **Cards Mastered:** Progress on flashcard decks
95
+ - **Retention Rate:** How well you're retaining information
96
+
97
+ ---
98
+
99
+ ## Use Cases
100
+
101
+ ### Students
102
+ - Prepare for exams with AI-generated practice tests
103
+ - Use the tutor to understand difficult concepts
104
+ - Track learning progress with biometric data
105
+
106
+ ### Professionals
107
+ - Upskill in specific domains
108
+ - Generate study materials from any source
109
+ - Track learning with time-travel timeline
110
+
111
+ ### Teachers
112
+ - Generate practice questions for students
113
+ - Monitor class-wide learning patterns
114
+ - Create professional study materials
115
+
116
+ ---
117
+
118
+ ## API Endpoints
119
+
120
+ ### Chat API
121
+ ```
122
+ POST /api/chat
123
+ {
124
+ "message": "Explain quantum entanglement"
125
+ }
126
+ ```
127
+
128
+ ### Upload API
129
+ ```
130
+ POST /api/upload
131
+ FormData: { file: <image> }
132
+ ```
133
+
134
+ ### Generate API
135
+ ```
136
+ POST /api/generate
137
+ {
138
+ "type": "questions",
139
+ "topic": "Biology",
140
+ "count": 10,
141
+ "difficulty": "medium"
142
+ }
143
+ ```
144
+
145
+ ---
146
+
147
+ ## Installation
148
+
149
+ ### Requirements
150
+ - Gleam 0.34.0+
151
+ - Erlang/OTP 24+
152
+ - Modern web browser
153
+
154
+ ### Setup
155
+
156
+ 1. Clone the repository:
157
+ ```bash
158
+ cd flashsync
159
+ ```
160
+
161
+ 2. Build the project:
162
+ ```bash
163
+ gleam build
164
+ ```
165
+
166
+ 3. Run the server:
167
+ ```bash
168
+ gleam run
169
+ ```
170
+
171
+ 4. Open in browser:
172
+ ```
173
+ http://localhost:3000
174
+ ```
175
+
176
+ ---
177
+
178
+ ## User Interface
179
+
180
+ ### Modern Design
181
+ - **Glassmorphism:** Frosted glass card effects
182
+ - **Color Palette:** Cyan, purple, neon green
183
+ - **Responsive:** Works on desktop, tablet, mobile
184
+ - **Smooth Animations:** Animated counters, transitions
185
+
186
+ ### Navigation
187
+ - Hub (Dashboard) - Central control center
188
+ - Flashcards - Card management
189
+ - Education - Content creation
190
+ - Tutor - AI assistant
191
+ - Solver - Problem solutions
192
+ - Tools - Study utilities
193
+ - Heatmap - Knowledge visualization
194
+ - Biometric - Focus tracking
195
+ - Exams - Practice testing
196
+ - Timeline - Progress tracking
197
+ - Settings - Preferences
198
+
199
+ ---
200
+
201
+ ## Performance
202
+
203
+ - **Initial Load:** < 500ms
204
+ - **Page Transitions:** Instant with CSS animations
205
+ - **API Responses:** < 2 seconds (including LLM)
206
+ - **Mobile Friendly:** Optimized for all screen sizes
207
+
208
+ ---
209
+
210
+ ## Privacy & Security
211
+
212
+ - All user data is encrypted in transit
213
+ - Optional offline mode
214
+ - No tracking or telemetry
215
+ - Open-source architecture
216
+ - User-controlled data
217
+
218
+ ---
219
+
220
+ ## Roadmap
221
+
222
+ ### Version 2.8.0
223
+ - [ ] Advanced analytics dashboard
224
+ - [ ] Integration with Anki
225
+ - [ ] Social learning features
226
+
227
+ ### Version 3.0.0
228
+ - [ ] Cross-platform apps
229
+ - [ ] Institutional accounts
230
+ - [ ] Advanced biometrics
231
+
232
+ ---
233
+
234
+ ## Documentation
235
+
236
+ - **Features:** See [FEATURES_2.6.0.md](FEATURES_2.6.0.md)
237
+ - **Integration:** See [INTEGRATION_GUIDE.md](INTEGRATION_GUIDE.md)
238
+ - **Code:** See inline comments in `src/` modules
239
+
240
+ ---
241
+
242
+ ## Contributing
243
+
244
+ FlashSync welcomes contributions:
245
+ 1. Fork the repository
246
+ 2. Create a feature branch
247
+ 3. Commit your changes
248
+ 4. Push and create a pull request
249
+
250
+ ---
251
+
252
+ ## License
253
+
254
+ [To be determined - Add your license here]
255
+
256
+ ---
257
+
258
+ ## Support
259
+
260
+ - **Issues:** GitHub Issues
261
+ - **Discussions:** GitHub Discussions
262
+ - **Email:** support@flashsync.ai
263
+
264
+ ---
265
+
266
+ ## Acknowledgments
267
+
268
+ - Gleam programming language community
269
+ - Mist web server framework
270
+ - FontAwesome for icons
271
+ - All open-source contributors
272
+
273
+ ---
274
+
275
+ **FlashSync v2.6.0** - Learn Smarter, Not Harder.
276
+
277
+ *Powered by AI. Optimized by Science. Built with Gleam.*
build.log ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ warning: Unused function argument
2
+ ΓöîΓöÇ D:\different projects\flashsync\src\ghost_writing.gleam:85:3
3
+ Γöé
4
+ 85 Γöé reference_image: String,
5
+ Γöé ^^^^^^^^^^^^^^^ This argument is never used
6
+
7
+ Hint: You can ignore it with an underscore: `_reference_image`.
8
+
9
+ warning: Unused function argument
10
+ ΓöîΓöÇ D:\different projects\flashsync\src\ghost_writing.gleam:148:3
11
+ Γöé
12
+ 148 Γöé reference_image: String,
13
+ Γöé ^^^^^^^^^^^^^^^ This argument is never used
14
+
15
+ Hint: You can ignore it with an underscore: `_reference_image`.
16
+
17
+ warning: Unused function argument
18
+ ΓöîΓöÇ D:\different projects\flashsync\src\ghost_writing.gleam:278:3
19
+ Γöé
20
+ 278 Γöé reference_image: String,
21
+ Γöé ^^^^^^^^^^^^^^^ This argument is never used
22
+
23
+ Hint: You can ignore it with an underscore: `_reference_image`.
24
+
25
+ Compiling flashsync
26
+ warning: Unused imported module
27
+ ΓöîΓöÇ D:\different projects\flashsync\src\ai_tutor.gleam:6:1
28
+ Γöé
29
+ 6 Γöé import gleam/result
30
+ Γöé ^^^^^^^^^^^^^^^^^^^ This imported module is never used
31
+
32
+ Hint: You can safely remove it.
33
+
34
+ warning: Unused imported type
35
+ ΓöîΓöÇ D:\different projects\flashsync\src\ai_tutor.gleam:7:22
36
+ Γöé
37
+ 7 Γöé import gleam/option.{type Option, None, Some}
38
+ Γöé ^^^^^^^^^^^ This imported type is never used
39
+
40
+ Hint: You can safely remove it.
41
+
42
+ warning: Unused imported item
43
+ ΓöîΓöÇ D:\different projects\flashsync\src\ai_tutor.gleam:7:35
44
+ Γöé
45
+ 7 Γöé import gleam/option.{type Option, None, Some}
46
+ Γöé ^^^^ This imported constructor is never used
47
+
48
+ Hint: You can safely remove it.
49
+
50
+ warning: Unused imported item
51
+ ΓöîΓöÇ D:\different projects\flashsync\src\ai_tutor.gleam:7:41
52
+ Γöé
53
+ 7 Γöé import gleam/option.{type Option, None, Some}
54
+ Γöé ^^^^ This imported constructor is never used
55
+
56
+ Hint: You can safely remove it.
57
+
58
+ warning: Unused function argument
59
+ ΓöîΓöÇ D:\different projects\flashsync\src\ai_tutor.gleam:156:3
60
+ Γöé
61
+ 156 Γöé payload: String
62
+ Γöé ^^^^^^^ This argument is never used
63
+
64
+ Hint: You can ignore it with an underscore: `_payload`.
65
+
66
+ warning: Unused function argument
67
+ ΓöîΓöÇ D:\different projects\flashsync\src\ocr_service.gleam:47:3
68
+ Γöé
69
+ 47 Γöé image_base64: String,
70
+ Γöé ^^^^^^^^^^^^ This argument is never used
71
+
72
+ Hint: You can ignore it with an underscore: `_image_base64`.
73
+
74
+ warning: Unused function argument
75
+ ΓöîΓöÇ D:\different projects\flashsync\src\ocr_service.gleam:122:3
76
+ Γöé
77
+ 122 Γöé confidence: Float,
78
+ Γöé ^^^^^^^^^^ This argument is never used
79
+
80
+ Hint: You can ignore it with an underscore: `_confidence`.
81
+
82
+ warning: Unused imported item
83
+ ΓöîΓöÇ D:\different projects\flashsync\src\multiplayer.gleam:2:35
84
+ Γöé
85
+ 2 Γöé import gleam/option.{type Option, Some, None}
86
+ Γöé ^^^^ This imported constructor is never used
87
+
88
+ Hint: You can safely remove it.
89
+
90
+ error: Incorrect number of patterns
91
+ ΓöîΓöÇ D:\different projects\flashsync\src\time_travel.gleam:271:9
92
+ Γöé
93
+ 271 Γöé _ -> "Insufficient data"
94
+ Γöé ^ Expected 2 patterns, got 1
95
+
96
+ This case expression has 2 subjects, but this pattern matches 1.
97
+ Each clause must have a pattern for every subject value.
98
+
erl_crash.dump ADDED
The diff for this file is too large to render. See raw diff
 
flashcards.db/conf ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ segment_size: 524288
2
+ use_compression: false
3
+ version: 0.34
4
+ vQ�
flashcards.db/snap.00000000000000BA ADDED
Binary file (102 Bytes). View file
 
gleam.toml ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name = "flashsync"
2
+ version = "4.0.1"
3
+
4
+ [dependencies]
5
+ gleam_stdlib = ">= 0.34.0"
6
+ gleam_erlang = ">= 0.25.0"
7
+ argv = ">= 1.0.1"
8
+ mist = ">= 2.0.0"
9
+ gleam_http = ">= 0.17.0"
10
+ lustre = ">= 5.7.0 and < 6.0.0"
11
+ simplifile = ">= 2.0.1 and < 3.0.0"
12
+
13
+ [dev-dependencies]
14
+ gleeunit = ">= 1.0.0"
15
+ lustre_dev_tools = ">= 2.3.6 and < 3.0.0"
manifest.toml ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file was generated by Gleam
2
+ # You typically do not need to edit this file
3
+
4
+ packages = [
5
+ { name = "argv", version = "1.0.2", build_tools = ["gleam"], requirements = [], otp_app = "argv", source = "hex", outer_checksum = "BA1FF0929525DEBA1CE67256E5ADF77A7CDDFE729E3E3F57A5BDCAA031DED09D" },
6
+ { name = "booklet", version = "1.1.0", build_tools = ["gleam"], requirements = [], otp_app = "booklet", source = "hex", outer_checksum = "08E0FDB78DC4D8A5D3C80295B021505C7D2A2E7B6C6D5EAB7286C36F4A53C851" },
7
+ { name = "directories", version = "1.2.0", build_tools = ["gleam"], requirements = ["envoy", "gleam_stdlib", "platform", "simplifile"], otp_app = "directories", source = "hex", outer_checksum = "D13090CFCDF6759B87217E8DDD73A75903A700148A82C1D33799F333E249BF9E" },
8
+ { name = "envoy", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "envoy", source = "hex", outer_checksum = "9C6FBB6BFA02A52798BEEC5977A738CAD6E4A057F4B67FD0C8061AD2502C191A" },
9
+ { name = "exception", version = "2.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "exception", source = "hex", outer_checksum = "329D269D5C2A314F7364BD2711372B6F2C58FA6F39981572E5CA68624D291F8C" },
10
+ { name = "filepath", version = "1.1.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "B06A9AF0BF10E51401D64B98E4B627F1D2E48C154967DA7AF4D0914780A6D40A" },
11
+ { name = "gleam_community_ansi", version = "1.4.4", build_tools = ["gleam"], requirements = ["gleam_community_colour", "gleam_regexp", "gleam_stdlib"], otp_app = "gleam_community_ansi", source = "hex", outer_checksum = "1B3AEA6074AB34D5F0674744F36DDC7290303A03295507E2DEC61EDD6F5777FE" },
12
+ { name = "gleam_community_colour", version = "2.0.4", build_tools = ["gleam"], requirements = ["gleam_json", "gleam_stdlib"], otp_app = "gleam_community_colour", source = "hex", outer_checksum = "6DB4665555D7D2B27F0EA32EF47E8BEBC4303821765F9C73D483F38EE24894F0" },
13
+ { name = "gleam_crypto", version = "1.5.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_crypto", source = "hex", outer_checksum = "50774BAFFF1144E7872814C566C5D653D83A3EBF23ACC3156B757A1B6819086E" },
14
+ { name = "gleam_erlang", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "1124AD3AA21143E5AF0FC5CF3D9529F6DB8CA03E43A55711B60B6B7B3874375C" },
15
+ { name = "gleam_http", version = "4.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_http", source = "hex", outer_checksum = "82EA6A717C842456188C190AFB372665EA56CE13D8559BF3B1DD9E40F619EE0C" },
16
+ { name = "gleam_httpc", version = "5.0.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_http", "gleam_stdlib"], otp_app = "gleam_httpc", source = "hex", outer_checksum = "C545172618D07811494E97AAA4A0FB34DA6F6D0061FDC8041C2F8E3BE2B2E48F" },
17
+ { name = "gleam_json", version = "3.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_json", source = "hex", outer_checksum = "44FDAA8847BE8FC48CA7A1C089706BD54BADCC4C45B237A992EDDF9F2CDB2836" },
18
+ { name = "gleam_otp", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "gleam_otp", source = "hex", outer_checksum = "BA6A294E295E428EC1562DC1C11EA7530DCB981E8359134BEABC8493B7B2258E" },
19
+ { name = "gleam_regexp", version = "1.1.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_regexp", source = "hex", outer_checksum = "9C215C6CA84A5B35BB934A9B61A9A306EC743153BE2B0425A0D032E477B062A9" },
20
+ { name = "gleam_stdlib", version = "0.70.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "86949BF5D1F0E4AC0AB5B06F235D8A5CC11A2DFC33BF22F752156ED61CA7D0FF" },
21
+ { name = "gleam_time", version = "1.8.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_time", source = "hex", outer_checksum = "533D8723774D61AD4998324F5DD1DABDCDBFABAFB9E87CB5D03C6955448FC97D" },
22
+ { name = "gleeunit", version = "1.9.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "DA9553CE58B67924B3C631F96FE3370C49EB6D6DC6B384EC4862CC4AAA718F3C" },
23
+ { name = "glint", version = "1.2.1", build_tools = ["gleam"], requirements = ["gleam_community_ansi", "gleam_community_colour", "gleam_stdlib", "snag"], otp_app = "glint", source = "hex", outer_checksum = "2214C7CEFDE457CEE62140C3D4899B964E05236DA74E4243DFADF4AF29C382BB" },
24
+ { name = "glisten", version = "9.0.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_otp", "gleam_stdlib", "logging"], otp_app = "glisten", source = "hex", outer_checksum = "D92808C66F7D3F22F2289CD04CBA8151757AAE9CB3D86992F0C6DE32A41205E1" },
25
+ { name = "gramps", version = "6.0.0", build_tools = ["gleam"], requirements = ["gleam_crypto", "gleam_erlang", "gleam_http", "gleam_stdlib"], otp_app = "gramps", source = "hex", outer_checksum = "8B7195978FBFD30B43DF791A8A272041B81E45D245314D7A41FC57237AA882A0" },
26
+ { name = "group_registry", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_otp", "gleam_stdlib"], otp_app = "group_registry", source = "hex", outer_checksum = "BC798A53D6F2406DB94E27CB45C57052CB56B32ACF7CC16EA20F6BAEC7E36B90" },
27
+ { name = "houdini", version = "1.2.1", build_tools = ["gleam"], requirements = [], otp_app = "houdini", source = "hex", outer_checksum = "6F8AC2F12974567FB744BEA66AC93CEB76AAEA19AD28564623F76CDA9BC26A85" },
28
+ { name = "hpack_erl", version = "0.3.0", build_tools = ["rebar3"], requirements = [], otp_app = "hpack", source = "hex", outer_checksum = "D6137D7079169D8C485C6962DFE261AF5B9EF60FBC557344511C1E65E3D95FB0" },
29
+ { name = "justin", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "justin", source = "hex", outer_checksum = "8B1C62269E8607D0A0ED698B7903984CE0BF7B6B3C0DEA3C6C8302B39402837B" },
30
+ { name = "logging", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "logging", source = "hex", outer_checksum = "1098FBF10B54B44C2C7FDF0B01C1253CAFACDACABEFB4B0D027803246753E06D" },
31
+ { name = "lustre", version = "5.7.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_json", "gleam_otp", "gleam_stdlib", "houdini"], otp_app = "lustre", source = "hex", outer_checksum = "38C6FCBD7B7BACE994D5BF643202BB69B02576D44250B4C5DCE738387C0E8F87" },
32
+ { name = "lustre_dev_tools", version = "2.3.6", build_tools = ["gleam"], requirements = ["argv", "booklet", "filepath", "gleam_community_ansi", "gleam_crypto", "gleam_erlang", "gleam_http", "gleam_httpc", "gleam_json", "gleam_otp", "gleam_regexp", "gleam_stdlib", "glint", "group_registry", "justin", "lustre", "mist", "polly", "simplifile", "tom", "wisp"], otp_app = "lustre_dev_tools", source = "hex", outer_checksum = "7A650A107C7E767D902A8CB608460B927DE0CDD47D5BA04DED71F9F622FE6AD9" },
33
+ { name = "marceau", version = "1.3.0", build_tools = ["gleam"], requirements = [], otp_app = "marceau", source = "hex", outer_checksum = "2D1C27504BEF45005F5DFB18591F8610FB4BFA91744878210BDC464412EC44E9" },
34
+ { name = "mist", version = "6.0.2", build_tools = ["gleam"], requirements = ["exception", "gleam_erlang", "gleam_http", "gleam_otp", "gleam_stdlib", "glisten", "gramps", "hpack_erl", "logging"], otp_app = "mist", source = "hex", outer_checksum = "6B03DEEA38A02F276333CB27B53B16D3D45BD741B89599085A601BAF635F2006" },
35
+ { name = "platform", version = "1.0.0", build_tools = ["gleam"], requirements = [], otp_app = "platform", source = "hex", outer_checksum = "8339420A95AD89AAC0F82F4C3DB8DD401041742D6C3F46132A8739F6AEB75391" },
36
+ { name = "polly", version = "3.1.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_erlang", "gleam_otp", "gleam_stdlib", "simplifile"], otp_app = "polly", source = "hex", outer_checksum = "51FB565D81FF6212FDF3306D44419601F2A7C4EDD1F00FC9DA5C376A00AED4FE" },
37
+ { name = "simplifile", version = "2.4.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "7C18AFA4FED0B4CE1FA5B0B4BAC1FA1744427054EA993565F6F3F82E5453170D" },
38
+ { name = "snag", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "snag", source = "hex", outer_checksum = "274F41D6C3ECF99F7686FDCE54183333E41D2C1CA5A3A673F9A8B2C7A4401077" },
39
+ { name = "tom", version = "2.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "gleam_time"], otp_app = "tom", source = "hex", outer_checksum = "DCF04CB7AB35D58CFC598C66EA2E1816D160759802C89B2BA6238780D59BC256" },
40
+ { name = "wisp", version = "2.2.2", build_tools = ["gleam"], requirements = ["directories", "exception", "filepath", "gleam_crypto", "gleam_erlang", "gleam_http", "gleam_json", "gleam_stdlib", "houdini", "logging", "marceau", "mist", "simplifile"], otp_app = "wisp", source = "hex", outer_checksum = "5FF5F1E288C3437252ABB93D8F9CF42FF652CE7AD54480CFE736038DC09C4F22" },
41
+ ]
42
+
43
+ [requirements]
44
+ argv = { version = ">= 1.0.1" }
45
+ gleam_erlang = { version = ">= 0.25.0" }
46
+ gleam_http = { version = ">= 0.17.0" }
47
+ gleam_stdlib = { version = ">= 0.34.0" }
48
+ gleeunit = { version = ">= 1.0.0" }
49
+ lustre = { version = ">= 5.7.0 and < 6.0.0" }
50
+ lustre_dev_tools = { version = ">= 2.3.6 and < 3.0.0" }
51
+ mist = { version = ">= 2.0.0" }
52
+ simplifile = { version = ">= 2.0.1 and < 3.0.0" }
native/sled_bridge ADDED
File without changes
native/sled_engine/Cargo.lock ADDED
@@ -0,0 +1,335 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is automatically @generated by Cargo.
2
+ # It is not intended for manual editing.
3
+ version = 4
4
+
5
+ [[package]]
6
+ name = "aho-corasick"
7
+ version = "1.1.4"
8
+ source = "registry+https://github.com/rust-lang/crates.io-index"
9
+ checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
10
+ dependencies = [
11
+ "memchr",
12
+ ]
13
+
14
+ [[package]]
15
+ name = "bitflags"
16
+ version = "1.3.2"
17
+ source = "registry+https://github.com/rust-lang/crates.io-index"
18
+ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
19
+
20
+ [[package]]
21
+ name = "byteorder"
22
+ version = "1.5.0"
23
+ source = "registry+https://github.com/rust-lang/crates.io-index"
24
+ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
25
+
26
+ [[package]]
27
+ name = "cfg-if"
28
+ version = "1.0.4"
29
+ source = "registry+https://github.com/rust-lang/crates.io-index"
30
+ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
31
+
32
+ [[package]]
33
+ name = "crc32fast"
34
+ version = "1.5.0"
35
+ source = "registry+https://github.com/rust-lang/crates.io-index"
36
+ checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
37
+ dependencies = [
38
+ "cfg-if",
39
+ ]
40
+
41
+ [[package]]
42
+ name = "crossbeam-epoch"
43
+ version = "0.9.18"
44
+ source = "registry+https://github.com/rust-lang/crates.io-index"
45
+ checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
46
+ dependencies = [
47
+ "crossbeam-utils",
48
+ ]
49
+
50
+ [[package]]
51
+ name = "crossbeam-utils"
52
+ version = "0.8.21"
53
+ source = "registry+https://github.com/rust-lang/crates.io-index"
54
+ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
55
+
56
+ [[package]]
57
+ name = "flashsync_native"
58
+ version = "0.1.0"
59
+ dependencies = [
60
+ "rustler",
61
+ "sled",
62
+ ]
63
+
64
+ [[package]]
65
+ name = "fs2"
66
+ version = "0.4.3"
67
+ source = "registry+https://github.com/rust-lang/crates.io-index"
68
+ checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"
69
+ dependencies = [
70
+ "libc",
71
+ "winapi",
72
+ ]
73
+
74
+ [[package]]
75
+ name = "fxhash"
76
+ version = "0.2.1"
77
+ source = "registry+https://github.com/rust-lang/crates.io-index"
78
+ checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
79
+ dependencies = [
80
+ "byteorder",
81
+ ]
82
+
83
+ [[package]]
84
+ name = "heck"
85
+ version = "0.5.0"
86
+ source = "registry+https://github.com/rust-lang/crates.io-index"
87
+ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
88
+
89
+ [[package]]
90
+ name = "instant"
91
+ version = "0.1.13"
92
+ source = "registry+https://github.com/rust-lang/crates.io-index"
93
+ checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
94
+ dependencies = [
95
+ "cfg-if",
96
+ ]
97
+
98
+ [[package]]
99
+ name = "inventory"
100
+ version = "0.3.22"
101
+ source = "registry+https://github.com/rust-lang/crates.io-index"
102
+ checksum = "009ae045c87e7082cb72dab0ccd01ae075dd00141ddc108f43a0ea150a9e7227"
103
+ dependencies = [
104
+ "rustversion",
105
+ ]
106
+
107
+ [[package]]
108
+ name = "libc"
109
+ version = "0.2.183"
110
+ source = "registry+https://github.com/rust-lang/crates.io-index"
111
+ checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d"
112
+
113
+ [[package]]
114
+ name = "lock_api"
115
+ version = "0.4.14"
116
+ source = "registry+https://github.com/rust-lang/crates.io-index"
117
+ checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
118
+ dependencies = [
119
+ "scopeguard",
120
+ ]
121
+
122
+ [[package]]
123
+ name = "log"
124
+ version = "0.4.29"
125
+ source = "registry+https://github.com/rust-lang/crates.io-index"
126
+ checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
127
+
128
+ [[package]]
129
+ name = "memchr"
130
+ version = "2.8.0"
131
+ source = "registry+https://github.com/rust-lang/crates.io-index"
132
+ checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
133
+
134
+ [[package]]
135
+ name = "parking_lot"
136
+ version = "0.11.2"
137
+ source = "registry+https://github.com/rust-lang/crates.io-index"
138
+ checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
139
+ dependencies = [
140
+ "instant",
141
+ "lock_api",
142
+ "parking_lot_core",
143
+ ]
144
+
145
+ [[package]]
146
+ name = "parking_lot_core"
147
+ version = "0.8.6"
148
+ source = "registry+https://github.com/rust-lang/crates.io-index"
149
+ checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc"
150
+ dependencies = [
151
+ "cfg-if",
152
+ "instant",
153
+ "libc",
154
+ "redox_syscall",
155
+ "smallvec",
156
+ "winapi",
157
+ ]
158
+
159
+ [[package]]
160
+ name = "proc-macro2"
161
+ version = "1.0.106"
162
+ source = "registry+https://github.com/rust-lang/crates.io-index"
163
+ checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
164
+ dependencies = [
165
+ "unicode-ident",
166
+ ]
167
+
168
+ [[package]]
169
+ name = "quote"
170
+ version = "1.0.45"
171
+ source = "registry+https://github.com/rust-lang/crates.io-index"
172
+ checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
173
+ dependencies = [
174
+ "proc-macro2",
175
+ ]
176
+
177
+ [[package]]
178
+ name = "redox_syscall"
179
+ version = "0.2.16"
180
+ source = "registry+https://github.com/rust-lang/crates.io-index"
181
+ checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
182
+ dependencies = [
183
+ "bitflags",
184
+ ]
185
+
186
+ [[package]]
187
+ name = "regex"
188
+ version = "1.12.3"
189
+ source = "registry+https://github.com/rust-lang/crates.io-index"
190
+ checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276"
191
+ dependencies = [
192
+ "aho-corasick",
193
+ "memchr",
194
+ "regex-automata",
195
+ "regex-syntax",
196
+ ]
197
+
198
+ [[package]]
199
+ name = "regex-automata"
200
+ version = "0.4.14"
201
+ source = "registry+https://github.com/rust-lang/crates.io-index"
202
+ checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f"
203
+ dependencies = [
204
+ "aho-corasick",
205
+ "memchr",
206
+ "regex-syntax",
207
+ ]
208
+
209
+ [[package]]
210
+ name = "regex-syntax"
211
+ version = "0.8.10"
212
+ source = "registry+https://github.com/rust-lang/crates.io-index"
213
+ checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
214
+
215
+ [[package]]
216
+ name = "rustler"
217
+ version = "0.34.0"
218
+ source = "registry+https://github.com/rust-lang/crates.io-index"
219
+ checksum = "e94bdfa68c0388cbd725f1ca54e975956482c262599e5cced04a903eec918b7f"
220
+ dependencies = [
221
+ "inventory",
222
+ "rustler_codegen",
223
+ "rustler_sys",
224
+ ]
225
+
226
+ [[package]]
227
+ name = "rustler_codegen"
228
+ version = "0.34.0"
229
+ source = "registry+https://github.com/rust-lang/crates.io-index"
230
+ checksum = "996dc019acb78b91b4e0c1bd6fa2cd509a835d309de762dc15213b97eac399da"
231
+ dependencies = [
232
+ "heck",
233
+ "inventory",
234
+ "proc-macro2",
235
+ "quote",
236
+ "syn",
237
+ ]
238
+
239
+ [[package]]
240
+ name = "rustler_sys"
241
+ version = "2.4.3"
242
+ source = "registry+https://github.com/rust-lang/crates.io-index"
243
+ checksum = "ddd0e2c955cfc86ea4680067e1d5e711427b43f7befcb6e23c7807cf3dd90e97"
244
+ dependencies = [
245
+ "regex",
246
+ "unreachable",
247
+ ]
248
+
249
+ [[package]]
250
+ name = "rustversion"
251
+ version = "1.0.22"
252
+ source = "registry+https://github.com/rust-lang/crates.io-index"
253
+ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
254
+
255
+ [[package]]
256
+ name = "scopeguard"
257
+ version = "1.2.0"
258
+ source = "registry+https://github.com/rust-lang/crates.io-index"
259
+ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
260
+
261
+ [[package]]
262
+ name = "sled"
263
+ version = "0.34.7"
264
+ source = "registry+https://github.com/rust-lang/crates.io-index"
265
+ checksum = "7f96b4737c2ce5987354855aed3797279def4ebf734436c6aa4552cf8e169935"
266
+ dependencies = [
267
+ "crc32fast",
268
+ "crossbeam-epoch",
269
+ "crossbeam-utils",
270
+ "fs2",
271
+ "fxhash",
272
+ "libc",
273
+ "log",
274
+ "parking_lot",
275
+ ]
276
+
277
+ [[package]]
278
+ name = "smallvec"
279
+ version = "1.15.1"
280
+ source = "registry+https://github.com/rust-lang/crates.io-index"
281
+ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
282
+
283
+ [[package]]
284
+ name = "syn"
285
+ version = "2.0.117"
286
+ source = "registry+https://github.com/rust-lang/crates.io-index"
287
+ checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
288
+ dependencies = [
289
+ "proc-macro2",
290
+ "quote",
291
+ "unicode-ident",
292
+ ]
293
+
294
+ [[package]]
295
+ name = "unicode-ident"
296
+ version = "1.0.24"
297
+ source = "registry+https://github.com/rust-lang/crates.io-index"
298
+ checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
299
+
300
+ [[package]]
301
+ name = "unreachable"
302
+ version = "1.0.0"
303
+ source = "registry+https://github.com/rust-lang/crates.io-index"
304
+ checksum = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
305
+ dependencies = [
306
+ "void",
307
+ ]
308
+
309
+ [[package]]
310
+ name = "void"
311
+ version = "1.0.2"
312
+ source = "registry+https://github.com/rust-lang/crates.io-index"
313
+ checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
314
+
315
+ [[package]]
316
+ name = "winapi"
317
+ version = "0.3.9"
318
+ source = "registry+https://github.com/rust-lang/crates.io-index"
319
+ checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
320
+ dependencies = [
321
+ "winapi-i686-pc-windows-gnu",
322
+ "winapi-x86_64-pc-windows-gnu",
323
+ ]
324
+
325
+ [[package]]
326
+ name = "winapi-i686-pc-windows-gnu"
327
+ version = "0.4.0"
328
+ source = "registry+https://github.com/rust-lang/crates.io-index"
329
+ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
330
+
331
+ [[package]]
332
+ name = "winapi-x86_64-pc-windows-gnu"
333
+ version = "0.4.0"
334
+ source = "registry+https://github.com/rust-lang/crates.io-index"
335
+ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
native/sled_engine/Cargo.toml ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [package]
2
+ name = "flashsync_native"
3
+ version = "0.1.0"
4
+ edition = "2021"
5
+
6
+ [lib]
7
+ name = "flashsync_native"
8
+ crate-type = ["cdylib"]
9
+
10
+ [dependencies]
11
+ rustler = "0.34.0"
12
+ sled = "0.34.7"
13
+ serde = { version = "1.0", features = ["derive"] }
14
+ serde_json = "1.0"
15
+ chrono = "0.4"
16
+ uuid = { version = "1.0", features = ["v4", "serde"] }
native/sled_engine/src/lib.rs ADDED
@@ -0,0 +1,294 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ use rustler::{NifResult, Binary};
2
+ use serde::{Deserialize, Serialize};
3
+ use chrono::{DateTime, Utc};
4
+ use uuid::Uuid;
5
+
6
+ #[derive(Debug, Clone, Serialize, Deserialize)]
7
+ pub struct ReviewHistory {
8
+ pub review_date: String,
9
+ pub grade: i32, // 0-5 (SM-2 grades)
10
+ pub time_spent: i64, // milliseconds
11
+ }
12
+
13
+ #[derive(Debug, Clone, Serialize, Deserialize)]
14
+ pub struct CardMetadata {
15
+ pub id: String,
16
+ pub created_at: String,
17
+ pub updated_at: String,
18
+ pub last_reviewed: Option<String>,
19
+ pub ease_factor: f64, // SM-2: starts at 2.5
20
+ pub interval: i64, // SM-2: days between reviews
21
+ pub repetitions: i32, // SM-2: number of times reviewed
22
+ pub tags: Vec<String>,
23
+ pub related_cards: Vec<String>,
24
+ pub question: String,
25
+ pub answer: String,
26
+ pub sketch_data: Option<String>,
27
+ pub review_history: Vec<ReviewHistory>,
28
+ pub variations: Vec<CardVariation>,
29
+ pub is_mastered: bool,
30
+ pub focused_count: i32, // biometric tracking
31
+ }
32
+
33
+ #[derive(Debug, Clone, Serialize, Deserialize)]
34
+ pub struct CardVariation {
35
+ pub timestamp: String,
36
+ pub question: String,
37
+ pub answer: String,
38
+ }
39
+
40
+ #[derive_nifizer::nif]
41
+ #[rustler::nif]
42
+ fn create_card(
43
+ id: String,
44
+ question: String,
45
+ answer: String,
46
+ tags: Vec<String>,
47
+ ) -> NifResult<String> {
48
+ let card = CardMetadata {
49
+ id: id.clone(),
50
+ created_at: Utc::now().to_rfc3339(),
51
+ updated_at: Utc::now().to_rfc3339(),
52
+ last_reviewed: None,
53
+ ease_factor: 2.5,
54
+ interval: 1,
55
+ repetitions: 0,
56
+ tags,
57
+ related_cards: vec![],
58
+ question,
59
+ answer,
60
+ sketch_data: None,
61
+ review_history: vec![],
62
+ variations: vec![],
63
+ is_mastered: false,
64
+ focused_count: 0,
65
+ };
66
+
67
+ let db = sled::open("flashcards.db")
68
+ .map_err(|e| rustler::Error::Term(Box::new(e.to_string())))?;
69
+
70
+ let card_json = serde_json::to_string(&card)
71
+ .map_err(|e| rustler::Error::Term(Box::new(e.to_string())))?;
72
+
73
+ db.insert(id.as_bytes(), card_json.as_bytes())
74
+ .map_err(|e| rustler::Error::Term(Box::new(e.to_string())))?;
75
+
76
+ let _ = db.flush();
77
+ Ok(serde_json::to_string(&card).unwrap_or_default())
78
+ }
79
+
80
+ #[rustler::nif]
81
+ fn save_card(id: String, content: String) -> NifResult<String> {
82
+ let db = sled::open("flashcards.db")
83
+ .map_err(|e| rustler::Error::Term(Box::new(e.to_string())))?;
84
+
85
+ match db.get(id.as_bytes())
86
+ .map_err(|e| rustler::Error::Term(Box::new(e.to_string())))? {
87
+ Some(existing) => {
88
+ let mut card: CardMetadata = serde_json::from_slice(&existing)
89
+ .map_err(|e| rustler::Error::Term(Box::new(e.to_string())))?;
90
+
91
+ // Store old version in variations for time-travel
92
+ card.variations.push(CardVariation {
93
+ timestamp: card.updated_at.clone(),
94
+ question: card.question.clone(),
95
+ answer: card.answer.clone(),
96
+ });
97
+
98
+ // Keep only last 50 variations
99
+ if card.variations.len() > 50 {
100
+ card.variations.remove(0);
101
+ }
102
+
103
+ // Update with new content (expecting JSON)
104
+ if let Ok(update) = serde_json::from_str::<serde_json::Value>(&content) {
105
+ if let Some(q) = update.get("question").and_then(|v| v.as_str()) {
106
+ card.question = q.to_string();
107
+ }
108
+ if let Some(a) = update.get("answer").and_then(|v| v.as_str()) {
109
+ card.answer = a.to_string();
110
+ }
111
+ if let Some(tags) = update.get("tags").and_then(|v| v.as_array()) {
112
+ card.tags = tags.iter().filter_map(|t| t.as_str().map(|s| s.to_string())).collect();
113
+ }
114
+ if let Some(sketch) = update.get("sketch_data").and_then(|v| v.as_str()) {
115
+ card.sketch_data = Some(sketch.to_string());
116
+ }
117
+ }
118
+
119
+ card.updated_at = Utc::now().to_rfc3339();
120
+
121
+ let card_json = serde_json::to_string(&card)
122
+ .map_err(|e| rustler::Error::Term(Box::new(e.to_string())))?;
123
+
124
+ db.insert(id.as_bytes(), card_json.as_bytes())
125
+ .map_err(|e| rustler::Error::Term(Box::new(e.to_string())))?;
126
+
127
+ let _ = db.flush();
128
+ Ok("UPDATED".to_string())
129
+ }
130
+ None => {
131
+ db.insert(id.as_bytes(), content.as_bytes())
132
+ .map_err(|e| rustler::Error::Term(Box::new(e.to_string())))?;
133
+ let _ = db.flush();
134
+ Ok("CREATED".to_string())
135
+ }
136
+ }
137
+ }
138
+
139
+ #[rustler::nif]
140
+ fn get_card(id: String) -> NifResult<String> {
141
+ let db = sled::open("flashcards.db")
142
+ .map_err(|e| rustler::Error::Term(Box::new(e.to_string())))?;
143
+
144
+ match db.get(id.as_bytes())
145
+ .map_err(|e| rustler::Error::Term(Box::new(e.to_string())))? {
146
+ Some(ivec) => Ok(String::from_utf8_lossy(&ivec).to_string()),
147
+ None => Ok("NOT_FOUND".to_string()),
148
+ }
149
+ }
150
+
151
+ #[rustler::nif]
152
+ fn record_review(
153
+ id: String,
154
+ grade: i32,
155
+ time_spent: i64,
156
+ ) -> NifResult<String> {
157
+ let db = sled::open("flashcards.db")
158
+ .map_err(|e| rustler::Error::Term(Box::new(e.to_string())))?;
159
+
160
+ match db.get(id.as_bytes())
161
+ .map_err(|e| rustler::Error::Term(Box::new(e.to_string())))? {
162
+ Some(existing) => {
163
+ let mut card: CardMetadata = serde_json::from_slice(&existing)
164
+ .map_err(|e| rustler::Error::Term(Box::new(e.to_string())))?;
165
+
166
+ // SM-2 Algorithm Implementation
167
+ card.review_history.push(ReviewHistory {
168
+ review_date: Utc::now().to_rfc3339(),
169
+ grade,
170
+ time_spent,
171
+ });
172
+
173
+ card.repetitions += 1;
174
+ card.last_reviewed = Some(Utc::now().to_rfc3339());
175
+
176
+ // SM-2 calculation
177
+ if grade >= 3 {
178
+ if card.repetitions == 1 {
179
+ card.interval = 1;
180
+ } else if card.repetitions == 2 {
181
+ card.interval = 3;
182
+ } else {
183
+ card.interval = (card.interval as f64 * card.ease_factor).ceil() as i64;
184
+ }
185
+ } else {
186
+ card.repetitions = 0;
187
+ card.interval = 1;
188
+ }
189
+
190
+ // Ease Factor adjustment
191
+ let ef = card.ease_factor + (0.1 - (5.0 - grade as f64) * (0.08 + (5.0 - grade as f64) * 0.02));
192
+ card.ease_factor = if ef < 1.3 { 1.3 } else { ef };
193
+
194
+ // Mark as mastered if reviewed 5+ times with grade 4+
195
+ if card.repetitions >= 5 && grade >= 4 {
196
+ card.is_mastered = true;
197
+ }
198
+
199
+ let card_json = serde_json::to_string(&card)
200
+ .map_err(|e| rustler::Error::Term(Box::new(e.to_string())))?;
201
+
202
+ db.insert(id.as_bytes(), card_json.as_bytes())
203
+ .map_err(|e| rustler::Error::Term(Box::new(e.to_string())))?;
204
+
205
+ let _ = db.flush();
206
+ Ok(serde_json::to_string(&card).unwrap_or_default())
207
+ }
208
+ None => Err(rustler::Error::Term(Box::new("CARD_NOT_FOUND"))),
209
+ }
210
+ }
211
+
212
+ #[rustler::nif]
213
+ fn add_relationship(card_id: String, related_id: String) -> NifResult<String> {
214
+ let db = sled::open("flashcards.db")
215
+ .map_err(|e| rustler::Error::Term(Box::new(e.to_string())))?;
216
+
217
+ match db.get(card_id.as_bytes())
218
+ .map_err(|e| rustler::Error::Term(Box::new(e.to_string())))? {
219
+ Some(existing) => {
220
+ let mut card: CardMetadata = serde_json::from_slice(&existing)
221
+ .map_err(|e| rustler::Error::Term(Box::new(e.to_string())))?;
222
+
223
+ if !card.related_cards.contains(&related_id) {
224
+ card.related_cards.push(related_id);
225
+ }
226
+
227
+ let card_json = serde_json::to_string(&card)
228
+ .map_err(|e| rustler::Error::Term(Box::new(e.to_string())))?;
229
+
230
+ db.insert(card_id.as_bytes(), card_json.as_bytes())
231
+ .map_err(|e| rustler::Error::Term(Box::new(e.to_string())))?;
232
+
233
+ let _ = db.flush();
234
+ Ok("RELATIONSHIP_ADDED".to_string())
235
+ }
236
+ None => Err(rustler::Error::Term(Box::new("CARD_NOT_FOUND"))),
237
+ }
238
+ }
239
+
240
+ #[rustler::nif]
241
+ fn get_all_cards() -> NifResult<String> {
242
+ let db = sled::open("flashcards.db")
243
+ .map_err(|e| rustler::Error::Term(Box::new(e.to_string())))?;
244
+
245
+ let cards: Vec<CardMetadata> = db.iter()
246
+ .filter_map(|item| {
247
+ item.ok().and_then(|(_, v)| {
248
+ serde_json::from_slice(&v).ok()
249
+ })
250
+ })
251
+ .collect();
252
+
253
+ Ok(serde_json::to_string(&cards).unwrap_or_default())
254
+ }
255
+
256
+ #[rustler::nif]
257
+ fn get_historical_snapshot(id: String, timestamp: String) -> NifResult<String> {
258
+ let db = sled::open("flashcards.db")
259
+ .map_err(|e| rustler::Error::Term(Box::new(e.to_string())))?;
260
+
261
+ match db.get(id.as_bytes())
262
+ .map_err(|e| rustler::Error::Term(Box::new(e.to_string())))? {
263
+ Some(existing) => {
264
+ let card: CardMetadata = serde_json::from_slice(&existing)
265
+ .map_err(|e| rustler::Error::Term(Box::new(e.to_string())))?;
266
+
267
+ // Find variation closest to timestamp
268
+ let closest = card.variations.iter()
269
+ .min_by_key(|v| {
270
+ (v.timestamp.as_str().cmp(&timestamp.as_str()),
271
+ std::cmp::Ordering::Equal)
272
+ });
273
+
274
+ if let Some(variation) = closest {
275
+ Ok(serde_json::to_string(variation).unwrap_or_default())
276
+ } else {
277
+ Ok(format!("{{\\"question\\": \\"{}\\", \\"answer\\": \\"{}\\"}}",
278
+ card.question.replace("\"", "\\\""),
279
+ card.answer.replace("\"", "\\\"")))
280
+ }
281
+ }
282
+ None => Err(rustler::Error::Term(Box::new("CARD_NOT_FOUND"))),
283
+ }
284
+ }
285
+
286
+ rustler::init!("flashsync_native", [
287
+ create_card,
288
+ save_card,
289
+ get_card,
290
+ record_review,
291
+ add_relationship,
292
+ get_all_cards,
293
+ get_historical_snapshot
294
+ ]);
priv/exam.html ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ <div id='vpro-enterprise-app'>
2
+ <style>/* Add your CSS here */</style>
3
+ </div>
priv/static/app.js ADDED
The diff for this file is too large to render. See raw diff
 
priv/static/emojis/openmoji-72x72-color/0023-FE0F-20E3.png ADDED
priv/static/emojis/openmoji-72x72-color/002A-FE0F-20E3.png ADDED
priv/static/emojis/openmoji-72x72-color/002D.png ADDED
priv/static/emojis/openmoji-72x72-color/0030-FE0F-20E3.png ADDED
priv/static/emojis/openmoji-72x72-color/0031-FE0F-20E3.png ADDED
priv/static/emojis/openmoji-72x72-color/0032-FE0F-20E3.png ADDED
priv/static/emojis/openmoji-72x72-color/0033-FE0F-20E3.png ADDED
priv/static/emojis/openmoji-72x72-color/0034-FE0F-20E3.png ADDED
priv/static/emojis/openmoji-72x72-color/0035-FE0F-20E3.png ADDED
priv/static/emojis/openmoji-72x72-color/0036-FE0F-20E3.png ADDED
priv/static/emojis/openmoji-72x72-color/0037-FE0F-20E3.png ADDED
priv/static/emojis/openmoji-72x72-color/0038-FE0F-20E3.png ADDED
priv/static/emojis/openmoji-72x72-color/0039-FE0F-20E3.png ADDED
priv/static/emojis/openmoji-72x72-color/00A9.png ADDED
priv/static/emojis/openmoji-72x72-color/00AE.png ADDED
priv/static/emojis/openmoji-72x72-color/1F004.png ADDED
priv/static/emojis/openmoji-72x72-color/1F0CF.png ADDED
priv/static/emojis/openmoji-72x72-color/1F10D.png ADDED
priv/static/emojis/openmoji-72x72-color/1F10E.png ADDED
priv/static/emojis/openmoji-72x72-color/1F10F.png ADDED
priv/static/emojis/openmoji-72x72-color/1F12F.png ADDED
priv/static/emojis/openmoji-72x72-color/1F16D.png ADDED
priv/static/emojis/openmoji-72x72-color/1F16E.png ADDED
priv/static/emojis/openmoji-72x72-color/1F16F.png ADDED
priv/static/emojis/openmoji-72x72-color/1F170.png ADDED
priv/static/emojis/openmoji-72x72-color/1F171.png ADDED
priv/static/emojis/openmoji-72x72-color/1F17E.png ADDED
priv/static/emojis/openmoji-72x72-color/1F17F.png ADDED
priv/static/emojis/openmoji-72x72-color/1F18E.png ADDED
priv/static/emojis/openmoji-72x72-color/1F191.png ADDED
priv/static/emojis/openmoji-72x72-color/1F192.png ADDED
priv/static/emojis/openmoji-72x72-color/1F193.png ADDED
priv/static/emojis/openmoji-72x72-color/1F194.png ADDED
priv/static/emojis/openmoji-72x72-color/1F195.png ADDED