-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathschema.sql
More file actions
373 lines (372 loc) · 14.7 KB
/
Copy pathschema.sql
File metadata and controls
373 lines (372 loc) · 14.7 KB
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
-- WARNING: This schema is for context only and is not meant to be run.
-- Table order and constraints may not be valid for execution.
CREATE TABLE public.daily_challenge (
id text NOT NULL,
user_id text NOT NULL,
challenge_date bigint NOT NULL,
challenge_type text NOT NULL CHECK (challenge_type = ANY (ARRAY['story'::text, 'sentence'::text])),
dialect text NOT NULL,
story_id text,
sentences jsonb,
used_word_ids jsonb,
bonus_xp integer NOT NULL DEFAULT 10,
completed boolean DEFAULT false,
completed_at bigint,
xp_awarded boolean DEFAULT false,
created_at bigint NOT NULL,
CONSTRAINT daily_challenge_pkey PRIMARY KEY (id),
CONSTRAINT daily_challenge_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.user(id),
CONSTRAINT daily_challenge_story_fkey FOREIGN KEY (story_id) REFERENCES public.generated_story(id)
);
CREATE TABLE public.email_verification_token (
id character varying NOT NULL,
user_id character varying NOT NULL,
expires bigint NOT NULL,
CONSTRAINT email_verification_token_pkey PRIMARY KEY (id),
CONSTRAINT email_verification_token_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.user(id)
);
CREATE TABLE public.game_progress (
id text NOT NULL,
user_id text NOT NULL,
dialect text NOT NULL CHECK (dialect = ANY (ARRAY['egyptian-arabic'::text, 'fusha'::text, 'levantine'::text, 'darija'::text])),
category text NOT NULL,
game_mode text NOT NULL CHECK (game_mode = ANY (ARRAY['multiple-choice'::text, 'listening'::text, 'speaking'::text])),
current_index integer NOT NULL DEFAULT 0,
total_questions integer NOT NULL,
score integer NOT NULL DEFAULT 0,
words_to_review jsonb DEFAULT '[]'::jsonb,
question_order jsonb NOT NULL,
status text NOT NULL DEFAULT 'in_progress'::text CHECK (status = ANY (ARRAY['in_progress'::text, 'completed'::text])),
started_at bigint NOT NULL DEFAULT (EXTRACT(epoch FROM now()) * (1000)::numeric),
last_played_at bigint NOT NULL DEFAULT (EXTRACT(epoch FROM now()) * (1000)::numeric),
completed_at bigint,
CONSTRAINT game_progress_pkey PRIMARY KEY (id),
CONSTRAINT game_progress_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.user(id)
);
CREATE TABLE public.generated_lesson (
id text NOT NULL,
user_id text NOT NULL,
title text,
title_arabic text,
description text,
level text NOT NULL CHECK (level = ANY (ARRAY['beginner'::text, 'intermediate'::text, 'advanced'::text])),
dialect text NOT NULL CHECK (dialect = ANY (ARRAY['egyptian-arabic'::text, 'fusha'::text, 'levantine'::text, 'darija'::text])),
lesson_body text NOT NULL,
sub_lesson_count integer,
estimated_duration integer,
created_at text NOT NULL,
is_private boolean NOT NULL DEFAULT false,
CONSTRAINT generated_lesson_pkey PRIMARY KEY (id),
CONSTRAINT generated_lesson_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.user(id)
);
CREATE TABLE public.generated_story (
id text NOT NULL,
user_id text NOT NULL,
title text NOT NULL,
description text NOT NULL,
difficulty text NOT NULL,
story_body text NOT NULL,
dialect text NOT NULL,
created_at text NOT NULL,
audio_file_key text,
CONSTRAINT generated_story_pkey PRIMARY KEY (id),
CONSTRAINT generated_story_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.user(id)
);
CREATE TABLE public.password_reset_token (
id character varying NOT NULL,
user_id character varying NOT NULL,
expires bigint NOT NULL,
CONSTRAINT password_reset_token_pkey PRIMARY KEY (id),
CONSTRAINT password_reset_token_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.user(id)
);
CREATE TABLE public.saved_word (
id text NOT NULL,
user_id text NOT NULL,
arabic_word text NOT NULL,
english_word text NOT NULL,
transliterated_word text NOT NULL,
created_at bigint NOT NULL,
word_id text,
ease_factor real DEFAULT 2.5,
interval_days integer DEFAULT 0,
repetitions integer DEFAULT 0,
next_review_date bigint,
last_review_date bigint,
is_learning boolean DEFAULT true,
mastery_level integer DEFAULT 0,
dialect text,
forgotten_in_session boolean DEFAULT false,
CONSTRAINT saved_word_pkey PRIMARY KEY (id),
CONSTRAINT saved_word_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.user(id),
CONSTRAINT fk_saved_word_word_id FOREIGN KEY (word_id) REFERENCES public.word(id)
);
CREATE TABLE public.self_study_sessions (
id text NOT NULL,
user_id text NOT NULL,
title text NOT NULL,
dialect text NOT NULL,
level text NOT NULL DEFAULT 'intermediate'::text,
vocab_count integer NOT NULL DEFAULT 0,
step_count integer NOT NULL DEFAULT 0,
score_percent integer,
session_data_key text NOT NULL,
created_at bigint NOT NULL,
CONSTRAINT self_study_sessions_pkey PRIMARY KEY (id),
CONSTRAINT self_study_sessions_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.user(id)
);
CREATE TABLE public.stories (
id character varying NOT NULL,
title character varying NOT NULL,
key character varying NOT NULL,
description text NOT NULL,
difficulty integer NOT NULL,
created_at bigint NOT NULL,
CONSTRAINT stories_pkey PRIMARY KEY (id)
);
CREATE TABLE public.structured_lesson_progress (
id text NOT NULL,
user_id text NOT NULL,
topic_id text NOT NULL,
dialect text NOT NULL CHECK (dialect = ANY (ARRAY['egyptian-arabic'::text, 'fusha'::text, 'levantine'::text, 'darija'::text, 'alphabet'::text])),
status text NOT NULL DEFAULT 'not_started'::text CHECK (status = ANY (ARRAY['not_started'::text, 'in_progress'::text, 'completed'::text])),
started_at bigint,
completed_at bigint,
last_accessed_at bigint,
progress_percentage integer DEFAULT 0 CHECK (progress_percentage >= 0 AND progress_percentage <= 100),
created_at bigint NOT NULL DEFAULT EXTRACT(epoch FROM now()),
updated_at bigint NOT NULL DEFAULT EXTRACT(epoch FROM now()),
CONSTRAINT structured_lesson_progress_pkey PRIMARY KEY (id),
CONSTRAINT structured_lesson_progress_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.user(id)
);
CREATE TABLE public.tutor_conversation (
id text NOT NULL,
user_id text NOT NULL,
dialect text NOT NULL,
created_at bigint NOT NULL,
ended_at bigint,
summary text,
topics_discussed ARRAY,
new_vocabulary ARRAY,
CONSTRAINT tutor_conversation_pkey PRIMARY KEY (id),
CONSTRAINT tutor_conversation_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.user(id)
);
CREATE TABLE public.tutor_learning_insight (
id text NOT NULL,
user_id text NOT NULL,
dialect text NOT NULL,
insight_type text NOT NULL CHECK (insight_type = ANY (ARRAY['weakness'::text, 'strength'::text, 'topic_interest'::text, 'vocabulary_gap'::text])),
content text NOT NULL,
confidence real DEFAULT 0.5,
occurrences integer DEFAULT 1,
last_observed_at bigint NOT NULL,
created_at bigint NOT NULL,
CONSTRAINT tutor_learning_insight_pkey PRIMARY KEY (id),
CONSTRAINT tutor_learning_insight_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.user(id)
);
CREATE TABLE public.tutor_message (
id text NOT NULL,
conversation_id text NOT NULL,
role text NOT NULL CHECK (role = ANY (ARRAY['user'::text, 'tutor'::text])),
arabic text,
english text,
transliteration text,
feedback text,
created_at bigint NOT NULL,
CONSTRAINT tutor_message_pkey PRIMARY KEY (id),
CONSTRAINT tutor_message_conversation_id_fkey FOREIGN KEY (conversation_id) REFERENCES public.tutor_conversation(id)
);
CREATE TABLE public.user (
id text NOT NULL,
email text NOT NULL UNIQUE,
email_verified boolean NOT NULL,
is_subscriber boolean NOT NULL,
subscriber_id text,
subscription_end_date bigint,
sentences_viewed integer,
verb_conjugation_tenses_viewed integer,
google_id text,
auth_provider text,
name text,
picture text,
supabase_auth_id uuid,
target_dialect text CHECK (target_dialect = ANY (ARRAY['egyptian-arabic'::text, 'fusha'::text, 'levantine'::text, 'darija'::text])),
learning_reason text,
proficiency_level text CHECK (proficiency_level = ANY (ARRAY['A1'::text, 'A2'::text, 'B1'::text, 'B2'::text, 'C1'::text, 'C2'::text])),
onboarding_completed boolean DEFAULT false,
onboarding_completed_at bigint,
current_streak integer DEFAULT 0,
longest_streak integer DEFAULT 0,
last_activity_date bigint,
total_reviews integer DEFAULT 0,
total_sentences_viewed integer DEFAULT 0,
total_stories_viewed integer DEFAULT 0,
total_lessons_viewed integer DEFAULT 0,
total_saved_words integer DEFAULT 0,
reviews_this_week integer DEFAULT 0,
sentences_viewed_this_week integer DEFAULT 0,
stories_viewed_this_week integer DEFAULT 0,
lessons_viewed_this_week integer DEFAULT 0,
saved_words_this_week integer DEFAULT 0,
week_start_date bigint,
daily_review_limit integer DEFAULT 20,
show_arabic boolean DEFAULT true,
show_transliteration boolean DEFAULT true,
show_english boolean DEFAULT true,
preferred_font_size text DEFAULT 'medium'::text CHECK (preferred_font_size = ANY (ARRAY['small'::text, 'medium'::text, 'large'::text])),
last_content_type text CHECK (last_content_type = ANY (ARRAY['sentences'::text, 'lessons'::text, 'stories'::text, 'vocabulary'::text, 'alphabet'::text, 'review'::text])),
last_content_id text,
last_content_position integer DEFAULT 0,
last_content_dialect text CHECK (last_content_dialect = ANY (ARRAY['egyptian-arabic'::text, 'fusha'::text, 'levantine'::text, 'darija'::text])),
last_content_accessed_at bigint,
total_shorts_viewed integer DEFAULT 0,
shorts_viewed_this_week integer DEFAULT 0,
total_xp integer NOT NULL DEFAULT 0,
current_level integer NOT NULL DEFAULT 1,
email_notifications_enabled boolean NOT NULL DEFAULT true,
xp_this_week integer NOT NULL DEFAULT 0,
leaderboard_opt_out boolean NOT NULL DEFAULT false,
tts_calls_count integer NOT NULL DEFAULT 0,
CONSTRAINT user_pkey PRIMARY KEY (id)
);
CREATE TABLE public.user_daily_activity (
id text NOT NULL,
user_id text NOT NULL,
activity_date bigint NOT NULL,
reviews_count integer DEFAULT 0,
sentences_viewed integer DEFAULT 0,
stories_viewed integer DEFAULT 0,
lessons_viewed integer DEFAULT 0,
saved_words_count integer DEFAULT 0,
created_at bigint NOT NULL,
updated_at bigint NOT NULL,
shorts_viewed integer DEFAULT 0,
word_of_day_saved boolean DEFAULT false,
CONSTRAINT user_daily_activity_pkey PRIMARY KEY (id),
CONSTRAINT user_daily_activity_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.user(id)
);
CREATE TABLE public.user_key (
id character varying NOT NULL,
user_id character varying NOT NULL,
hashed_password character varying,
CONSTRAINT user_key_pkey PRIMARY KEY (id),
CONSTRAINT user_key_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.user(id)
);
CREATE TABLE public.user_session (
id character varying NOT NULL,
user_id character varying NOT NULL,
active_expires bigint NOT NULL,
idle_expires bigint NOT NULL,
CONSTRAINT user_session_pkey PRIMARY KEY (id),
CONSTRAINT user_session_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.user(id)
);
CREATE TABLE public.user_story_completion (
id text NOT NULL,
user_id text NOT NULL,
story_id text NOT NULL,
completed_at bigint NOT NULL,
created_at bigint NOT NULL,
CONSTRAINT user_story_completion_pkey PRIMARY KEY (id),
CONSTRAINT user_story_completion_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.user(id)
);
CREATE TABLE public.user_topic_story (
id text NOT NULL,
user_id text NOT NULL,
topic_id text NOT NULL,
story_id text NOT NULL,
created_at bigint NOT NULL,
CONSTRAINT user_topic_story_pkey PRIMARY KEY (id),
CONSTRAINT user_topic_story_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.user(id)
);
CREATE TABLE public.video (
id text NOT NULL,
user_id text NOT NULL,
title text NOT NULL,
description text NOT NULL,
url text NOT NULL,
thumbnail_url text NOT NULL,
dialect text NOT NULL,
created_at text NOT NULL,
video_body text NOT NULL,
CONSTRAINT video_pkey PRIMARY KEY (id),
CONSTRAINT video_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.user(id)
);
CREATE TABLE public.word (
id text NOT NULL,
arabic_word text NOT NULL,
english_word text NOT NULL,
transliterated_word text NOT NULL,
dialect text NOT NULL,
category text NOT NULL,
audio_url text,
frequency integer,
source text NOT NULL DEFAULT 'api'::text,
created_at bigint NOT NULL DEFAULT EXTRACT(epoch FROM now()),
updated_at bigint NOT NULL DEFAULT EXTRACT(epoch FROM now()),
CONSTRAINT word_pkey PRIMARY KEY (id)
);
CREATE TABLE public.word_import_item (
id uuid NOT NULL DEFAULT gen_random_uuid(),
job_id uuid NOT NULL,
status text NOT NULL DEFAULT 'pending'::text,
row_data jsonb NOT NULL,
error_message text,
created_at timestamp with time zone DEFAULT now(),
CONSTRAINT word_import_item_pkey PRIMARY KEY (id),
CONSTRAINT word_import_item_job_id_fkey FOREIGN KEY (job_id) REFERENCES public.word_import_job(id)
);
CREATE TABLE public.word_import_job (
id uuid NOT NULL DEFAULT gen_random_uuid(),
user_id text NOT NULL,
status text NOT NULL DEFAULT 'pending'::text,
dialect text NOT NULL,
file_name text,
total_items integer NOT NULL DEFAULT 0,
processed_count integer NOT NULL DEFAULT 0,
imported_count integer NOT NULL DEFAULT 0,
skipped_count integer NOT NULL DEFAULT 0,
failed_count integer NOT NULL DEFAULT 0,
created_at timestamp with time zone DEFAULT now(),
updated_at timestamp with time zone DEFAULT now(),
CONSTRAINT word_import_job_pkey PRIMARY KEY (id)
);
CREATE TABLE public.word_of_the_day (
id uuid NOT NULL DEFAULT gen_random_uuid(),
arabic text NOT NULL,
transliteration text NOT NULL,
english text NOT NULL,
example_egyptian text,
example_levantine text,
example_darija text,
example_fusha text,
audio_url text,
display_date date NOT NULL,
created_at timestamp with time zone DEFAULT now(),
dialect text NOT NULL DEFAULT 'egyptian-arabic'::text CHECK (dialect = ANY (ARRAY['egyptian-arabic'::text, 'fusha'::text, 'levantine'::text, 'darija'::text])),
CONSTRAINT word_of_the_day_pkey PRIMARY KEY (id)
);
CREATE TABLE public.word_review (
id text NOT NULL,
saved_word_id text NOT NULL,
user_id text NOT NULL,
difficulty integer NOT NULL CHECK (difficulty >= 1 AND difficulty <= 3),
ease_factor real NOT NULL DEFAULT 2.5,
interval_days integer NOT NULL DEFAULT 0,
repetitions integer NOT NULL DEFAULT 0,
reviewed_at bigint NOT NULL,
next_review_date bigint NOT NULL,
created_at bigint NOT NULL,
dialect text,
CONSTRAINT word_review_pkey PRIMARY KEY (id),
CONSTRAINT word_review_saved_word_id_fkey FOREIGN KEY (saved_word_id) REFERENCES public.saved_word(id),
CONSTRAINT word_review_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.user(id)
);
CREATE TABLE public.youtube_shorts_cache (
id uuid NOT NULL DEFAULT gen_random_uuid(),
dialect text NOT NULL,
search_query text NOT NULL,
response jsonb NOT NULL,
next_page_token text,
created_at timestamp with time zone DEFAULT now(),
expires_at timestamp with time zone DEFAULT (now() + '06:00:00'::interval),
CONSTRAINT youtube_shorts_cache_pkey PRIMARY KEY (id)
);