1pub mod seed_accessibility_course;
2pub use seed_accessibility_course::seed_accessibility_course;
3pub mod seed_chatbot;
4pub mod seed_lock_chapter_course;
5pub use seed_lock_chapter_course::seed_lock_chapter_course;
6pub mod seed_material_reference_course;
7pub use seed_material_reference_course::seed_material_reference_course;
8pub mod seed_course_with_peer_review;
9pub mod seed_graded;
10pub use seed_graded::seed_graded_course;
11pub mod seed_glossary;
12pub mod seed_switching_course_instances_course;
13pub use seed_switching_course_instances_course::seed_switching_course_instances_course;
14
15use std::sync::Arc;
16
17use crate::domain::models_requests::{self, JwtKey};
18
19use crate::programs::seed::seed_helpers::{
20 ExampleExerciseFlexibleParams, create_best_exercise, create_best_peer_review, create_page,
21 example_exercise_flexible, paragraph, quizzes_exercise, submit_and_grade,
22};
23use anyhow::Result;
24use chrono::{TimeZone, Utc};
25
26use headless_lms_models::{
27 PKeyPolicy, certificate_configuration_to_requirements, certificate_configurations, chapters,
28 chapters::NewChapter,
29 course_instance_enrollments,
30 course_instance_enrollments::NewCourseInstanceEnrollment,
31 course_instances::{self, NewCourseInstance},
32 course_modules::{self, NewCourseModule},
33 courses::{self, NewCourse},
34 feedback,
35 feedback::{FeedbackBlock, NewFeedback},
36 file_uploads, glossary, library,
37 library::content_management::CreateNewCourseFixedIds,
38 page_history::HistoryChangeReason,
39 pages::CmsPageUpdate,
40 pages::{self, NewCoursePage},
41 peer_or_self_review_configs::PeerReviewProcessingStrategy::{
42 AutomaticallyGradeByAverage, AutomaticallyGradeOrManualReviewByAverage,
43 ManualReviewEverything,
44 },
45 proposed_block_edits::NewProposedBlockEdit,
46 proposed_page_edits,
47 proposed_page_edits::NewProposedPageEdits,
48 url_redirections, user_ai_usage_notice_acknowledgements,
49};
50use headless_lms_models::{certificate_configurations::DatabaseCertificateConfiguration, roles};
51use headless_lms_models::{
52 pages::PageUpdateArgs,
53 roles::{RoleDomain, UserRole},
54};
55use headless_lms_utils::{attributes, document_schema_processor::GutenbergBlock};
56
57use sqlx::{Pool, Postgres};
58use tracing::info;
59use uuid::Uuid;
60
61use super::{
62 seed_helpers::{CommonExerciseData, get_seed_spec_fetcher, heading},
63 seed_users::SeedUsersResult,
64};
65
66#[derive(Clone)]
67pub struct CommonCourseData {
68 pub db_pool: Pool<Postgres>,
69 pub organization_id: Uuid,
70 pub teacher_user_id: Uuid,
71 pub student_user_id: Uuid,
72 pub langs_user_id: Uuid,
73 pub example_normal_user_ids: Arc<Vec<Uuid>>,
74 pub jwt_key: Arc<JwtKey>,
75 pub base_url: String,
76}
77
78pub async fn seed_sample_course(
79 course_id: Uuid,
80 course_name: &str,
81 course_slug: &str,
82 common_course_data: CommonCourseData,
83 can_add_chatbot: bool,
84 seed_users_result: SeedUsersResult,
85) -> Result<Uuid> {
86 let CommonCourseData {
87 db_pool,
88 organization_id: org,
89 teacher_user_id,
90 student_user_id: student,
91 langs_user_id,
92 example_normal_user_ids: users,
93 jwt_key: _jwt_key,
94 base_url: _base_url,
95 } = common_course_data;
96 let spec_fetcher = get_seed_spec_fetcher();
97 info!("inserting sample course {}", course_name);
98 let mut conn = db_pool.acquire().await?;
99 let new_course = NewCourse {
100 name: course_name.to_string(),
101 organization_id: org,
102 slug: course_slug.to_string(),
103 language_code: "en".to_string(),
104 teacher_in_charge_name: "admin".to_string(),
105 teacher_in_charge_email: "admin@example.com".to_string(),
106 description: "Sample course.".to_string(),
107 is_draft: false,
108 is_test_mode: false,
109 is_unlisted: false,
110 copy_user_permissions: false,
111 is_joinable_by_code_only: false,
112 join_code: None,
113 ask_marketing_consent: false,
114 flagged_answers_threshold: Some(3),
115 can_add_chatbot,
116 };
117 let (course, _front_page, default_instance, default_module) =
118 library::content_management::create_new_course(
119 &mut conn,
120 PKeyPolicy::Fixed(CreateNewCourseFixedIds {
121 course_id,
122 default_course_instance_id: Uuid::new_v5(
123 &course_id,
124 b"7344f1c8-b7ce-4c7d-ade2-5f39997bd454",
125 ),
126 }),
127 new_course,
128 teacher_user_id,
129 &spec_fetcher,
130 models_requests::fetch_service_info,
131 )
132 .await?;
133 courses::set_cheater_detection_enabled(&mut conn, course.id, false).await?;
137 course_modules::update_enable_registering_completion_to_uh_open_university(
138 &mut conn,
139 default_module.id,
140 true,
141 )
142 .await?;
143 course_instances::insert(
144 &mut conn,
145 PKeyPolicy::Fixed(Uuid::new_v5(
146 &course_id,
147 b"67f077b4-0562-47ae-a2b9-db2f08f168a9",
148 )),
149 NewCourseInstance {
150 course_id: course.id,
151 name: Some("Non-default instance"),
152 description: Some("This is a non-default instance"),
153 support_email: Some("contact@example.com"),
154 teacher_in_charge_name: "admin",
155 teacher_in_charge_email: "admin@example.com",
156 opening_time: None,
157 closing_time: None,
158 },
159 )
160 .await?;
161
162 let new_chapter = NewChapter {
165 chapter_number: 1,
166 course_id: course.id,
167 front_page_id: None,
168 name: "The Basics".to_string(),
169 color: None,
170 opens_at: None,
171 deadline: Some(Utc.with_ymd_and_hms(2225, 1, 1, 23, 59, 59).unwrap()),
172 course_module_id: Some(default_module.id),
173 };
174 let (chapter_1, _front_page_1) = library::content_management::create_new_chapter(
175 &mut conn,
176 PKeyPolicy::Fixed((
177 Uuid::new_v5(&course_id, b"bfc557e1-0f8e-4f10-8e21-d7d8ffe50a3a"),
178 Uuid::new_v5(&course_id, b"b1e392db-482a-494e-9cbb-c87bbc70e340"),
179 )),
180 &new_chapter,
181 teacher_user_id,
182 &spec_fetcher,
183 models_requests::fetch_service_info,
184 )
185 .await?;
186 chapters::set_opens_at(&mut conn, chapter_1.id, Utc::now()).await?;
187 let new_chapter = NewChapter {
188 chapter_number: 2,
189 course_id: course.id,
190 front_page_id: None,
191 name: "The intermediaries".to_string(),
192 color: None,
193 opens_at: None,
194 deadline: None,
195 course_module_id: Some(default_module.id),
196 };
197 let (chapter_2, _front_page_2) = library::content_management::create_new_chapter(
198 &mut conn,
199 PKeyPolicy::Fixed((
200 Uuid::new_v5(&course_id, b"8d699f05-4318-47f7-b020-b2084128f746"),
201 Uuid::new_v5(&course_id, b"9734cb59-4c3c-467d-91e8-f4281baccfe5"),
202 )),
203 &new_chapter,
204 teacher_user_id,
205 &spec_fetcher,
206 models_requests::fetch_service_info,
207 )
208 .await?;
209 chapters::set_opens_at(
210 &mut conn,
211 chapter_2.id,
212 Utc::now() + chrono::Duration::minutes(10),
213 )
214 .await?;
215 let new_chapter = NewChapter {
216 chapter_number: 3,
217 course_id: course.id,
218 front_page_id: None,
219 name: "Advanced studies".to_string(),
220 color: None,
221 opens_at: None,
222 deadline: None,
223 course_module_id: Some(default_module.id),
224 };
225 let (chapter_3, _front_page_3) = library::content_management::create_new_chapter(
226 &mut conn,
227 PKeyPolicy::Fixed((
228 Uuid::new_v5(&course_id, b"791eada6-5299-41e9-b39c-da4f3c564814"),
229 Uuid::new_v5(&course_id, b"22cb6a59-9d9d-4a0b-945b-11a6f2f8d6ef"),
230 )),
231 &new_chapter,
232 teacher_user_id,
233 &spec_fetcher,
234 models_requests::fetch_service_info,
235 )
236 .await?;
237 chapters::set_opens_at(
238 &mut conn,
239 chapter_3.id,
240 Utc::now() + chrono::Duration::minutes(20),
241 )
242 .await?;
243 let new_chapter = NewChapter {
244 chapter_number: 4,
245 course_id: course.id,
246 front_page_id: None,
247 name: "Forbidden magicks".to_string(),
248 color: None,
249 opens_at: None,
250 deadline: None,
251 course_module_id: Some(default_module.id),
252 };
253 let (chapter_4, _front_page_4) = library::content_management::create_new_chapter(
254 &mut conn,
255 PKeyPolicy::Fixed((
256 Uuid::new_v5(&course_id, b"07f8ceea-d41e-4dcb-9e4b-f600d3894e7f"),
257 Uuid::new_v5(&course_id, b"cd7a35b7-8f16-4e86-bef2-b730943ec15b"),
258 )),
259 &new_chapter,
260 teacher_user_id,
261 &spec_fetcher,
262 models_requests::fetch_service_info,
263 )
264 .await?;
265 chapters::set_opens_at(
266 &mut conn,
267 chapter_4.id,
268 Utc::now() + (chrono::Duration::days(365) * 100),
269 )
270 .await?;
271
272 tracing::info!("inserting modules");
273 let second_module = course_modules::insert(
274 &mut conn,
275 PKeyPolicy::Generate,
276 &NewCourseModule::new(course.id, Some("Another module".to_string()), 1)
277 .set_ects_credits(Some(5.0)),
278 )
279 .await?;
280 let new_chapter = NewChapter {
281 chapter_number: 5,
282 course_id: course.id,
283 front_page_id: None,
284 name: "Another chapter".to_string(),
285 color: None,
286 opens_at: None,
287 deadline: None,
288 course_module_id: Some(second_module.id),
289 };
290 let (_m1_chapter_1, _m1c1_front_page) = library::content_management::create_new_chapter(
291 &mut conn,
292 PKeyPolicy::Fixed((
293 Uuid::new_v5(&course_id, b"c9003113-b69b-4ee7-8b13-e16397f1a3ea"),
294 Uuid::new_v5(&course_id, b"f95aa0bc-93d0-4d83-acde-64682f5e8f66"),
295 )),
296 &new_chapter,
297 teacher_user_id,
298 &spec_fetcher,
299 models_requests::fetch_service_info,
300 )
301 .await?;
302 let new_chapter = NewChapter {
303 chapter_number: 6,
304 course_id: course.id,
305 front_page_id: None,
306 name: "Another another chapter".to_string(),
307 color: None,
308 opens_at: None,
309 deadline: None,
310 course_module_id: Some(second_module.id),
311 };
312 let (_m1_chapter_2, _m1c2_front_page) = library::content_management::create_new_chapter(
313 &mut conn,
314 PKeyPolicy::Fixed((
315 Uuid::new_v5(&course_id, b"4989533a-7888-424c-963c-d8007d820fca"),
316 Uuid::new_v5(&course_id, b"e68b9d5b-fa2e-4a94-a1da-5d69f29dcb63"),
317 )),
318 &new_chapter,
319 teacher_user_id,
320 &spec_fetcher,
321 models_requests::fetch_service_info,
322 )
323 .await?;
324 let module = course_modules::insert(
325 &mut conn,
326 PKeyPolicy::Generate,
327 &NewCourseModule::new(course.id, Some("Bonus module".to_string()), 2)
328 .set_enable_registering_completion_to_uh_open_university(true),
329 )
330 .await?;
331 let new_chapter = NewChapter {
332 chapter_number: 7,
333 course_id: course.id,
334 front_page_id: None,
335 name: "Bonus chapter".to_string(),
336 color: None,
337 opens_at: None,
338 deadline: None,
339 course_module_id: Some(module.id),
340 };
341 let (_m2_chapter_1, _m2c1_front_page) = library::content_management::create_new_chapter(
342 &mut conn,
343 PKeyPolicy::Fixed((
344 Uuid::new_v5(&course_id, b"26b52b2f-8b02-4be8-b341-6e956ff3ca86"),
345 Uuid::new_v5(&course_id, b"0512fb7c-cb3f-4111-b663-e2fa7714939f"),
346 )),
347 &new_chapter,
348 teacher_user_id,
349 &spec_fetcher,
350 models_requests::fetch_service_info,
351 )
352 .await?;
353 let new_chapter = NewChapter {
354 chapter_number: 8,
355 course_id: course.id,
356 front_page_id: None,
357 name: "Another bonus chapter".to_string(),
358 color: None,
359 opens_at: None,
360 deadline: None,
361 course_module_id: Some(module.id),
362 };
363 let (_m2_chapter_2, _m2c2_front_page) = library::content_management::create_new_chapter(
364 &mut conn,
365 PKeyPolicy::Fixed((
366 Uuid::new_v5(&course_id, b"4e48b13a-9740-4d4f-9f60-8176649901b9"),
367 Uuid::new_v5(&course_id, b"bc6569fe-52d2-4590-aa3a-8ae80e961db8"),
368 )),
369 &new_chapter,
370 teacher_user_id,
371 &spec_fetcher,
372 models_requests::fetch_service_info,
373 )
374 .await?;
375
376 let welcome_page = NewCoursePage::new(
377 course.id,
378 1,
379 "/welcome",
380 "Welcome to Introduction to Everything",
381 );
382 let (_page, _) = pages::insert_course_page(&mut conn, &welcome_page, teacher_user_id).await?;
383 let hidden_page = welcome_page
384 .followed_by("/hidden", "Hidden Page")
385 .set_hidden(true)
386 .set_content(vec![GutenbergBlock::paragraph(
387 "You found the secret of the project 331!",
388 )]);
389 let (_page, _) = pages::insert_course_page(&mut conn, &hidden_page, teacher_user_id).await?;
390
391 info!("sample exercises");
392 let block_id_1 = Uuid::new_v5(&course_id, b"af3b467a-f5db-42ad-9b21-f42ca316b3c6");
393 let block_id_2 = Uuid::new_v5(&course_id, b"465f1f95-22a1-43e1-b4a3-7d18e525dc12");
394 let block_id_3 = Uuid::new_v5(&course_id, b"46aad5a8-71bd-49cd-8d86-3368ee8bb7ac");
395 let block_id_4 = Uuid::new_v5(&course_id, b"09b327a8-8e65-437e-9678-554fc4d98dd4");
396 let block_id_5 = Uuid::new_v5(&course_id, b"834648cc-72d9-42d1-bed7-cc6a2e186ae6");
397 let block_id_6 = Uuid::new_v5(&course_id, b"c7cb99a4-b2e8-45d8-b30a-2f32de3465c8");
398 let block_id_7 = Uuid::new_v5(&course_id, b"655dbafe-09ed-4f59-8184-159d0c2efd7c");
399 let block_id_8 = Uuid::new_v5(&course_id, b"3bce0ce2-5cfb-45a8-bc0e-af5f634d4d61");
400 let block_id_9 = Uuid::new_v5(&course_id, b"95cd9695-1406-446b-9412-3a1ee10a7927");
401 let exercise_1_id = Uuid::new_v5(&course_id, b"cfb950a7-db4e-49e4-8ec4-d7a32b691b08");
402 let exercise_1_slide_1_id = Uuid::new_v5(&course_id, b"182c4128-c4e4-40c9-bc5a-1265bfd3654c");
403 let exercise_1_slide_1_task_1_id =
404 Uuid::new_v5(&course_id, b"f73dab3b-3549-422d-8377-ece1972e5576");
405 let exercise_1_slide_1_task_1_spec_1_id =
406 Uuid::new_v5(&course_id, b"5f6b7850-5034-4cef-9dcf-e3fd4831067f");
407 let exercise_1_slide_1_task_1_spec_2_id =
408 Uuid::new_v5(&course_id, b"c713bbfc-86bf-4877-bd39-53afaf4444b5");
409 let exercise_1_slide_1_task_1_spec_3_id =
410 Uuid::new_v5(&course_id, b"4027d508-4fad-422e-bb7f-15c613a02cc6");
411
412 let (exercise_block_1, exercise_1, slide_1, task_1) = create_best_exercise(
413 block_id_3,
414 exercise_1_slide_1_task_1_spec_1_id,
415 exercise_1_slide_1_task_1_spec_2_id,
416 exercise_1_slide_1_task_1_spec_3_id,
417 Some("Best exercise".to_string()),
418 CommonExerciseData {
419 exercise_id: exercise_1_id,
420 exercise_slide_id: exercise_1_slide_1_id,
421 exercise_task_id: exercise_1_slide_1_task_1_id,
422 block_id: block_id_2,
423 },
424 );
425 let page_c1_1 = create_page(
426 &mut conn,
427 course.id,
428 teacher_user_id,
429 Some(chapter_1.id),
430 CmsPageUpdate {
431 url_path: "/chapter-1/page-1".to_string(),
432 title: "Page One".to_string(),
433 chapter_id: Some(chapter_1.id),
434 exercises: vec![exercise_1],
435 exercise_slides: vec![slide_1],
436 exercise_tasks: vec![task_1],
437 content: vec![
438 paragraph("Everything is a big topic.", block_id_1),
439 exercise_block_1,
440 paragraph("So big, that we need many paragraphs.", block_id_4),
441 paragraph("Like this.", block_id_5),
442 paragraph("The abacus is one of the oldest known calculating tools, with origins tracing back to ancient Mesopotamia and China. Often consisting of a wooden frame with rows of beads, it has been used for centuries as a reliable aid in performing arithmetic operations. Its simplicity and effectiveness made it a cornerstone of commerce and education across many civilizations.", block_id_6),
443
444 paragraph("Throughout history, the abacus has taken on various forms, from the Roman hand abacus to the Chinese suanpan and the Japanese soroban. Each design introduced unique innovations, optimizing calculation methods for their respective regions. Despite the rise of digital calculators, the abacus continues to be used in some educational settings to teach arithmetic concepts and mental math techniques.", block_id_7),
445
446 paragraph("Modern interest in the abacus has grown as educators recognize its value in developing number sense and concentration in children. Competitions in mental abacus calculation demonstrate just how powerful this tool can be when mastered. While it may seem outdated, the abacus remains a symbol of timeless ingenuity and practical problem-solving.", block_id_8),
447
448 paragraph("In recent years, digital adaptations of the abacus have also emerged, blending traditional methods with modern interfaces. These tools not only preserve the historical legacy of the abacus but also make it more accessible to new generations of learners. Whether used physically or virtually, the abacus continues to bridge the gap between tactile learning and abstract thinking.", block_id_9),
449 ],
450 },
451
452 )
453 .await?;
454
455 let exercise_2_id = Uuid::new_v5(&course_id, b"36e7f0c2-e663-4382-a503-081866cfe7d0");
456 let exercise_2_slide_1_id = Uuid::new_v5(&course_id, b"0d85864d-a20d-4d65-9ace-9b4d377f38e8");
457 let exercise_2_slide_1_task_1_id =
458 Uuid::new_v5(&course_id, b"e7fca192-2161-4ab8-8533-8c41dbaa2d69");
459 let exercise_2_slide_1_task_1_spec_1_id =
460 Uuid::new_v5(&course_id, b"5898293f-2d41-43b1-9e44-92d487196ade");
461 let exercise_2_slide_1_task_1_spec_2_id =
462 Uuid::new_v5(&course_id, b"93d27d79-f9a1-44ab-839f-484accc67e32");
463 let exercise_2_slide_1_task_1_spec_3_id =
464 Uuid::new_v5(&course_id, b"81ec2df2-a5fd-4d7d-b85f-0c304e8d2030");
465 let exercise_3_id = Uuid::new_v5(&course_id, b"64d273eb-628f-4d43-a11a-e69ebe244942");
466 let exercise_3_slide_1_id = Uuid::new_v5(&course_id, b"5441c7c0-60f1-4058-8223-7090c9cac7cb");
467 let exercise_3_slide_1_task_1_id =
468 Uuid::new_v5(&course_id, b"114caac5-006a-4afb-9806-785154263c11");
469 let exercise_3_slide_1_task_1_spec_1_id =
470 Uuid::new_v5(&course_id, b"28ea3062-bd6a-45f5-9844-03174e00a0a8");
471 let exercise_3_slide_1_task_1_spec_2_id =
472 Uuid::new_v5(&course_id, b"1982f566-2d6a-485d-acb0-65d8b8864c7e");
473 let exercise_3_slide_1_task_1_spec_3_id =
474 Uuid::new_v5(&course_id, b"01ec5329-2cf6-4d0f-92b2-d388360fb402");
475 let exercise_4_id = Uuid::new_v5(&course_id, b"029688ec-c7be-4cb3-8928-85cfd6551083");
476 let exercise_4_slide_1_id = Uuid::new_v5(&course_id, b"ab8a314b-ac03-497b-8ade-3d8512ed00c9");
477 let exercise_4_slide_1_task_1_id =
478 Uuid::new_v5(&course_id, b"382fffce-f177-47d0-a5c0-cc8906d34c49");
479 let exercise_4_slide_1_task_1_spec_1_id =
480 Uuid::new_v5(&course_id, b"4bae54a3-d67c-428b-8996-290f70ae08fa");
481 let exercise_4_slide_1_task_1_spec_2_id =
482 Uuid::new_v5(&course_id, b"c3f257c0-bdc2-4d81-99ff-a71c76fe670a");
483 let exercise_4_slide_1_task_1_spec_3_id =
484 Uuid::new_v5(&course_id, b"fca5a8ba-50e0-4375-8d4b-9d02762d908c");
485 let (exercise_block_2, exercise_2, slide_2, task_2) = create_best_exercise(
486 Uuid::new_v5(&course_id, b"c0986981-c8ae-4c0b-b558-1163a16760ec"),
487 exercise_2_slide_1_task_1_spec_1_id,
488 exercise_2_slide_1_task_1_spec_2_id,
489 exercise_2_slide_1_task_1_spec_3_id,
490 Some("Best exercise".to_string()),
491 CommonExerciseData {
492 exercise_id: exercise_2_id,
493 exercise_slide_id: exercise_2_slide_1_id,
494 exercise_task_id: exercise_2_slide_1_task_1_id,
495 block_id: Uuid::new_v5(&course_id, b"2dbb4649-bcac-47ab-a817-ca17dcd70378"),
496 },
497 );
498 let (exercise_block_3, exercise_3, slide_3, task_3) = create_best_exercise(
499 Uuid::new_v5(&course_id, b"c0986981-c8ae-4c0b-b558-1163a16760ec"),
500 exercise_3_slide_1_task_1_spec_1_id,
501 exercise_3_slide_1_task_1_spec_2_id,
502 exercise_3_slide_1_task_1_spec_3_id,
503 Some("Best exercise".to_string()),
504 CommonExerciseData {
505 exercise_id: exercise_3_id,
506 exercise_slide_id: exercise_3_slide_1_id,
507 exercise_task_id: exercise_3_slide_1_task_1_id,
508 block_id: Uuid::new_v5(&course_id, b"fb26489d-ca49-4f76-a1c2-f759ed3146c0"),
509 },
510 );
511 let (exercise_block_4, exercise_4, slide_4, task_4_1) = create_best_exercise(
512 Uuid::new_v5(&course_id, b"389e80bd-5f91-40c7-94ff-7dda1eeb96fb"),
513 exercise_4_slide_1_task_1_spec_1_id,
514 exercise_4_slide_1_task_1_spec_2_id,
515 exercise_4_slide_1_task_1_spec_3_id,
516 Some("Best exercise".to_string()),
517 CommonExerciseData {
518 exercise_id: exercise_4_id,
519 exercise_slide_id: exercise_4_slide_1_id,
520 exercise_task_id: exercise_4_slide_1_task_1_id,
521 block_id: Uuid::new_v5(&course_id, b"334593ad-8ba5-4589-b1f7-b159e754bdc5"),
522 },
523 );
524
525 let page2_id = create_page(
526 &mut conn,
527 course.id,
528 teacher_user_id,
529 Some(chapter_1.id),
530 CmsPageUpdate {
531 url_path: "/chapter-1/page-2".to_string(),
532 title: "Page 2".to_string(),
533 chapter_id: Some(chapter_1.id),
534 exercises: vec![exercise_2, exercise_3, exercise_4],
535 exercise_slides: vec![slide_2, slide_3, slide_4],
536 exercise_tasks: vec![task_2, task_3, task_4_1],
537 content: vec![
538 paragraph(
539 "First chapters second page.",
540 Uuid::new_v5(&course_id, b"9faf5a2d-f60d-4a70-af3d-0e7e3d6fe273"),
541 ),
542 exercise_block_2,
543 exercise_block_3,
544 exercise_block_4,
545 ],
546 },
547 )
548 .await?;
549
550 url_redirections::upsert(
551 &mut conn,
552 PKeyPolicy::Generate,
553 page2_id,
554 "/old-url",
555 course.id,
556 )
557 .await?;
558
559 let (
560 quizzes_exercise_block_1,
561 quizzes_exercise_1,
562 quizzes_exercise_slide_1,
563 quizzes_exercise_task_1,
564 ) = quizzes_exercise(
565 "Best quizzes exercise".to_string(),
566 Uuid::new_v5(&course_id, b"f6f63ff0-c119-4141-922b-bc04cbfa0a31"),
567 true,
568 serde_json::json!({
569 "id": "a2704a2b-fe3d-4945-a007-5593e4b81195",
570 "body": "very hard",
571 "open": "2021-12-17T07:15:33.479Z",
572 "part": 0,
573 "items": [{
574 "id": "c449acf6-094e-494e-aef4-f5dfa51729ae",
575 "body": "",
576 "type": "essay",
577 "multi": false,
578 "multipleChoiceMultipleOptionsGradingPolicy": "default",
579 "order": 0,
580 "title": "write an essay",
581 "quizId": "a2704a2b-fe3d-4945-a007-5593e4b81195",
582 "options": [],
583 "maxValue": null,
584 "maxWords": 500,
585 "minValue": null,
586 "minWords": 10,
587 "createdAt": "2021-12-17T07:16:23.202Z",
588 "direction": "row",
589 "updatedAt": "2021-12-17T07:16:23.202Z",
590 "formatRegex": null,
591 "validityRegex": null,
592 "failureMessage": null,
593 "successMessage": null,
594 "allAnswersCorrect": false,
595 "sharedOptionFeedbackMessage": null,
596 "usesSharedOptionFeedbackMessage": false
597 }],
598 "title": "Pretty good exercise",
599 "tries": 1,
600 "points": 2,
601 "section": 0,
602 "courseId": "1dbd4a71-5f4c-49c9-b8a0-2e65fb8c4e0c",
603 "deadline": "3125-12-17T07:15:33.479Z",
604 "createdAt": "2021-12-17T07:15:33.479Z",
605 "updatedAt": "2021-12-17T07:15:33.479Z",
606 "autoReject": false,
607 "autoConfirm": true,
608 "triesLimited": true,
609 "submitMessage": "This is an extra submit message from the teacher.",
610 "excludedFromScore": true,
611 "grantPointsPolicy": "grant_whenever_possible",
612 "awardPointsEvenIfWrong": false}),
613 Some(Utc.with_ymd_and_hms(2125, 1, 1, 23, 59, 59).unwrap()),
614 CommonExerciseData {
615 exercise_id: Uuid::new_v5(&course_id, b"a6ee42d0-2200-43b7-9981-620753a9b5c0"),
616 exercise_slide_id: Uuid::new_v5(&course_id, b"8d01d9b3-87d1-4e24-bee2-2726d3853ec6"),
617 exercise_task_id: Uuid::new_v5(&course_id, b"00dd984d-8651-404e-80b8-30fae9cf32ed"),
618 block_id: Uuid::new_v5(&course_id, b"a66c2552-8123-4287-bd8b-b49a29204870"),
619 },
620 );
621
622 let (
623 quizzes_exercise_block_2,
624 quizzes_exercise_2,
625 quizzes_exercise_slide_2,
626 quizzes_exercise_task_2,
627 ) = quizzes_exercise(
628 "Best quizzes exercise".to_string(),
629 Uuid::new_v5(&course_id, b"1057f91c-9dac-4364-9d6a-fa416abc540b"),
630 false,
631 serde_json::json!({
632 "id": "1e2bb795-1736-4b37-ae44-b16ca59b4e4f",
633 "body": "very hard",
634 "open": "2021-12-17T07:15:33.479Z",
635 "part": 0,
636 "items": [{
637 "id": "d81a81f2-5e44-48c5-ab6d-f724af8a23f2",
638 "body": "",
639 "type": "open",
640 "multi": false,
641 "multipleChoiceMultipleOptionsGradingPolicy": "default",
642 "order": 0,
643 "title": "When you started studying at the uni? Give the date in yyyy-mm-dd format.",
644 "quizId": "690c69e2-9275-4cfa-aba4-63ac917e59f6",
645 "options": [],
646 "maxValue": null,
647 "maxWords": null,
648 "minValue": null,
649 "minWords": null,
650 "createdAt": "2021-12-17T07:16:23.202Z",
651 "direction": "row",
652 "updatedAt": "2021-12-17T07:16:23.202Z",
653 "formatRegex": null,
654 "validityRegex": r"^\d{4}\-(0[1-9]|1[012])\-(0[1-9]|[12][0-9]|3[01])$".to_string(),
655 "failureMessage": "Oh no! Your answer is not in yyyy-mm-dd format :(".to_string(),
656 "successMessage": "Gongrats! your answer is in yyyy-mm-dd format!".to_string(),
657 "allAnswersCorrect": false,
658 "sharedOptionFeedbackMessage": null,
659 "usesSharedOptionFeedbackMessage": false
660 }],
661 "title": "Pretty good exercise",
662 "tries": 1,
663 "points": 2,
664 "section": 0,
665 "courseId": "39c7879a-e61f-474a-8f18-7fc476ccc3a0",
666 "deadline": "2021-12-17T07:15:33.479Z",
667 "createdAt": "2021-12-17T07:15:33.479Z",
668 "updatedAt": "2021-12-17T07:15:33.479Z",
669 "autoReject": false,
670 "autoConfirm": true,
671 "randomizeOptions": false,
672 "triesLimited": true,
673 "submitMessage": "This is an extra submit message from the teacher.",
674 "excludedFromScore": true,
675 "grantPointsPolicy": "grant_whenever_possible",
676 "awardPointsEvenIfWrong": false}),
677 Some(Utc.with_ymd_and_hms(2125, 1, 1, 23, 59, 59).unwrap()),
678 CommonExerciseData {
679 exercise_id: Uuid::new_v5(&course_id, b"949b548f-a87f-4dc6-aafc-9f1e1abe34a7"),
680 exercise_slide_id: Uuid::new_v5(&course_id, b"39c36d3f-017e-4c36-a97e-908e25b3678b"),
681 exercise_task_id: Uuid::new_v5(&course_id, b"8ae8971c-95dd-4d8c-b38f-152ad89c6b20"),
682 block_id: Uuid::new_v5(&course_id, b"d05b1d9b-f270-4e5e-baeb-a904ea29dc90"),
683 },
684 );
685
686 let (
687 quizzes_exercise_block_3,
688 quizzes_exercise_3,
689 quizzes_exercise_slide_3,
690 quizzes_exercise_task_3,
691 ) = quizzes_exercise(
692 "Best quizzes exercise".to_string(),
693 Uuid::new_v5(&course_id, b"8845b17e-2320-4384-97f8-24e42457cb5e"),
694 false,
695 serde_json::json!({
696 "id": "f1f0520e-3037-409c-b52d-163ad0bc5c59",
697 "body": "very hard",
698 "open": "2021-12-17T07:15:33.479Z",
699 "part": 0,
700 "items": [{
701 "id": "f8cff916-da28-40ab-9e8b-f523e661ddb6",
702 "body": "",
703 "type": "multiple-choice-dropdown",
704 "multi": false,
705 "multipleChoiceMultipleOptionsGradingPolicy": "default",
706 "order": 0,
707 "title": "Choose the right answer from given options.",
708 "quizId": "f1f0520e-3037-409c-b52d-163ad0bc5c59",
709 "options": [{
710 "id": "86a2d838-04aa-4b1c-8115-2c15ed19e7b3",
711 "body": null,
712 "order": 1,
713 "title": "The right answer",
714 "quizItemId": "f8cff916-da28-40ab-9e8b-f523e661ddb6",
715 "correct":true,
716 "messageAfterSubmissionWhenSelected": "You chose wisely...",
717 "additionalCorrectnessExplanationOnModelSolution": null,
718 },
719 {
720 "id": "fef8cd36-04ab-48f2-861c-51769ccad52f",
721 "body": null,
722 "order": 2,
723 "title": "The Wright answer",
724 "quizItemId": "f8cff916-da28-40ab-9e8b-f523e661ddb6",
725 "correct":false,
726 "messageAfterSubmissionWhenSelected": "You chose poorly...",
727 "additionalCorrectnessExplanationOnModelSolution": null,
728 }],
729 "maxValue": null,
730 "maxWords": null,
731 "minValue": null,
732 "minWords": null,
733 "createdAt": "2021-12-17T07:16:23.202Z",
734 "direction": "row",
735 "updatedAt": "2021-12-17T07:16:23.202Z",
736 "formatRegex": null,
737 "validityRegex": null,
738 "messageAfterSubmissionWhenSelected": null,
739 "additionalCorrectnessExplanationOnModelSolution": null,
740 "allAnswersCorrect": false,
741 "sharedOptionFeedbackMessage": null,
742 "usesSharedOptionFeedbackMessage": false
743 }],
744 "title": "Pretty good exercise",
745 "tries": 1,
746 "points": 2,
747 "section": 0,
748 "courseId": "39c7879a-e61f-474a-8f18-7fc476ccc3a0",
749 "deadline": "2021-12-17T07:15:33.479Z",
750 "createdAt": "2021-12-17T07:15:33.479Z",
751 "updatedAt": "2021-12-17T07:15:33.479Z",
752 "autoReject": false,
753 "autoConfirm": true,
754 "randomizeOptions": false,
755 "triesLimited": true,
756 "submitMessage": "This is an extra submit message from the teacher.",
757 "excludedFromScore": true,
758 "grantPointsPolicy": "grant_whenever_possible",
759 "awardPointsEvenIfWrong": false}),
760 Some(Utc.with_ymd_and_hms(2125, 1, 1, 23, 59, 59).unwrap()),
761 CommonExerciseData {
762 exercise_id: Uuid::new_v5(&course_id, b"9bcf634d-584c-4fef-892c-3c0e97dab1d5"),
763 exercise_slide_id: Uuid::new_v5(&course_id, b"984457f6-bc9b-4604-b54c-80fb4adfab76"),
764 exercise_task_id: Uuid::new_v5(&course_id, b"e4230b3a-1db8-49c4-9554-1f96f7f3d015"),
765 block_id: Uuid::new_v5(&course_id, b"52939561-af36-4ab6-bffa-be97e94d3314"),
766 },
767 );
768
769 let (
770 quizzes_exercise_block_4,
771 quizzes_exercise_4,
772 quizzes_exercise_slide_4,
773 quizzes_exercise_task_4,
774 ) = quizzes_exercise(
775 "Best quizzes exercise".to_string(),
776 Uuid::new_v5(&course_id, b"7ca39a36-2dcd-4521-bbf6-bfc5849874e3"),
777 false,
778 serde_json::json!({
779 "version": "2",
780 "title": "",
781 "body": "very hard",
782 "awardPointsEvenIfWrong": false,
783 "grantPointsPolicy": "grant_whenever_possible",
784 "quizItemDisplayDirection": "vertical",
785 "submitMessage": "This is an extra submit message from the teacher.",
786 "items": [
787 {
788 "type": "choose-n",
789 "id": "663c52bd-f649-4ba2-9c39-2387c386cbf1",
790 "failureMessage": "",
791 "options": [
792 {
793 "order": 1,
794 "additionalCorrectnessExplanationOnModelSolution": "",
795 "body": "",
796 "correct": true,
797 "id": "9339c966-cc48-4a6c-9512-b38c82240dd0",
798 "messageAfterSubmissionWhenSelected": "Java is a programming language",
799 "title": "Java"
800 },
801 {
802 "order": 2,
803 "additionalCorrectnessExplanationOnModelSolution": "",
804 "body": "",
805 "correct": true,
806 "id": "2e6de165-ea76-4f03-a216-2f15179c9e6e",
807 "messageAfterSubmissionWhenSelected": "Erlang is a programming language",
808 "title": "Erlang"
809 },
810 {
811 "order": 3,
812 "additionalCorrectnessExplanationOnModelSolution": "",
813 "body": "",
814 "correct": false,
815 "id": "2d452914-8cf7-426c-b130-51d556a33566",
816 "messageAfterSubmissionWhenSelected": "Jupiter is not a programming language",
817 "title": "Jupiter"
818 },
819 {
820 "order": 4,
821 "additionalCorrectnessExplanationOnModelSolution": "",
822 "body": "",
823 "correct": true,
824 "id": "d503894c-3eaf-4ebe-a7d5-95f04b641479",
825 "messageAfterSubmissionWhenSelected": "Rust is a programming language",
826 "title": "Rust"
827 },
828 {
829 "order": 5,
830 "additionalCorrectnessExplanationOnModelSolution": "",
831 "body": "",
832 "correct": false,
833 "id": "a5a6cef2-df55-4926-9ecc-95da3e049ea7",
834 "messageAfterSubmissionWhenSelected": "AC is not a programming language",
835 "title": "AC"
836 }
837 ],
838 "order": 0,
839 "successMessage": "",
840 "title": "Pick all the programming languages from below",
841 "body": "",
842 "n": 2
843 }
844 ]
845 }),
846 Some(Utc.with_ymd_and_hms(2125, 1, 1, 23, 59, 59).unwrap()),
847 CommonExerciseData {
848 exercise_id: Uuid::new_v5(&course_id, b"854a4e05-6575-4d27-8feb-6ee01f662d8a"),
849 exercise_slide_id: Uuid::new_v5(&course_id, b"6a8e65be-f5cd-4c87-b4f9-9522cb37bbcb"),
850 exercise_task_id: Uuid::new_v5(&course_id, b"b5e1e7e87-0678-4296-acf7-a8ac926ff94b"),
851 block_id: Uuid::new_v5(&course_id, b"50e26d7f-f11f-4a8a-990d-fb17c3371d1d"),
852 },
853 );
854
855 let (
856 quizzes_exercise_block_5,
857 quizzes_exercise_5,
858 quizzes_exercise_slide_5,
859 quizzes_exercise_task_5,
860 ) = quizzes_exercise(
861 "Best quizzes exercise".to_string(),
862 Uuid::new_v5(&course.id, b"b2f7d8d5-f3c0-4cac-8eb7-89a7b88c2236"),
863 false,
864 serde_json::json!({
865 "autoConfirm": true,
866 "randomizeOptions": false,
867 "autoReject": false,
868 "awardPointsEvenIfWrong": false,
869 "body": "",
870 "courseId": "29b09b7e-337f-4074-b14b-6109427a52f6",
871 "createdAt": "2022-05-04T09:03:06.271Z",
872 "deadline": "2022-05-04T09:03:06.271Z",
873 "excludedFromScore": true,
874 "grantPointsPolicy": "grant_whenever_possible",
875 "id": "72c3bb44-1695-4ea0-af3e-f2280c726551",
876 "items": [
877 {
878 "allAnswersCorrect": false,
879 "body": "",
880 "createdAt": "2022-05-04T09:03:09.167Z",
881 "direction": "column",
882 "failureMessage": null,
883 "formatRegex": null,
884 "id": "105270c8-e94a-40ec-a159-8fe38f116bb4",
885 "maxValue": null,
886 "maxWords": null,
887 "minValue": null,
888 "minWords": null,
889 "multi": false,
890 "optionCells": null,
891 "options": [],
892 "order": 0,
893 "quizId": "72c3bb44-1695-4ea0-af3e-f2280c726551",
894 "sharedOptionFeedbackMessage": null,
895 "successMessage": null,
896 "timelineItems": [
897 {
898 "correctEventId": "59e30264-fb11-4e44-a91e-1c5cf80fd977",
899 "correctEventName": "Finland joins the European Union",
900 "id": "c40fc487-9cb9-4007-80d3-8ffd7a8dc799",
901 "year": "1995"
902 },
903 {
904 "correctEventId": "0ee17a8e-6d51-4620-b355-90815462543f",
905 "correctEventName": "Finland switches their currency to Euro",
906 "id": "d63fd98e-b73c-47cf-a634-9046249c78e4",
907 "year": "2002"
908 },
909 {
910 "correctEventId": "0a59d2d3-6cf6-4b91-b1bd-873eefde78ac",
911 "correctEventName": "Finland joins the Economic and Monetary Union of the European Union",
912 "id": "50d7641c-382e-4805-95d8-e873c462bc48",
913 "year": "1998"
914 }
915 ],
916 "title": "",
917 "type": "timeline",
918 "updatedAt": "2022-05-04T09:03:09.167Z",
919 "usesSharedOptionFeedbackMessage": false,
920 "validityRegex": null
921 }
922 ],
923 "open": "2022-05-04T09:03:06.271Z",
924 "part": 0,
925 "points": 0,
926 "section": 0,
927 "submitMessage": "This is an extra submit message from the teacher.",
928 "title": "",
929 "tries": 1,
930 "triesLimited": true,
931 "updatedAt": "2022-05-04T09:03:06.271Z"
932 }),
933 Some(Utc.with_ymd_and_hms(2125, 1, 1, 23, 59, 59).unwrap()),
934 CommonExerciseData {
935 exercise_id: Uuid::new_v5(&course.id, b"981623c8-baa3-4d14-bb8a-963e167da9ca"),
936 exercise_slide_id: Uuid::new_v5(&course.id, b"b1a6d7e4-00b2-43fb-bf39-863f4ef49d09"),
937 exercise_task_id: Uuid::new_v5(&course.id, b"1a2f2c9f-9552-440e-8dd3-1e3703bd0fab"),
938 block_id: Uuid::new_v5(&course.id, b"6b568812-f752-4d9f-a60a-48257822d21e"),
939 },
940 );
941
942 let (
943 quizzes_exercise_block_6,
944 quizzes_exercise_6,
945 quizzes_exercise_slide_6,
946 quizzes_exercise_task_6,
947 ) = quizzes_exercise(
948 "Multiple choice with feedback".to_string(),
949 Uuid::new_v5(&course.id, b"664ea614-4af4-4ad0-9855-eae1881568e6"),
950 false,
951 serde_json::from_str(include_str!(
952 "../../../assets/quizzes-multiple-choice-feedback.json"
953 ))?,
954 Some(Utc.with_ymd_and_hms(2125, 1, 1, 23, 59, 59).unwrap()),
955 CommonExerciseData {
956 exercise_id: Uuid::new_v5(&course.id, b"f7fa3a08-e287-44de-aea8-32133af89d31"),
957 exercise_slide_id: Uuid::new_v5(&course.id, b"31820133-579a-4d9f-8b0c-2120f76d1390"),
958 exercise_task_id: Uuid::new_v5(&course.id, b"55f929c7-30ab-441d-a0ad-6cd115857b3b"),
959 block_id: Uuid::new_v5(&course.id, b"d7a91d07-9bd9-449c-9862-fbacb0b402b0"),
960 },
961 );
962
963 let (
964 quizzes_exercise_block_7,
965 quizzes_exercise_7,
966 quizzes_exercise_slide_7,
967 quizzes_exercise_task_7,
968 ) = quizzes_exercise(
969 "Scale".to_string(),
970 Uuid::new_v5(&course.id, b"05fa1188-4653-4904-bf1c-a93363225841"),
971 false,
972 serde_json::from_str(include_str!("../../../assets/scale.json"))?,
973 Some(Utc.with_ymd_and_hms(2125, 1, 1, 23, 59, 59).unwrap()),
974 CommonExerciseData {
975 exercise_id: Uuid::new_v5(&course.id, b"212132eb-b108-4027-b312-2275cf0b7473"),
976 exercise_slide_id: Uuid::new_v5(&course.id, b"6172a36a-b65d-463c-81d0-7f7fce07615c"),
977 exercise_task_id: Uuid::new_v5(&course.id, b"0dcfc4ca-c2f7-40b0-8654-14c6893a1fd9"),
978 block_id: Uuid::new_v5(&course.id, b"b64d7bd2-a216-494e-a23c-7a975fb1a415"),
979 },
980 );
981
982 let (
983 quizzes_exercise_block_8,
984 quizzes_exercise_8,
985 quizzes_exercise_slide_8,
986 quizzes_exercise_task_8,
987 ) = quizzes_exercise(
988 "Vector exercise".to_string(),
989 Uuid::new_v5(&course.id, b"0c271345-6934-4489-8164-2cc4dc8974bb"),
990 false,
991 serde_json::from_str(include_str!("../../../assets/vector-exercise.json"))?,
992 None,
993 CommonExerciseData {
994 exercise_id: Uuid::new_v5(&course.id, b"80373dc3-ceba-45b4-a114-161d60228c0c"),
995 exercise_slide_id: Uuid::new_v5(&course.id, b"08f0da90-9080-4cdd-adc7-66173cd5b833"),
996 exercise_task_id: Uuid::new_v5(&course.id, b"ea24c875-1a3c-403e-8272-b1249a475c89"),
997 block_id: Uuid::new_v5(&course.id, b"38ed716f-5d4f-4ddd-9f5a-700ef124b934"),
998 },
999 );
1000
1001 let page_3 = create_page(
1002 &mut conn,
1003 course.id,
1004 teacher_user_id,
1005 Some(chapter_1.id),
1006 CmsPageUpdate {
1007 url_path: "/chapter-1/page-3".to_string(),
1008 title: "Page 3".to_string(),
1009 chapter_id: Some(chapter_1.id),
1010 exercises: vec![quizzes_exercise_1],
1011 exercise_slides: vec![quizzes_exercise_slide_1],
1012 exercise_tasks: vec![quizzes_exercise_task_1],
1013 content: vec![
1014 paragraph(
1015 "First chapters essay page.",
1016 Uuid::new_v5(&course_id, b"6e4ab83a-2ae8-4bd2-a6ea-0e0d1eeabe23"),
1017 ),
1018 quizzes_exercise_block_1,
1019 ],
1020 },
1021 )
1022 .await?;
1023
1024 create_page(
1025 &mut conn,
1026 course.id,
1027 teacher_user_id,
1028 Some(chapter_1.id),
1029 CmsPageUpdate {
1030 url_path: "/chapter-1/page-4".to_string(),
1031 title: "Page 4".to_string(),
1032 chapter_id: Some(chapter_1.id),
1033 exercises: vec![quizzes_exercise_2],
1034 exercise_slides: vec![quizzes_exercise_slide_2],
1035 exercise_tasks: vec![quizzes_exercise_task_2],
1036 content: vec![
1037 paragraph(
1038 "First chapters open page.",
1039 Uuid::new_v5(&course_id, b"771b9c61-dbc9-4266-a980-dadc853455c9"),
1040 ),
1041 quizzes_exercise_block_2,
1042 ],
1043 },
1044 )
1045 .await?;
1046
1047 create_page(
1048 &mut conn,
1049 course.id,
1050 teacher_user_id,
1051 Some(chapter_1.id),
1052 CmsPageUpdate {
1053 url_path: "/chapter-1/page-5".to_string(),
1054 title: "Page 5".to_string(),
1055 chapter_id: Some(chapter_1.id),
1056 exercises: vec![quizzes_exercise_3],
1057 exercise_slides: vec![quizzes_exercise_slide_3],
1058 exercise_tasks: vec![quizzes_exercise_task_3],
1059 content: vec![
1060 paragraph(
1061 "First chapters multiple-choice-dropdown page",
1062 Uuid::new_v5(&course_id, b"7af470e7-cc4f-411e-ad5d-c137e353f7c3"),
1063 ),
1064 quizzes_exercise_block_3,
1065 ],
1066 },
1067 )
1068 .await?;
1069
1070 create_page(
1071 &mut conn,
1072 course.id,
1073 teacher_user_id,
1074 Some(chapter_1.id),
1075 CmsPageUpdate {
1076 url_path: "/chapter-1/page-6".to_string(),
1077 title: "Page 6".to_string(),
1078 chapter_id: Some(chapter_1.id),
1079 exercises: vec![quizzes_exercise_4],
1080 exercise_slides: vec![quizzes_exercise_slide_4],
1081 exercise_tasks: vec![quizzes_exercise_task_4],
1082 content: vec![
1083 paragraph(
1084 "First chapters multiple-choice clickable page.",
1085 Uuid::new_v5(&course_id, b"6b7775c3-b46e-41e5-a730-0a2c2f0ba148"),
1086 ),
1087 quizzes_exercise_block_4,
1088 ],
1089 },
1090 )
1091 .await?;
1092
1093 create_page(
1094 &mut conn,
1095 course.id,
1096 teacher_user_id,
1097 Some(chapter_1.id),
1098 CmsPageUpdate {
1099 url_path: "/chapter-1/the-timeline".to_string(),
1100 title: "The timeline".to_string(),
1101 chapter_id: Some(chapter_2.id),
1102 exercises: vec![quizzes_exercise_5],
1103 exercise_slides: vec![quizzes_exercise_slide_5],
1104 exercise_tasks: vec![quizzes_exercise_task_5],
1105 content: vec![
1106 paragraph(
1107 "Best page",
1108 Uuid::new_v5(&course.id, b"891de1ca-f3a9-506f-a268-3477ea4fdd27"),
1109 ),
1110 quizzes_exercise_block_5,
1111 ],
1112 },
1113 )
1114 .await?;
1115
1116 create_page(
1117 &mut conn,
1118 course.id,
1119 teacher_user_id,
1120 Some(chapter_1.id),
1121 CmsPageUpdate {
1122 url_path: "/chapter-1/scale".to_string(),
1123 title: "scale".to_string(),
1124 chapter_id: Some(chapter_1.id),
1125 exercises: vec![quizzes_exercise_7],
1126 exercise_slides: vec![quizzes_exercise_slide_7],
1127 exercise_tasks: vec![quizzes_exercise_task_7],
1128 content: vec![
1129 paragraph(
1130 "The page for the scale execise.",
1131 Uuid::new_v5(&course_id, b"53f68082-c417-4d38-99ad-40b6a30b2da4"),
1132 ),
1133 quizzes_exercise_block_7,
1134 ],
1135 },
1136 )
1137 .await?;
1138
1139 create_page(
1140 &mut conn,
1141 course.id,
1142 teacher_user_id,
1143 Some(chapter_1.id),
1144 CmsPageUpdate {
1145 url_path: "/chapter-1/the-multiple-choice-with-feedback".to_string(),
1146 title: "Multiple choice with feedback".to_string(),
1147 chapter_id: Some(chapter_1.id),
1148 exercises: vec![quizzes_exercise_6],
1149 exercise_slides: vec![quizzes_exercise_slide_6],
1150 exercise_tasks: vec![quizzes_exercise_task_6],
1151 content: vec![
1152 paragraph(
1153 "Something about rust and feedback.",
1154 Uuid::new_v5(&course_id, b"cbb87878-5af1-4c01-b343-97bf668b8034"),
1155 ),
1156 quizzes_exercise_block_6,
1157 ],
1158 },
1159 )
1160 .await?;
1161
1162 create_page(
1163 &mut conn,
1164 course.id,
1165 teacher_user_id,
1166 Some(chapter_1.id),
1167 CmsPageUpdate {
1168 url_path: "/chapter-1/vector".to_string(),
1169 title: "Vector".to_string(),
1170 chapter_id: Some(chapter_1.id),
1171 exercises: vec![quizzes_exercise_8],
1172 exercise_slides: vec![quizzes_exercise_slide_8],
1173 exercise_tasks: vec![quizzes_exercise_task_8],
1174 content: vec![
1175 paragraph(
1176 "This page has a vector exercise composed of three close-ended questions.",
1177 Uuid::new_v5(&course_id, b"53f68082-c417-4d38-99ad-40b6a30b2da4"),
1178 ),
1179 quizzes_exercise_block_8,
1180 ],
1181 },
1182 )
1183 .await?;
1184
1185 let multi_exercise_1_id = Uuid::new_v5(&course_id, b"3abe8579-73f1-4cdf-aba0-3e123fcedaea");
1186 let multi_exercise_1_slide_1_id =
1187 Uuid::new_v5(&course_id, b"efc7663c-b0fd-4e21-893a-7b7891191e07");
1188 let multi_exercise_1_slide_1_task_1_id =
1189 Uuid::new_v5(&course_id, b"b8833157-aa58-4472-a09b-98406a82ef42");
1190 let multi_exercise_1_slide_1_task_2_id =
1191 Uuid::new_v5(&course_id, b"36921424-0a65-4de8-8f92-3be96d695463");
1192 let multi_exercise_1_slide_1_task_3_id =
1193 Uuid::new_v5(&course_id, b"4c4bc8e5-7108-4f0d-a3d9-54383aa57269");
1194 let (multi_exercise_block_1, multi_exercise_1, multi_exercise_1_slides, multi_exercise_1_tasks) =
1195 example_exercise_flexible(ExampleExerciseFlexibleParams {
1196 exercise_id: multi_exercise_1_id,
1197 exercise_name: "Multiple task exercise".to_string(),
1198 exercise_slides: vec![(
1199 multi_exercise_1_slide_1_id,
1200 vec![
1201 (
1202 multi_exercise_1_slide_1_task_1_id,
1203 "example-exercise".to_string(),
1204 serde_json::json!([paragraph(
1205 "First question.",
1206 Uuid::new_v5(&course_id, b"e972a22b-67ae-4971-b437-70effd5614d4")
1207 )]),
1208 serde_json::json!([
1209 {
1210 "name": "Correct",
1211 "correct": true,
1212 "id": Uuid::new_v5(&course_id, b"0a046287-6b49-405d-ad9e-12f6dc5f9b1d"),
1213 },
1214 {
1215 "name": "Incorrect",
1216 "correct": false,
1217 "id": Uuid::new_v5(&course_id, b"c202540e-9a3f-4ff4-9703-b9921e9eee8e"),
1218 },
1219 ]),
1220 ),
1221 (
1222 multi_exercise_1_slide_1_task_2_id,
1223 "example-exercise".to_string(),
1224 serde_json::json!([paragraph(
1225 "Second question.",
1226 Uuid::new_v5(&course_id, b"e4895ced-757c-401a-8836-b734b75dff54")
1227 )]),
1228 serde_json::json!([
1229 {
1230 "name": "Correct",
1231 "correct": true,
1232 "id": Uuid::new_v5(&course_id, b"e0c2efa8-ac15-4a3c-94bb-7d5e72e57671"),
1233 },
1234 {
1235 "name": "Incorrect",
1236 "correct": false,
1237 "id": Uuid::new_v5(&course_id, b"db5cf7d4-b5bb-43f7-931e-e329cc2e95b1"),
1238 },
1239 ]),
1240 ),
1241 (
1242 multi_exercise_1_slide_1_task_3_id,
1243 "example-exercise".to_string(),
1244 serde_json::json!([paragraph(
1245 "Third question.",
1246 Uuid::new_v5(&course_id, b"13b75f4e-b02d-41fa-b5bc-79adf22d9aef")
1247 )]),
1248 serde_json::json!([
1249 {
1250 "name": "Correct",
1251 "correct": true,
1252 "id": Uuid::new_v5(&course_id, b"856defd2-08dd-4632-aaef-ec71cdfd3bca"),
1253 },
1254 {
1255 "name": "Incorrect",
1256 "correct": false,
1257 "id": Uuid::new_v5(&course_id, b"95ffff70-7dbe-4e39-9480-2a3514e9ea1d"),
1258 },
1259 ]),
1260 ),
1261 ],
1262 )],
1263 client_id: Uuid::new_v5(&course_id, b"9e70076a-9137-4d65-989c-0c0951027c53"),
1264 needs_peer_review: None,
1265 peer_or_self_review_config: None,
1266 peer_or_self_review_questions: None,
1267 teacher_reviews_answer_after_locking: true,
1268 });
1269 create_page(
1270 &mut conn,
1271 course.id,
1272 teacher_user_id,
1273 Some(chapter_1.id),
1274 CmsPageUpdate {
1275 url_path: "/chapter-1/complicated-exercise".to_string(),
1276 title: "Complicated exercise page".to_string(),
1277 chapter_id: Some(chapter_1.id),
1278 exercises: vec![multi_exercise_1],
1279 exercise_slides: multi_exercise_1_slides,
1280 exercise_tasks: multi_exercise_1_tasks,
1281 content: vec![
1282 paragraph(
1283 "This page has a complicated exercise.",
1284 Uuid::new_v5(&course_id, b"86f1b595-ec82-43a6-954f-c1f8de3d53ac"),
1285 ),
1286 multi_exercise_block_1,
1287 ],
1288 },
1289 )
1290 .await?;
1291
1292 let exercise_5_id = Uuid::new_v5(&course_id, b"8bb4faf4-9a34-4df7-a166-89ade530d0f6");
1293 let exercise_5_slide_1_id = Uuid::new_v5(&course_id, b"b99d1041-7835-491e-a1c8-b47eee8e7ab4");
1294 let exercise_5_slide_1_task_1_id =
1295 Uuid::new_v5(&course_id, b"a6508b8a-f58e-43ac-9f02-785575e716f5");
1296 let exercise_5_slide_1_task_1_spec_1_id =
1297 Uuid::new_v5(&course_id, b"fe464d17-2365-4e65-8b33-e0ebb5a67836");
1298 let exercise_5_slide_1_task_1_spec_2_id =
1299 Uuid::new_v5(&course_id, b"6633ffc7-c76e-4049-840e-90eefa6b49e8");
1300 let exercise_5_slide_1_task_1_spec_3_id =
1301 Uuid::new_v5(&course_id, b"d77fb97d-322c-4c5f-a405-8978a8cfb0a9");
1302 let (exercise_block_5, exercise_5, exercise_slide_5, exercise_task_5) = create_best_exercise(
1303 Uuid::new_v5(&course_id, b"fe464d17-2365-4e65-8b33-e0ebb5a67836"),
1304 exercise_5_slide_1_task_1_spec_1_id,
1305 exercise_5_slide_1_task_1_spec_2_id,
1306 exercise_5_slide_1_task_1_spec_3_id,
1307 Some("Best exercise".to_string()),
1308 CommonExerciseData {
1309 exercise_id: exercise_5_id,
1310 exercise_slide_id: exercise_5_slide_1_id,
1311 exercise_task_id: exercise_5_slide_1_task_1_id,
1312 block_id: Uuid::new_v5(&course_id, b"e869c471-b1b7-42a0-af05-dffd1d86a7bb"),
1313 },
1314 );
1315 create_page(
1316 &mut conn,
1317 course.id,
1318 teacher_user_id,
1319 Some(chapter_2.id),
1320 CmsPageUpdate {
1321 url_path: "/chapter-2/intro".to_string(),
1322 title: "In the second chapter...".to_string(),
1323 chapter_id: Some(chapter_2.id),
1324 exercises: vec![exercise_5],
1325 exercise_slides: vec![exercise_slide_5],
1326 exercise_tasks: vec![exercise_task_5],
1327 content: vec![exercise_block_5],
1328 },
1329 )
1330 .await?;
1331
1332 let multi_exercise_2_id = Uuid::new_v5(&course_id, b"057def52-6895-4374-a7f5-1849d136f1f4");
1333 let multi_exercise_2_slide_1_id =
1334 Uuid::new_v5(&course_id, b"fa02d232-8e33-4e20-9c20-d3b03fa89eb5");
1335 let multi_exercise_2_slide_1_task_1_id =
1336 Uuid::new_v5(&course_id, b"6c72f989-4d7e-4b22-b63c-3c51c631abcb");
1337 let multi_exercise_2_slide_1_task_2_id =
1338 Uuid::new_v5(&course_id, b"9445e8a3-6a86-4492-96b8-971f7b7acedd");
1339 let multi_exercise_2_slide_1_task_3_id =
1340 Uuid::new_v5(&course_id, b"8fbdbc4d-0c62-4b70-bb31-4c5fbb4ea6dd");
1341 let (multi_exercise_block_2, multi_exercise_2, multi_exercise_2_slides, multi_exercise_2_tasks) =
1342 example_exercise_flexible(ExampleExerciseFlexibleParams {
1343 exercise_id: multi_exercise_2_id,
1344 exercise_name: "Multiple task quizzes exercise".to_string(),
1345 exercise_slides: vec![(
1346 multi_exercise_2_slide_1_id,
1347 vec![
1348 (
1349 multi_exercise_2_slide_1_task_1_id,
1350 "quizzes".to_string(),
1351 serde_json::json!([paragraph(
1352 "First question.",
1353 Uuid::new_v5(&course_id, b"c8414adc-4e99-4d93-b926-e257517ff934")
1354 )]),
1355 serde_json::json!({
1356 "id": "e8a81dad-d616-44ab-bd6e-ec5430b454be",
1357 "body": "very hard",
1358 "open": "2021-12-17T07:15:33.479Z",
1359 "part": 0,
1360 "items": [{
1361 "id": "ba2b179a-fab7-4eb7-896f-ef841eeda8e5",
1362 "body": null,
1363 "type": "multiple-choice",
1364 "multi": false,
1365 "multipleChoiceMultipleOptionsGradingPolicy": "default",
1366 "order": 0,
1367 "title": "Select all correct answers from below",
1368 "quizId": "e8a81dad-d616-44ab-bd6e-ec5430b454be",
1369 "options": [
1370 {
1371 "id": "bb172040-753d-40ef-bded-a487b668905a",
1372 "body": "Correct",
1373 "order": 1,
1374 "title": null,
1375 "quizItemId": "ba2b179a-fab7-4eb7-896f-ef841eeda8e5",
1376 "correct":true,
1377 "messageAfterSubmissionWhenSelected": "This is correct option",
1378 "additionalCorrectnessExplanationOnModelSolution": null
1379 },
1380 {
1381 "id": "a1534c77-3379-4462-b67c-f55a17aa6499",
1382 "body": "Correct",
1383 "order": 2,
1384 "title": null,
1385 "quizItemId": "ba2b179a-fab7-4eb7-896f-ef841eeda8e5",
1386 "correct":true,
1387 "messageAfterSubmissionWhenSelected": "This is correct option",
1388 "additionalCorrectnessExplanationOnModelSolution": null,
1389 },
1390 {
1391 "id": "828328e6-5491-4ccb-b6f7-1df0796db44e",
1392 "body": "Incorrect",
1393 "order": 3,
1394 "title": null,
1395 "quizItemId": "ba2b179a-fab7-4eb7-896f-ef841eeda8e5",
1396 "correct":false,
1397 "messageAfterSubmissionWhenSelected": "This is incorrect option",
1398 "additionalCorrectnessExplanationOnModelSolution": null
1399 },
1400 ],
1401 "allAnswersCorrect": false,
1402 "sharedOptionFeedbackMessage": null,
1403 "usesSharedOptionFeedbackMessage": false
1404 }],
1405 "title": "Pretty good exercise",
1406 "tries": 1,
1407 "points": 2,
1408 "section": 0,
1409 "courseId": "39c7879a-e61f-474a-8f18-7fc476ccc3a0",
1410 "deadline": "2021-12-17T07:15:33.479Z",
1411 "createdAt": "2021-12-17T07:15:33.479Z",
1412 "updatedAt": "2021-12-17T07:15:33.479Z",
1413 "autoReject": false,
1414 "autoConfirm": true,
1415 "randomizeOptions": false,
1416 "triesLimited": true,
1417 "submitMessage": "This is an extra submit message from the teacher.",
1418 "excludedFromScore": true,
1419 "grantPointsPolicy": "grant_whenever_possible",
1420 "awardPointsEvenIfWrong": false}),
1421 ),
1422 (
1423 multi_exercise_2_slide_1_task_2_id,
1424 "quizzes".to_string(),
1425 serde_json::json!([paragraph(
1426 "Second question.",
1427 Uuid::new_v5(&course_id, b"fcdeb228-a36e-499b-9cf0-dfb264a2cf34")
1428 )]),
1429 serde_json::json!({
1430 "id": "67fc1eea-541c-4247-a852-090c71d7a9d1",
1431 "body": "very hard",
1432 "open": "2021-12-17T07:15:33.479Z",
1433 "part": 0,
1434 "items": [{
1435 "id": "7640b8db-eee0-4685-b031-dde26f183c9c",
1436 "body": null,
1437 "type": "multiple-choice",
1438 "multi": false,
1439 "multipleChoiceMultipleOptionsGradingPolicy": "default",
1440 "order": 0,
1441 "title": "Select all correct answers from below",
1442 "quizId": "67fc1eea-541c-4247-a852-090c71d7a9d1",
1443 "options": [
1444 {
1445 "id": "446034b8-e049-4973-a634-5561da4b6d8e",
1446 "body": "Correct",
1447 "order": 1,
1448 "title": null,
1449 "quizItemId": "7640b8db-eee0-4685-b031-dde26f183c9c",
1450 "correct":true,
1451 "messageAfterSubmissionWhenSelected": "This is correct option",
1452 "additionalCorrectnessExplanationOnModelSolution": null
1453 },
1454 {
1455 "id": "a4a0c48a-b171-4855-b738-b248f1e50561",
1456 "body": "Incorrect",
1457 "order": 2,
1458 "title": null,
1459 "quizItemId": "7640b8db-eee0-4685-b031-dde26f183c9c",
1460 "correct":false,
1461 "messageAfterSubmissionWhenSelected": "This is incorrect option",
1462 "additionalCorrectnessExplanationOnModelSolution": null,
1463 },
1464 {
1465 "id": "f65330da-de15-47f3-9a4d-9f47eb6a5f5a",
1466 "body": "Correct",
1467 "order": 3,
1468 "title": null,
1469 "quizItemId": "7640b8db-eee0-4685-b031-dde26f183c9c",
1470 "correct":true,
1471 "messageAfterSubmissionWhenSelected": "This is correct option",
1472 "additionalCorrectnessExplanationOnModelSolution": null
1473 },
1474 ],
1475 "allAnswersCorrect": false,
1476 "sharedOptionFeedbackMessage": null,
1477 "usesSharedOptionFeedbackMessage": false
1478 }],
1479 "title": "Pretty good exercise",
1480 "tries": 1,
1481 "points": 2,
1482 "section": 0,
1483 "courseId": "39c7879a-e61f-474a-8f18-7fc476ccc3a0",
1484 "deadline": "2021-12-17T07:15:33.479Z",
1485 "createdAt": "2021-12-17T07:15:33.479Z",
1486 "updatedAt": "2021-12-17T07:15:33.479Z",
1487 "autoReject": false,
1488 "autoConfirm": true,
1489 "randomizeOptions": false,
1490 "triesLimited": true,
1491 "submitMessage": "This is an extra submit message from the teacher.",
1492 "excludedFromScore": true,
1493 "grantPointsPolicy": "grant_whenever_possible",
1494 "awardPointsEvenIfWrong": false}),
1495 ),
1496 (
1497 multi_exercise_2_slide_1_task_3_id,
1498 "quizzes".to_string(),
1499 serde_json::json!([paragraph(
1500 "Third question.",
1501 Uuid::new_v5(&course_id, b"13b75f4e-b02d-41fa-b5bc-79adf22d9aef")
1502 )]),
1503 serde_json::json!({
1504 "id": "3f332295-b409-4fa8-a690-e5afd4e06b7a",
1505 "body": "very hard",
1506 "open": "2021-12-17T07:15:33.479Z",
1507 "part": 0,
1508 "items": [{
1509 "id": "a72b53f5-97c4-4385-899b-560d06592aec",
1510 "body": null,
1511 "type": "multiple-choice",
1512 "multi": false,
1513 "multipleChoiceMultipleOptionsGradingPolicy": "default",
1514 "order": 0,
1515 "title": "Pick all the correct answers from below",
1516 "quizId": "3f332295-b409-4fa8-a690-e5afd4e06b7a",
1517 "options": [
1518 {
1519 "id": "d606fec9-6854-4b40-9b37-e1f53f4d4a0f",
1520 "body": "Incorrect",
1521 "order": 1,
1522 "title": null,
1523 "quizItemId": "a72b53f5-97c4-4385-899b-560d06592aec",
1524 "correct":false,
1525 "messageAfterSubmissionWhenSelected": "This is incorrect option",
1526 "additionalCorrectnessExplanationOnModelSolution": null
1527 },
1528 {
1529 "id": "9c69312d-c1e1-48bd-b920-309b39d2a7db",
1530 "body": "Correct",
1531 "order": 2,
1532 "title": null,
1533 "quizItemId": "a72b53f5-97c4-4385-899b-560d06592aec",
1534 "correct":true,
1535 "messageAfterSubmissionWhenSelected": "This is correct option",
1536 "additionalCorrectnessExplanationOnModelSolution": null,
1537 },
1538 {
1539 "id": "fef8854d-fee0-40ad-ab81-f4ed66daadeb",
1540 "body": "Correct",
1541 "order": 3,
1542 "title": null,
1543 "quizItemId": "a72b53f5-97c4-4385-899b-560d06592aec",
1544 "correct":true,
1545 "messageAfterSubmissionWhenSelected": "This is correct option",
1546 "additionalCorrectnessExplanationOnModelSolution": null
1547 },
1548 ],
1549 "allAnswersCorrect": false,
1550 "sharedOptionFeedbackMessage": null,
1551 "usesSharedOptionFeedbackMessage": false
1552 }],
1553 "title": "Pretty good exercise",
1554 "tries": 1,
1555 "points": 2,
1556 "section": 0,
1557 "courseId": "39c7879a-e61f-474a-8f18-7fc476ccc3a0",
1558 "deadline": "2021-12-17T07:15:33.479Z",
1559 "createdAt": "2021-12-17T07:15:33.479Z",
1560 "updatedAt": "2021-12-17T07:15:33.479Z",
1561 "autoReject": false,
1562 "autoConfirm": true,
1563 "randomizeOptions": false,
1564 "triesLimited": true,
1565 "submitMessage": "This is an extra submit message from the teacher.",
1566 "excludedFromScore": true,
1567 "grantPointsPolicy": "grant_whenever_possible",
1568 "awardPointsEvenIfWrong": false}),
1569 ),
1570 ],
1571 )],
1572 client_id: Uuid::new_v5(&course_id, b"9e70076a-9137-4d65-989c-0c0951027c53"),
1573 needs_peer_review: None,
1574 peer_or_self_review_config: None,
1575 peer_or_self_review_questions: None,
1576 teacher_reviews_answer_after_locking: true,
1577 });
1578
1579 create_page(
1580 &mut conn,
1581 course.id,
1582 teacher_user_id,
1583 Some(chapter_1.id),
1584 CmsPageUpdate {
1585 url_path: "/chapter-1/complicated-quizzes-exercise".to_string(),
1586 title: "Complicated quizzes exercise page".to_string(),
1587 chapter_id: Some(chapter_1.id),
1588 exercises: vec![multi_exercise_2],
1589 exercise_slides: multi_exercise_2_slides,
1590 exercise_tasks: multi_exercise_2_tasks,
1591 content: vec![
1592 paragraph(
1593 "This page has a complicated quizzes exercise.",
1594 Uuid::new_v5(&course_id, b"ea0eaf34-3c92-4007-aae4-9abff7ad1e4c"),
1595 ),
1596 multi_exercise_block_2,
1597 ],
1598 },
1599 )
1600 .await?;
1601
1602 create_page(
1603 &mut conn,
1604 course.id,
1605 teacher_user_id,
1606 Some(chapter_1.id),
1607 CmsPageUpdate {
1608 url_path: "/chapter-1/the-authors".to_string(),
1609 title: "The Author Block".to_string(),
1610 chapter_id: Some(chapter_1.id),
1611 exercises: vec![],
1612 exercise_slides: vec![],
1613 exercise_tasks: vec![],
1614 content: vec![GutenbergBlock {
1615 name: "moocfi/author".to_string(),
1616 is_valid: true,
1617 client_id: Uuid::parse_str("eb27eddd-6fc7-46f8-b7aa-968b16f86f1f").unwrap(),
1618 attributes: attributes! {},
1619 inner_blocks: vec![GutenbergBlock {
1620 name: "moocfi/author-inner-block".to_string(),
1621 is_valid: true,
1622 client_id: Uuid::parse_str("b5565362-e8e3-4837-9546-014dc98af686").unwrap(),
1623 attributes: attributes! {},
1624 inner_blocks: vec![GutenbergBlock {
1625 name: "core/columns".to_string(),
1626 is_valid: true,
1627 client_id: Uuid::parse_str("d8df9ead-9be3-4d25-96ec-c6e591db261b").unwrap(),
1628 attributes: attributes! { "isStackedOnMobile": true },
1629 inner_blocks: vec![GutenbergBlock {
1630 name: "core/column".to_string(),
1631 is_valid: true,
1632 client_id: Uuid::parse_str("6435c2f7-ccc0-4cec-9c38-19bd688b057c").unwrap(),
1633 attributes: attributes! {},
1634 inner_blocks: vec![GutenbergBlock {
1635 name: "core/image".to_string(),
1636 is_valid: true,
1637 client_id: Uuid::parse_str("f700cf35-0c8e-4905-88ed-475ad60bdf82").unwrap(),
1638 attributes: attributes! {
1639 "alt": "Add alt",
1640 "anchor": "author-photo",
1641 "blurDataUrl": "",
1642 "href": "http://project-331.local/api/v0/files/uploads/jpgs/lilo-and-stitch.jpg",
1643 "linkDestination": "media",
1644 "sizeSlug": "full",
1645 "url": "http://project-331.local/api/v0/files/uploads/jpgs/lilo-and-stitch.jpg",
1646 },
1647 inner_blocks: vec![],
1648 }],
1649 },
1650 GutenbergBlock {
1651 name: "core/column".to_string(),
1652 is_valid: true,
1653 client_id: Uuid::parse_str("fe8b2efc-e5da-407e-9293-f156847cc571").unwrap(),
1654 attributes: attributes! {},
1655 inner_blocks: vec![GutenbergBlock {
1656 name: "core/paragraph".to_string(),
1657 is_valid: true,
1658 client_id: Uuid::parse_str("6d0e2979-9a57-492a-af6f-9f62381f1ede").unwrap(),
1659 attributes: attributes! {
1660 "align": "left",
1661 "content": "Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur",
1662 "dropCap": false,
1663 "placeholder": "Insert author's bio text..."
1664 },
1665 inner_blocks: vec![],
1666 }],
1667 },
1668 ],
1669
1670 },
1671 ],
1672 }]
1673 }]
1674 },
1675
1676 )
1677 .await?;
1678
1679 create_page(
1680 &mut conn,
1681 course.id,
1682 teacher_user_id,
1683 None,
1684 CmsPageUpdate {
1685 url_path: "/glossary".to_string(),
1686 title: "Glossary".to_string(),
1687 chapter_id: None,
1688 exercises: vec![],
1689 exercise_slides: vec![],
1690 exercise_tasks: vec![],
1691 content: vec![GutenbergBlock {
1692 name: "moocfi/glossary".to_string(),
1693 is_valid: true,
1694 client_id: Uuid::parse_str("3a388f47-4aa7-409f-af14-a0290b916225").unwrap(),
1695 attributes: attributes! {},
1696 inner_blocks: vec![],
1697 }],
1698 },
1699 )
1700 .await?;
1701
1702 info!("sample enrollments, user exercise states, submissions, grades");
1704 for user_id in users.iter().copied() {
1705 course_instance_enrollments::insert_enrollment_and_set_as_current(
1706 &mut conn,
1707 NewCourseInstanceEnrollment {
1708 course_id,
1709 course_instance_id: default_instance.id,
1710 user_id,
1711 },
1712 )
1713 .await?;
1714
1715 user_ai_usage_notice_acknowledgements::acknowledge(&mut conn, user_id, course_id).await?;
1718
1719 submit_and_grade(
1720 &mut conn,
1721 b"8c447aeb-1791-4236-8471-204d8bc27507",
1722 exercise_1_id,
1723 exercise_1_slide_1_id,
1724 course.id,
1725 exercise_1_slide_1_task_1_id,
1726 user_id,
1727 default_instance.id,
1728 exercise_1_slide_1_task_1_spec_1_id.to_string(),
1729 100.0,
1730 )
1731 .await?;
1732 submit_and_grade(
1734 &mut conn,
1735 b"a719fe25-5721-412d-adea-4696ccb3d883",
1736 exercise_1_id,
1737 exercise_1_slide_1_id,
1738 course.id,
1739 exercise_1_slide_1_task_1_id,
1740 user_id,
1741 default_instance.id,
1742 exercise_1_slide_1_task_1_spec_2_id.to_string(),
1743 1.0,
1744 )
1745 .await?;
1746 submit_and_grade(
1747 &mut conn,
1748 b"bbc16d4b-1f91-4bd0-a47f-047665a32196",
1749 exercise_1_id,
1750 exercise_1_slide_1_id,
1751 course.id,
1752 exercise_1_slide_1_task_1_id,
1753 user_id,
1754 default_instance.id,
1755 exercise_1_slide_1_task_1_spec_3_id.to_string(),
1756 0.0,
1757 )
1758 .await?;
1759 submit_and_grade(
1760 &mut conn,
1761 b"c60bf5e5-9b67-4f62-9df7-16d268c1b5f5",
1762 exercise_1_id,
1763 exercise_1_slide_1_id,
1764 course.id,
1765 exercise_1_slide_1_task_1_id,
1766 user_id,
1767 default_instance.id,
1768 exercise_1_slide_1_task_1_spec_1_id.to_string(),
1769 60.0,
1770 )
1771 .await?;
1772 submit_and_grade(
1773 &mut conn,
1774 b"e0ec1386-72aa-4eed-8b91-72bba420c23b",
1775 exercise_2_id,
1776 exercise_2_slide_1_id,
1777 course.id,
1778 exercise_2_slide_1_task_1_id,
1779 user_id,
1780 default_instance.id,
1781 exercise_2_slide_1_task_1_spec_1_id.to_string(),
1782 70.0,
1783 )
1784 .await?;
1785 submit_and_grade(
1786 &mut conn,
1787 b"02c9e1ad-6e4c-4473-a3e9-dbfab018a055",
1788 exercise_5_id,
1789 exercise_5_slide_1_id,
1790 course.id,
1791 exercise_5_slide_1_task_1_id,
1792 user_id,
1793 default_instance.id,
1794 exercise_5_slide_1_task_1_spec_1_id.to_string(),
1795 80.0,
1796 )
1797 .await?;
1798 submit_and_grade(
1799 &mut conn,
1800 b"75df4600-d337-4083-99d1-e8e3b6bf6192",
1801 exercise_1_id,
1802 exercise_1_slide_1_id,
1803 course.id,
1804 exercise_1_slide_1_task_1_id,
1805 user_id,
1806 default_instance.id,
1807 exercise_1_slide_1_task_1_spec_1_id.to_string(),
1808 90.0,
1809 )
1810 .await?;
1811 }
1812 course_instance_enrollments::insert_enrollment_and_set_as_current(
1813 &mut conn,
1814 NewCourseInstanceEnrollment {
1815 course_id,
1816 course_instance_id: default_instance.id,
1817 user_id: langs_user_id,
1818 },
1819 )
1820 .await?;
1821 user_ai_usage_notice_acknowledgements::acknowledge(&mut conn, langs_user_id, course_id).await?;
1822
1823 info!("sample feedback");
1825 let new_feedback = NewFeedback {
1826 feedback_given: "this part was unclear to me".to_string(),
1827 selected_text: Some("blanditiis".to_string()),
1828 related_blocks: vec![FeedbackBlock {
1829 id: block_id_4,
1830 text: Some(
1831 "blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas"
1832 .to_string(),
1833 ),
1834 order_number: Some(0),
1835 }],
1836 page_id: page_3,
1837 };
1838 let feedback = feedback::insert(
1839 &mut conn,
1840 PKeyPolicy::Generate,
1841 Some(student),
1842 course.id,
1843 new_feedback,
1844 )
1845 .await?;
1846 feedback::mark_as_read(&mut conn, feedback, true).await?;
1847 let new_feedback = NewFeedback {
1848 feedback_given: "I dont think we need these paragraphs".to_string(),
1849 selected_text: Some("verything".to_string()),
1850 related_blocks: vec![
1851 FeedbackBlock {
1852 id: block_id_1,
1853 text: Some("verything is a big topic.".to_string()),
1854 order_number: Some(0),
1855 },
1856 FeedbackBlock {
1857 id: block_id_4,
1858 text: Some("So big, that we need many paragraphs.".to_string()),
1859 order_number: Some(1),
1860 },
1861 FeedbackBlock {
1862 id: block_id_5,
1863 text: Some("Like th".to_string()),
1864 order_number: Some(2),
1865 },
1866 ],
1867 page_id: page_3,
1868 };
1869 feedback::insert(
1870 &mut conn,
1871 PKeyPolicy::Generate,
1872 Some(student),
1873 course.id,
1874 new_feedback,
1875 )
1876 .await?;
1877 feedback::insert(
1878 &mut conn,
1879 PKeyPolicy::Generate,
1880 None,
1881 course.id,
1882 NewFeedback {
1883 feedback_given: "Anonymous feedback".to_string(),
1884 selected_text: None,
1885 related_blocks: vec![FeedbackBlock {
1886 id: block_id_1,
1887 text: None,
1888 order_number: Some(0),
1889 }],
1890 page_id: page_3,
1891 },
1892 )
1893 .await?;
1894 feedback::insert(
1895 &mut conn,
1896 PKeyPolicy::Generate,
1897 None,
1898 course.id,
1899 NewFeedback {
1900 feedback_given: "Anonymous unrelated feedback".to_string(),
1901 selected_text: None,
1902 related_blocks: vec![],
1903 page_id: page_3,
1904 },
1905 )
1906 .await?;
1907
1908 info!("sample edit proposals");
1910 let edits = NewProposedPageEdits {
1911 page_id: page_c1_1,
1912 block_edits: vec![NewProposedBlockEdit {
1913 block_id: block_id_4,
1914 block_attribute: "content".to_string(),
1915 original_text: "So bg, that we need many paragraphs.".to_string(),
1916 changed_text: "So bg, that we need many, many paragraphs.".to_string(),
1917 }],
1918 };
1919 proposed_page_edits::insert(
1920 &mut conn,
1921 PKeyPolicy::Generate,
1922 course.id,
1923 Some(student),
1924 &edits,
1925 )
1926 .await?;
1927 let edits = NewProposedPageEdits {
1928 page_id: page_c1_1,
1929 block_edits: vec![
1930 NewProposedBlockEdit {
1931 block_id: block_id_1,
1932 block_attribute: "content".to_string(),
1933 original_text: "Everything is a big topic.".to_string(),
1934 changed_text: "Everything is a very big topic.".to_string(),
1935 },
1936 NewProposedBlockEdit {
1937 block_id: block_id_5,
1938 block_attribute: "content".to_string(),
1939 original_text: "Like this.".to_string(),
1940 changed_text: "Like this!".to_string(),
1941 },
1942 ],
1943 };
1944 proposed_page_edits::insert(
1945 &mut conn,
1946 PKeyPolicy::Generate,
1947 course.id,
1948 Some(student),
1949 &edits,
1950 )
1951 .await?;
1952
1953 glossary::insert(&mut conn, "CS", "Computer science. Computer science is an essential part of being successful in your life. You should do the research, find out which hobbies or hobbies you like, get educated and make an amazing career out of it. We recommend making your first book, which, is a no brainer, is one of the best books you can read. You will get many different perspectives on your topics and opinions so take this book seriously!", course.id).await?;
1955 glossary::insert(&mut conn, "HDD", "Hard disk drive. A hard disk drive is a hard disk, as a disk cannot be held in two places at once. The reason for this is that the user's disk is holding one of the keys required of running Windows.", course.id).await?;
1956 glossary::insert(&mut conn, "KB", "Keyboard.", course.id).await?;
1957
1958 let background_svg_path = "svgs/certificate-background.svg".to_string();
1962 let background_svg_file_upload_id = file_uploads::insert(
1963 &mut conn,
1964 &format!("background-{}.svg", module.id),
1965 &background_svg_path,
1966 "image/svg+xml",
1967 None,
1968 )
1969 .await?;
1970 let configuration = DatabaseCertificateConfiguration {
1971 id: Uuid::new_v5(&course_id, b"886d3e22-5007-4371-94d7-e0ad93a2391c"),
1972 certificate_owner_name_y_pos: None,
1973 certificate_owner_name_x_pos: None,
1974 certificate_owner_name_font_size: None,
1975 certificate_owner_name_text_color: None,
1976 certificate_owner_name_text_anchor: None,
1977 certificate_validate_url_y_pos: None,
1978 certificate_validate_url_x_pos: None,
1979 certificate_validate_url_font_size: None,
1980 certificate_validate_url_text_color: None,
1981 certificate_validate_url_text_anchor: None,
1982 certificate_date_y_pos: None,
1983 certificate_date_x_pos: None,
1984 certificate_date_font_size: None,
1985 certificate_date_text_color: None,
1986 certificate_date_text_anchor: None,
1987 certificate_locale: None,
1988 paper_size: None,
1989 background_svg_path,
1990 background_svg_file_upload_id,
1991 overlay_svg_path: None,
1992 overlay_svg_file_upload_id: None,
1993 render_certificate_grade: false,
1994 certificate_grade_y_pos: None,
1995 certificate_grade_x_pos: None,
1996 certificate_grade_font_size: None,
1997 certificate_grade_text_color: None,
1998 certificate_grade_text_anchor: None,
1999 };
2000 let database_configuration =
2001 certificate_configurations::insert(&mut conn, &configuration).await?;
2002 certificate_configuration_to_requirements::insert(
2003 &mut conn,
2004 database_configuration.id,
2005 Some(default_module.id),
2006 )
2007 .await?;
2008
2009 roles::insert(
2011 &mut conn,
2012 seed_users_result.teacher_user_id,
2013 UserRole::Teacher,
2014 RoleDomain::Course(course.id),
2015 )
2016 .await?;
2017
2018 Ok(course.id)
2019}
2020
2021pub async fn seed_cs_course_material(
2022 db_pool: &Pool<Postgres>,
2023 org: Uuid,
2024 teacher_user_id: Uuid,
2025 langs_user_id: Uuid,
2026 _base_url: String,
2027) -> Result<Uuid> {
2028 let mut conn = db_pool.acquire().await?;
2029 let spec_fetcher = get_seed_spec_fetcher();
2030 let new_course = NewCourse {
2032 name: "Introduction to Course Material".to_string(),
2033 organization_id: org,
2034 slug: "introduction-to-course-material".to_string(),
2035 language_code: "en".to_string(),
2036 teacher_in_charge_name: "admin".to_string(),
2037 teacher_in_charge_email: "admin@example.com".to_string(),
2038 description: "The definitive introduction to course material.".to_string(),
2039 is_draft: false,
2040 is_test_mode: false,
2041 is_unlisted: false,
2042 copy_user_permissions: false,
2043 is_joinable_by_code_only: false,
2044 join_code: None,
2045 ask_marketing_consent: false,
2046 flagged_answers_threshold: Some(3),
2047 can_add_chatbot: false,
2048 };
2049 let (course, front_page, default_instance, default_module) =
2050 library::content_management::create_new_course(
2051 &mut conn,
2052 PKeyPolicy::Fixed(CreateNewCourseFixedIds {
2053 course_id: Uuid::parse_str("d6b52ddc-6c34-4a59-9a59-7e8594441007")?,
2054 default_course_instance_id: Uuid::parse_str(
2055 "8e6c35cd-43f2-4982-943b-11e3ffb1b2f8",
2056 )?,
2057 }),
2058 new_course,
2059 teacher_user_id,
2060 &spec_fetcher,
2061 models_requests::fetch_service_info,
2062 )
2063 .await?;
2064 courses::set_cheater_detection_enabled(&mut conn, course.id, false).await?;
2065
2066 let (
2068 quizzes_exercise_block_5,
2069 quizzes_exercise_5,
2070 quizzes_exercise_slide_5,
2071 quizzes_exercise_task_5,
2072 ) = quizzes_exercise(
2073 "Best quizzes exercise".to_string(),
2074 Uuid::new_v5(&course.id, b"58e71279-81e1-4679-83e6-8f5f23ec055a"),
2075 false,
2076 serde_json::json!({
2077 "id": "3a1b3e10-2dd5-4cb9-9460-4c08f19e16d3",
2078 "body": "very hard",
2079 "part": 3,
2080 "items": [{
2081 "id": "7b0049ea-de8b-4eef-a4a9-164e0e874ecc",
2082 "body": "",
2083 "type": "multiple-choice",
2084 "direction": "row",
2085 "multi": false,
2086 "multipleChoiceMultipleOptionsGradingPolicy": "default",
2087 "order": 0,
2088 "title": "Choose the first answer",
2089 "quizId": "3a1b3e10-2dd5-4cb9-9460-4c08f19e16d3",
2090 "options": [{
2091 "id": "d5124283-4e84-4b4f-84c0-a91961b0ef21",
2092 "body": "This is first option",
2093 "order": 1,
2094 "title": null,
2095 "quizItemId": "7b0049ea-de8b-4eef-a4a9-164e0e874ecc",
2096 "correct":true,
2097 "messageAfterSubmissionWhenSelected": "Correct! This is indeed the first answer",
2098 "additionalCorrectnessExplanationOnModelSolution": null,
2099 },{
2100 "id": "846c09e2-653a-4471-81ae-25726486b003",
2101 "body": "This is second option",
2102 "order": 1,
2103 "title": null,
2104 "quizItemId": "7b0049ea-de8b-4eef-a4a9-164e0e874ecc",
2105 "correct":false,
2106 "messageAfterSubmissionWhenSelected": "Incorrect. This is not the first answer",
2107 "additionalCorrectnessExplanationOnModelSolution": null,
2108 },{
2109 "id": "8107ae39-96aa-4f54-aa78-1a33362a19c1",
2110 "body": "This is third option",
2111 "order": 1,
2112 "title": null,
2113 "quizItemId": "7b0049ea-de8b-4eef-a4a9-164e0e874ecc",
2114 "correct":false,
2115 "messageAfterSubmissionWhenSelected": "Incorrect. This is not the first answer",
2116 "additionalCorrectnessExplanationOnModelSolution": null,
2117 },],
2118 "allAnswersCorrect": false,
2119 "sharedOptionFeedbackMessage": null,
2120 "usesSharedOptionFeedbackMessage": false
2121 }],
2122 "title": "Very good exercise",
2123 "tries": 1,
2124 "points": 3,
2125 "section": 0,
2126 "courseId": "d6b52ddc-6c34-4a59-9a59-7e8594441007",
2127 "deadline": "2021-12-17T07:15:33.479Z",
2128 "createdAt": "2021-12-17T07:15:33.479Z",
2129 "updatedAt": "2021-12-17T07:15:33.479Z",
2130 "autoReject": false,
2131 "autoConfirm": true,
2132 "randomizeOptions": false,
2133 "triesLimited": true,
2134 "submitMessage": "This is an extra submit message from the teacher.",
2135 "excludedFromScore": true,
2136 "grantPointsPolicy": "grant_whenever_possible",
2137 "awardPointsEvenIfWrong": false}),
2138 Some(Utc.with_ymd_and_hms(2125, 1, 1, 23, 59, 59).unwrap()),
2139 CommonExerciseData {
2140 exercise_id: Uuid::new_v5(&course.id, b"cd3aa815-620e-43b3-b291-0fb10beca030"),
2141 exercise_slide_id: Uuid::new_v5(&course.id, b"0b1bbfb0-df56-4e40-92f1-df0a33f1fc70"),
2142 exercise_task_id: Uuid::new_v5(&course.id, b"7f011d0e-1cbf-4870-bacf-1873cf360c15"),
2143 block_id: Uuid::new_v5(&course.id, b"b9446b94-0edf-465c-9a9a-57708b7ef180"),
2144 },
2145 );
2146
2147 let (
2148 quizzes_exercise_block_6,
2149 quizzes_exercise_6,
2150 quizzes_exercise_slide_6,
2151 quizzes_exercise_task_6,
2152 ) = quizzes_exercise(
2153 "Best quizzes exercise".to_string(),
2154 Uuid::new_v5(&course.id, b"085b60ec-aa9d-11ec-b500-7b1e176646f8"),
2155 false,
2156 serde_json::from_str(include_str!(
2157 "../../../assets/quizzes-multiple-choice-additional-feedback.json"
2158 ))?,
2159 Some(Utc.with_ymd_and_hms(2125, 1, 1, 23, 59, 59).unwrap()),
2160 CommonExerciseData {
2161 exercise_id: Uuid::new_v5(&course.id, b"925d4a89-0f25-4e8e-bc11-350393d8d894"),
2162 exercise_slide_id: Uuid::new_v5(&course.id, b"ff92ca4a-aa9c-11ec-ac56-475e57747ad3"),
2163 exercise_task_id: Uuid::new_v5(&course.id, b"9037cb17-3841-4a79-8f50-bbe595a4f785"),
2164 block_id: Uuid::new_v5(&course.id, b"d6d80ae0-97a1-4db1-8a3b-2bdde3cfbe9a"),
2165 },
2166 );
2167
2168 let (
2169 quizzes_exercise_block_7,
2170 quizzes_exercise_7,
2171 quizzes_exercise_slide_7,
2172 quizzes_exercise_task_7,
2173 ) = quizzes_exercise(
2174 "Best quizzes exercise".to_string(),
2175 Uuid::new_v5(&course.id, b"6365746e-aa9d-11ec-8718-0b5628cbe29f"),
2176 false,
2177 serde_json::json!({
2178 "id": "33cd47ea-aa9d-11ec-897c-5b22513d61ee",
2179 "body": "very hard",
2180 "part": 5,
2181 "items": [{
2182 "id": "395888c8-aa9d-11ec-bb81-cb3a3f2609e4",
2183 "body": "",
2184 "type": "multiple-choice",
2185 "direction": "column",
2186 "multi": false,
2187 "multipleChoiceMultipleOptionsGradingPolicy": "default",
2188 "order": 0,
2189 "title": "Choose the first answer",
2190 "quizId": "33cd47ea-aa9d-11ec-897c-5b22513d61ee",
2191 "options": [{
2192 "id": "490543d8-aa9d-11ec-a20f-07269e5c09df",
2193 "body": "This is first option",
2194 "order": 1,
2195 "title": null,
2196 "quizItemId": "395888c8-aa9d-11ec-bb81-cb3a3f2609e4",
2197 "correct":true,
2198 "messageAfterSubmissionWhenSelected": "Correct! This is indeed the first answer",
2199 "additionalCorrectnessExplanationOnModelSolution": null,
2200 },{
2201 "id": "45e77450-aa9d-11ec-abea-6b824f5ae1f6",
2202 "body": "This is second option",
2203 "order": 1,
2204 "title": null,
2205 "quizItemId": "395888c8-aa9d-11ec-bb81-cb3a3f2609e4",
2206 "correct":false,
2207 "messageAfterSubmissionWhenSelected": "Incorrect. This is not the first answer",
2208 "additionalCorrectnessExplanationOnModelSolution": null,
2209 },{
2210 "id": "43428140-aa9d-11ec-a6b3-83ec8e2dfb88",
2211 "body": "This is third option",
2212 "order": 1,
2213 "title": null,
2214 "quizItemId": "395888c8-aa9d-11ec-bb81-cb3a3f2609e4",
2215 "correct":false,
2216 "messageAfterSubmissionWhenSelected": "Incorrect. This is not the first answer",
2217 "additionalCorrectnessExplanationOnModelSolution": null,
2218 },],
2219 "allAnswersCorrect": false,
2220 "sharedOptionFeedbackMessage": null,
2221 "usesSharedOptionFeedbackMessage": false
2222 }],
2223 "title": "Very good exercise",
2224 "tries": 1,
2225 "points": 3,
2226 "section": 0,
2227 "courseId": "d6b52ddc-6c34-4a59-9a59-7e8594441007",
2228 "deadline": "2021-12-17T07:15:33.479Z",
2229 "createdAt": "2021-12-17T07:15:33.479Z",
2230 "updatedAt": "2021-12-17T07:15:33.479Z",
2231 "autoReject": false,
2232 "autoConfirm": true,
2233 "randomizeOptions": false,
2234 "triesLimited": true,
2235 "submitMessage": "This is an extra submit message from the teacher.",
2236 "excludedFromScore": true,
2237 "grantPointsPolicy": "grant_whenever_possible",
2238 "awardPointsEvenIfWrong": false}),
2239 Some(Utc.with_ymd_and_hms(2125, 1, 1, 23, 59, 59).unwrap()),
2240 CommonExerciseData {
2241 exercise_id: Uuid::new_v5(&course.id, b"57905c8a-aa9d-11ec-92d4-47ab996cb70c"),
2242 exercise_slide_id: Uuid::new_v5(&course.id, b"5b058552-aa9d-11ec-bc36-57e1c5f8407a"),
2243 exercise_task_id: Uuid::new_v5(&course.id, b"5d953894-aa9d-11ec-97e7-2ff4d73f69f1"),
2244 block_id: Uuid::new_v5(&course.id, b"604dae7c-aa9d-11ec-8df1-575042832340"),
2245 },
2246 );
2247
2248 let (
2249 quizzes_exercise_block_8,
2250 quizzes_exercise_8,
2251 quizzes_exercise_slide_8,
2252 quizzes_exercise_task_8,
2253 ) = quizzes_exercise(
2254 "Best quizzes exercise".to_string(),
2255 Uuid::new_v5(&course.id, b"01b69776-3e82-4694-98a9-5ce53f2a4ab5"),
2256 false,
2257 serde_json::json!({
2258 "id": "9a186f2b-7616-472e-b839-62ab0f2f0a6c",
2259 "body": "very hard",
2260 "part": 6,
2261 "items": [{
2262 "id": "871c3640-aa9d-11ec-8103-633d645899a3",
2263 "body": "",
2264 "type": "multiple-choice",
2265 "direction": "column",
2266 "multi": false,
2267 "multipleChoiceMultipleOptionsGradingPolicy": "default",
2268 "order": 0,
2269 "title": "Choose the first answer",
2270 "quizId": "9a186f2b-7616-472e-b839-62ab0f2f0a6c",
2271 "options": [{
2272 "id": "4435ed30-c1da-46a0-80b8-c5b9ee923dd4",
2273 "body": "This is first option",
2274 "order": 1,
2275 "title": null,
2276 "quizItemId": "871c3640-aa9d-11ec-8103-633d645899a3",
2277 "correct":true,
2278 "messageAfterSubmissionWhenSelected": "Correct! This is indeed the first answer",
2279 "additionalCorrectnessExplanationOnModelSolution": null,
2280 },{
2281 "id": "1d5de4d0-8499-4ac1-b44c-21c1562639cb",
2282 "body": "This is second option",
2283 "order": 1,
2284 "title": null,
2285 "quizItemId": "871c3640-aa9d-11ec-8103-633d645899a3",
2286 "correct":false,
2287 "messageAfterSubmissionWhenSelected": "Incorrect. This is not the first answer",
2288 "additionalCorrectnessExplanationOnModelSolution": null,
2289 },{
2290 "id": "93fe358e-aa9d-11ec-9aa1-f3d18a09d58c",
2291 "body": "This is third option",
2292 "order": 1,
2293 "title": null,
2294 "quizItemId": "871c3640-aa9d-11ec-8103-633d645899a3",
2295 "correct":false,
2296 "messageAfterSubmissionWhenSelected": "Incorrect. This is not the first answer",
2297 "additionalCorrectnessExplanationOnModelSolution": null,
2298 },],
2299 "allAnswersCorrect": false,
2300 "sharedOptionFeedbackMessage": null,
2301 "usesSharedOptionFeedbackMessage": false
2302 }],
2303 "title": "Very good exercise",
2304 "tries": 1,
2305 "points": 3,
2306 "section": 0,
2307 "courseId": "d6b52ddc-6c34-4a59-9a59-7e8594441007",
2308 "deadline": "2021-12-17T07:15:33.479Z",
2309 "createdAt": "2021-12-17T07:15:33.479Z",
2310 "updatedAt": "2021-12-17T07:15:33.479Z",
2311 "autoReject": false,
2312 "autoConfirm": true,
2313 "randomizeOptions": false,
2314 "triesLimited": true,
2315 "submitMessage": "This is an extra submit message from the teacher.",
2316 "excludedFromScore": true,
2317 "grantPointsPolicy": "grant_whenever_possible",
2318 "awardPointsEvenIfWrong": false}),
2319 Some(Utc.with_ymd_and_hms(2125, 1, 1, 23, 59, 59).unwrap()),
2320 CommonExerciseData {
2321 exercise_id: Uuid::new_v5(&course.id, b"c1a4831c-cc78-4f42-be18-2a35a7f3b506"),
2322 exercise_slide_id: Uuid::new_v5(&course.id, b"75045b18-aa9d-11ec-b3d1-6f64c2d6d46d"),
2323 exercise_task_id: Uuid::new_v5(&course.id, b"712fd37c-e3d7-4569-8a64-371d7dda9c19"),
2324 block_id: Uuid::new_v5(&course.id, b"6799021d-ff0c-4e4d-b5db-c2c19fba7fb9"),
2325 },
2326 );
2327
2328 pages::update_page(
2329 &mut conn,
2330 PageUpdateArgs {
2331 page_id: front_page.id,
2332 author: teacher_user_id,
2333 cms_page_update: CmsPageUpdate {
2334 title: "Introduction to Course Material".to_string(),
2335 url_path: "/".to_string(),
2336 chapter_id: None,
2337 content: vec![
2338 GutenbergBlock::landing_page_hero_section("Welcome to Introduction to Course Material", "In this course you'll learn the basics of UI/UX design. At the end of course you should be able to create your own design system.")
2339 .with_id(Uuid::parse_str("6ad81525-0010-451f-85e5-4832e3e364a8")?),
2340 GutenbergBlock::course_objective_section()
2341 .with_id(Uuid::parse_str("2eec7ad7-a95f-406f-acfe-f3a332b86e26")?),
2342 GutenbergBlock::empty_block_from_name("moocfi/course-chapter-grid".to_string())
2343 .with_id(Uuid::parse_str("bb51d61b-fd19-44a0-8417-7ffc6058b247")?),
2344 GutenbergBlock::empty_block_from_name("moocfi/course-progress".to_string())
2345 .with_id(Uuid::parse_str("1d7c28ca-86ab-4318-8b10-3e5b7cd6e465")?),
2346 ],
2347 exercises: vec![],
2348 exercise_slides: vec![],
2349 exercise_tasks: vec![],
2350 },
2351 retain_ids: true,
2352 history_change_reason: HistoryChangeReason::PageSaved,
2353 is_exam_page: false
2354 },
2355 &spec_fetcher,
2356 models_requests::fetch_service_info,
2357 )
2358 .await?;
2359 let (_page, _history) = pages::insert_course_page(
2362 &mut conn,
2363 &NewCoursePage::new(course.id, 1, "/faq", "FAQ"),
2364 teacher_user_id,
2365 )
2366 .await?;
2367
2368 let new_chapter = NewChapter {
2370 chapter_number: 1,
2371 course_id: course.id,
2372 front_page_id: None,
2373 name: "User Interface".to_string(),
2374 color: None,
2375 opens_at: None,
2376 deadline: None,
2377 course_module_id: Some(default_module.id),
2378 };
2379 let (chapter_1, front_page_ch_1) = library::content_management::create_new_chapter(
2380 &mut conn,
2381 PKeyPolicy::Fixed((
2382 Uuid::new_v5(&course.id, b"77e95910-2289-452f-a1dd-8b8bf4a829a0"),
2383 Uuid::new_v5(&course.id, b"91b6887f-8bc0-4df6-89a4-5687890bc955"),
2384 )),
2385 &new_chapter,
2386 teacher_user_id,
2387 &spec_fetcher,
2388 models_requests::fetch_service_info,
2389 )
2390 .await?;
2391 chapters::set_opens_at(&mut conn, chapter_1.id, Utc::now()).await?;
2392
2393 pages::update_page(
2394 &mut conn,
2395 PageUpdateArgs {
2396 page_id: front_page_ch_1.id,
2397 author: teacher_user_id,
2398 cms_page_update: CmsPageUpdate {
2399 title: "User Interface".to_string(),
2400 url_path: "/chapter-1".to_string(),
2401 chapter_id: Some(chapter_1.id),
2402 content: vec![
2403 GutenbergBlock::hero_section("User Interface", "In the industrial design field of human–computer interaction, a user interface is the space where interactions between humans and machines occur.")
2404 .with_id(Uuid::parse_str("848ac898-81c0-4ebc-881f-6f84e9eaf472")?),
2405 GutenbergBlock::empty_block_from_name("moocfi/pages-in-chapter".to_string())
2406 .with_id(Uuid::parse_str("c8b36f58-5366-4d6b-b4ec-9fc0bd65950e")?),
2407 GutenbergBlock::empty_block_from_name("moocfi/exercises-in-chapter".to_string())
2408 .with_id(Uuid::parse_str("457431b0-55db-46ac-90ae-03965f48b27e")?),
2409 ],
2410 exercises: vec![],
2411 exercise_slides: vec![],
2412 exercise_tasks: vec![],
2413 },
2414 retain_ids: true,
2415 history_change_reason: HistoryChangeReason::PageSaved,
2416 is_exam_page: false
2417 },
2418 &spec_fetcher,
2419 models_requests::fetch_service_info,
2420 )
2421 .await?;
2422
2423 let design_content = CmsPageUpdate {
2425 url_path: "/chapter-1/design".to_string(),
2426 title: "Design".to_string(),
2427 chapter_id: Some(chapter_1.id),
2428 exercises: vec![],
2429 exercise_slides: vec![],
2430 exercise_tasks: vec![],
2431 content: vec![
2432 GutenbergBlock::hero_section("Design", "A design is a plan or specification for the construction of an object or system or for the implementation of an activity or process, or the result of that plan or specification in the form of a prototype, product or process.")
2433 .with_id(Uuid::parse_str("98729704-9dd8-4309-aa08-402f9b2a6071")?),
2434 heading("First heading", Uuid::parse_str("731aa55f-238b-42f4-8c40-c093dd95ee7f")?, 2),
2435 GutenbergBlock::block_with_name_and_attributes(
2436 "core/paragraph",
2437 attributes!{
2438 "content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur bibendum felis nisi, vitae commodo mi venenatis in. Mauris hendrerit lacinia augue ut hendrerit. Vestibulum non tellus mattis, convallis magna vel, semper mauris. Maecenas porta, arcu eget porttitor sagittis, nulla magna auctor dolor, sed tempus sem lacus eu tortor. Ut id diam quam. Etiam quis sagittis justo. Quisque sagittis dolor vitae felis facilisis, ut suscipit ipsum malesuada. Nulla tempor ultricies erat ut venenatis. Ut pulvinar lectus non mollis efficitur.",
2439 "dropCap": false
2440 },
2441 )
2442 .with_id(Uuid::parse_str("9ebddb78-23f6-4440-8d8f-5e4b33abb16f")?),
2443 heading("Second heading", Uuid::parse_str("a70aac40-acda-48e3-8f53-b64370be4585")?, 3),
2444 GutenbergBlock::block_with_name_and_attributes(
2445 "core/paragraph",
2446 attributes!{
2447 "content": "Sed quis fermentum mi. Integer commodo turpis a fermentum tristique. Integer convallis, nunc sed scelerisque varius, mi tellus molestie metus, eu ultrices justo tellus non arcu. Cras euismod, lectus eu scelerisque mattis, odio ex ornare ipsum, a dapibus nulla leo maximus orci. Etiam laoreet venenatis lorem, vitae iaculis mauris. Nullam lobortis, tortor eget ullamcorper lobortis, tellus odio tincidunt dolor, vitae gravida nibh turpis ac sem. Integer non sodales eros.",
2448 "dropCap": false
2449 },
2450 )
2451 .with_id(Uuid::parse_str("029ae4b5-08b0-49f7-8baf-d916b5f879a2")?),
2452 GutenbergBlock::block_with_name_and_attributes(
2453 "core/paragraph",
2454 attributes!{
2455 "content": "Vestibulum a scelerisque ante. Fusce interdum eros elit, posuere mattis sapien tristique id. Integer commodo mi orci, sit amet tempor libero vulputate in. Ut id gravida quam. Proin massa dolor, posuere nec metus eu, dignissim viverra nulla. Vestibulum quis neque bibendum, hendrerit diam et, fermentum diam. Sed risus nibh, suscipit in neque nec, bibendum interdum nibh. Aliquam ut enim a mi ultricies finibus. Nam tristique felis ac risus interdum molestie. Nulla venenatis, augue sed porttitor ultrices, lacus ante sollicitudin dui, vel vehicula ex enim ac mi.",
2456 "dropCap": false
2457 },
2458 )
2459 .with_id(Uuid::parse_str("3693e92b-9cf0-485a-b026-2851de58e9cf")?),
2460 heading("Third heading", Uuid::parse_str("4d16bfea-4fa9-4355-bbd4-4c61e33d3d7c")?, 2),
2461 GutenbergBlock::block_with_name_and_attributes(
2462 "core/paragraph",
2463 attributes!{
2464 "content": "Sed quis fermentum mi. Integer commodo turpis a fermentum tristique. Integer convallis, nunc sed scelerisque varius, mi tellus molestie metus, eu ultrices justo tellus non arcu. Cras euismod, lectus eu scelerisque mattis, odio ex ornare ipsum, a dapibus nulla leo maximus orci. Etiam laoreet venenatis lorem, vitae iaculis mauris. Nullam lobortis, tortor eget ullamcorper lobortis, tellus odio tincidunt dolor, vitae gravida nibh turpis ac sem. Integer non sodales eros.",
2465 "dropCap": false
2466 },
2467 )
2468 .with_id(Uuid::parse_str("4ef39962-634d-488c-be82-f44e5db19421")?),
2469 GutenbergBlock::block_with_name_and_attributes(
2470 "core/paragraph",
2471 attributes!{
2472 "content": "Vestibulum a scelerisque ante. Fusce interdum eros elit, posuere mattis sapien tristique id. Integer commodo mi orci, sit amet tempor libero vulputate in. Ut id gravida quam. Proin massa dolor, posuere nec metus eu, dignissim viverra nulla. Vestibulum quis neque bibendum, hendrerit diam et, fermentum diam. Sed risus nibh, suscipit in neque nec, bibendum interdum nibh. Aliquam ut enim a mi ultricies finibus. Nam tristique felis ac risus interdum molestie. Nulla venenatis, augue sed porttitor ultrices, lacus ante sollicitudin dui, vel vehicula ex enim ac mi.",
2473 "dropCap": false
2474 },
2475 )
2476 .with_id(Uuid::parse_str("0d47c02a-194e-42a4-927e-fb29a4fda39c")?),
2477 ],
2478 };
2479 create_page(
2480 &mut conn,
2481 course.id,
2482 teacher_user_id,
2483 Some(chapter_1.id),
2484 design_content,
2485 )
2486 .await?;
2487
2488 let content_b = CmsPageUpdate {
2490 chapter_id: Some(chapter_1.id),
2491 url_path: "/chapter-1/human-machine-interface".to_string(),
2492 title: "Human-machine interface".to_string(),
2493 exercises: vec![],
2494 exercise_slides: vec![],
2495 exercise_tasks: vec![],
2496 content: vec![
2497 GutenbergBlock::hero_section("Human-machine interface", "In the industrial design field of human–computer interaction, a user interface is the space where interactions between humans and machines occur.")
2498 .with_id(Uuid::parse_str("ae22ae64-c0e5-42e1-895a-4a49411a72e8")?),
2499 GutenbergBlock::block_with_name_and_attributes(
2500 "core/paragraph",
2501 attributes!{
2502 "content": "Sed venenatis, magna in ornare suscipit, orci ipsum consequat nulla, ut pulvinar libero metus et metus. Maecenas nec bibendum est. Donec quis ante elit. Nam in eros vitae urna aliquet vestibulum. Donec posuere laoreet facilisis. Aliquam auctor a tellus a tempus. Sed molestie leo eget commodo pellentesque. Curabitur lacinia odio nisl, eu sodales nunc placerat sit amet. Vivamus venenatis, risus vitae lobortis eleifend, odio nisi faucibus tortor, sed aliquet leo arcu et tellus. Donec ultrices consectetur nunc, non rhoncus sapien malesuada et. Nulla tempus ipsum vitae justo scelerisque, sed pretium neque fermentum. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur accumsan et ex pellentesque dignissim. Integer viverra libero quis tortor dignissim elementum.",
2503 "dropCap": false
2504 },
2505 )
2506 .with_id(Uuid::parse_str("b05a62ad-e5f7-432c-8c88-2976d971e7e1")?),
2507 GutenbergBlock::block_with_name_and_attributes(
2508 "core/paragraph",
2509 attributes!{
2510 "content": "Sed quis fermentum mi. Integer commodo turpis a fermentum tristique. Integer convallis, nunc sed scelerisque varius, mi tellus molestie metus, eu ultrices banana justo tellus non arcu. Cras euismod, cat lectus eu scelerisque mattis, odio ex ornare ipsum, a dapibus nulla leo maximus orci. Etiam laoreet venenatis lorem, vitae iaculis mauris. Nullam lobortis, tortor eget ullamcorper lobortis, tellus odio tincidunt dolor, vitae gravida nibh turpis ac sem. Integer non sodales eros.",
2511 "dropCap": false
2512 },
2513 )
2514 .with_id(Uuid::parse_str("db20e302-d4e2-4f56-a0b9-e48a4fbd5fa8")?),
2515 GutenbergBlock::block_with_name_and_attributes(
2516 "core/paragraph",
2517 attributes!{
2518 "content": "Vestibulum a scelerisque ante. Fusce interdum eros elit, posuere mattis sapien tristique id. Integer commodo mi orci, sit amet tempor libero vulputate in. Ut id gravida quam. Proin massa dolor, posuere nec metus eu, dignissim viverra nulla. Vestibulum quis neque bibendum, hendrerit diam et, fermentum diam. Sed risus nibh, suscipit in neque nec, bibendum interdum nibh. Aliquam ut enim a mi ultricies finibus. Nam tristique felis ac risus interdum molestie. Nulla venenatis, augue sed porttitor ultrices, lacus ante sollicitudin dui, vel vehicula ex enim ac mi.",
2519 "dropCap": false
2520 },
2521 )
2522 .with_id(Uuid::parse_str("c96f56d5-ea35-4aae-918a-72a36847a49c")?),
2523 ],
2524 };
2525 create_page(
2526 &mut conn,
2527 course.id,
2528 teacher_user_id,
2529 Some(chapter_1.id),
2530 content_b,
2531 )
2532 .await?;
2533
2534 let new_chapter_2 = NewChapter {
2536 chapter_number: 2,
2537 course_id: course.id,
2538 front_page_id: None,
2539 name: "User Experience".to_string(),
2540 color: None,
2541 opens_at: None,
2542 deadline: None,
2543 course_module_id: Some(default_module.id),
2544 };
2545 let (chapter_2, front_page_ch_2) = library::content_management::create_new_chapter(
2546 &mut conn,
2547 PKeyPolicy::Fixed((
2548 Uuid::new_v5(&course.id, b"5adff726-8910-4163-9fdb-e2f0f45c04d7"),
2549 Uuid::new_v5(&course.id, b"4d916791-5a09-4e3c-8201-c46509e0b2c7"),
2550 )),
2551 &new_chapter_2,
2552 teacher_user_id,
2553 &spec_fetcher,
2554 models_requests::fetch_service_info,
2555 )
2556 .await?;
2557 chapters::set_opens_at(&mut conn, chapter_2.id, Utc::now()).await?;
2558
2559 pages::update_page(
2560 &mut conn,
2561 PageUpdateArgs {
2562 page_id: front_page_ch_2.id,
2563 author: teacher_user_id,
2564 cms_page_update: CmsPageUpdate {
2565 url_path: "/chapter-2".to_string(),
2566 title: "User Experience".to_string(),
2567 chapter_id: Some(chapter_2.id),
2568 content: vec![
2569 GutenbergBlock::hero_section("User Experience", "The user experience is how a user interacts with and experiences a product, system or service. It includes a person's perceptions of utility, ease of use, and efficiency.")
2570 .with_id(Uuid::parse_str("c5c623f9-c7ca-4f8e-b04b-e91cecef217a")?),
2571 GutenbergBlock::empty_block_from_name("moocfi/pages-in-chapter".to_string())
2572 .with_id(Uuid::parse_str("37bbc4e9-2e96-45ea-a6f8-bbc7dc7f6be3")?),
2573 GutenbergBlock::empty_block_from_name("moocfi/exercises-in-chapter".to_string())
2574 .with_id(Uuid::parse_str("1bf7e311-75e8-48ec-bd55-e8f1185d76d0")?),
2575 ],
2576 exercises: vec![],
2577 exercise_slides: vec![],
2578 exercise_tasks: vec![],
2579 },
2580 retain_ids: true,
2581 history_change_reason: HistoryChangeReason::PageSaved,
2582 is_exam_page: false
2583 },
2584 &spec_fetcher,
2585 models_requests::fetch_service_info,
2586 )
2587 .await?;
2588 let page_content = CmsPageUpdate {
2590 chapter_id: Some(chapter_2.id),
2591 content: vec![
2592 GutenbergBlock::hero_section("User research", "User research focuses on understanding user behaviors, needs, and motivations through observation techniques, task analysis, and other feedback methodologies.")
2593 .with_id(Uuid::parse_str("a43f5460-b588-44ac-84a3-5fdcabd5d3f7")?),
2594 GutenbergBlock::block_with_name_and_attributes(
2595 "core/paragraph",
2596 attributes!{
2597 "content": "Sed venenatis, magna in ornare suscipit, orci ipsum consequat nulla, ut pulvinar libero metus et metus. Maecenas nec bibendum est. Donec quis ante elit. Nam in eros vitae urna aliquet vestibulum. Donec posuere laoreet facilisis. Aliquam auctor a tellus a tempus. Sed molestie leo eget commodo pellentesque. Curabitur lacinia odio nisl, eu sodales nunc placerat sit amet. Vivamus venenatis, risus vitae lobortis eleifend, odio nisi faucibus tortor, sed aliquet leo arcu et tellus. Donec ultrices consectetur nunc, non rhoncus sapien malesuada et. Nulla tempus ipsum vitae justo scelerisque, sed pretium neque fermentum. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur accumsan et ex pellentesque dignissim. Integer viverra libero quis tortor dignissim elementum.",
2598 "dropCap": false
2599 },
2600 )
2601 .with_id(Uuid::parse_str("816310e3-bbd7-44ae-87cb-3f40633a4b08")?),
2602 GutenbergBlock::block_with_name_and_attributes(
2603 "core/paragraph",
2604 attributes!{
2605 "content": "Sed quis fermentum mi. Integer commodo turpis a fermentum tristique. Integer convallis, nunc sed scelerisque varius, mi tellus molestie metus, eu ultrices justo tellus non arcu. Cras euismod, lectus eu scelerisque mattis, odio ex ornare ipsum, a dapibus nulla leo maximus orci. Etiam laoreet venenatis lorem, vitae iaculis mauris. Nullam lobortis, tortor eget ullamcorper lobortis, tellus odio tincidunt dolor, vitae gravida nibh turpis ac sem. Integer non sodales eros.",
2606 "dropCap": false
2607 },
2608 )
2609 .with_id(Uuid::parse_str("37aa6421-768e-49b9-b447-5f457e5192bc")?),
2610 GutenbergBlock::block_with_name_and_attributes(
2611 "core/paragraph",
2612 attributes!{
2613 "content": "Vestibulum a scelerisque ante. Fusce interdum eros elit, posuere mattis sapien tristique id. Integer commodo mi orci, sit amet tempor libero vulputate in. Ut id gravida quam. Proin massa dolor, posuere nec metus eu, dignissim viverra nulla. Vestibulum quis neque bibendum, hendrerit diam et, fermentum diam. Sed risus nibh, suscipit in neque nec, bibendum interdum nibh. Aliquam ut banana cat enim a mi ultricies finibus. Nam tristique felis ac risus interdum molestie. Nulla venenatis, augue sed porttitor ultrices, lacus ante sollicitudin dui, vel vehicula ex enim ac mi.",
2614 "dropCap": false
2615 },
2616 )
2617 .with_id(Uuid::parse_str("cf11a0fb-f56e-4e0d-bc12-51d920dbc278")?),
2618 ],
2619 exercises: vec![],
2620 exercise_slides: vec![],
2621 exercise_tasks: vec![],
2622 url_path: "/chapter-2/user-research".to_string(),
2623 title: "User research".to_string(),
2624 };
2625 create_page(
2626 &mut conn,
2627 course.id,
2628 teacher_user_id,
2629 Some(chapter_2.id),
2630 page_content,
2631 )
2632 .await?;
2633
2634 let page_content = include_str!("../../../assets/example-page.json");
2635 let parse_page_content = serde_json::from_str(page_content)?;
2636 create_page(
2637 &mut conn,
2638 course.id,
2639 teacher_user_id,
2640 Some(chapter_2.id),
2641 CmsPageUpdate {
2642 content: parse_page_content,
2643 exercises: vec![],
2644 exercise_slides: vec![],
2645 exercise_tasks: vec![],
2646 url_path: "/chapter-2/content-rendering".to_string(),
2647 title: "Content rendering".to_string(),
2648 chapter_id: Some(chapter_2.id),
2649 },
2650 )
2651 .await?;
2652
2653 create_page(
2656 &mut conn,
2657 course.id,
2658 teacher_user_id,
2659 Some(chapter_2.id),
2660 CmsPageUpdate {
2661 url_path: "/chapter-2/page-3".to_string(),
2662 title: "Page 3".to_string(),
2663 chapter_id: Some(chapter_2.id),
2664 exercises: vec![quizzes_exercise_5],
2665 exercise_slides: vec![quizzes_exercise_slide_5],
2666 exercise_tasks: vec![quizzes_exercise_task_5],
2667 content: vec![
2668 paragraph(
2669 "Second chapters third page",
2670 Uuid::new_v5(&course.id, b"4ebd0208-8328-5d69-8c44-ec50939c0967"),
2671 ),
2672 quizzes_exercise_block_5,
2673 ],
2674 },
2675 )
2676 .await?;
2677
2678 create_page(
2679 &mut conn,
2680 course.id,
2681 teacher_user_id,
2682 Some(chapter_2.id),
2683 CmsPageUpdate {
2684 url_path: "/chapter-2/page-4".to_string(),
2685 title: "Page 4".to_string(),
2686 chapter_id: Some(chapter_2.id),
2687 exercises: vec![quizzes_exercise_6],
2688 exercise_slides: vec![quizzes_exercise_slide_6],
2689 exercise_tasks: vec![quizzes_exercise_task_6],
2690 content: vec![
2691 paragraph(
2692 "Second chapters fourth page",
2693 Uuid::new_v5(&course.id, b"4841cabb-77a0-53cf-b539-39fbd060e73b"),
2694 ),
2695 quizzes_exercise_block_6,
2696 ],
2697 },
2698 )
2699 .await?;
2700
2701 create_page(
2702 &mut conn,
2703 course.id,
2704 teacher_user_id,
2705 Some(chapter_2.id),
2706 CmsPageUpdate {
2707 url_path: "/chapter-2/page-5".to_string(),
2708 title: "Page 5".to_string(),
2709 chapter_id: Some(chapter_2.id),
2710 exercises: vec![quizzes_exercise_7],
2711 exercise_slides: vec![quizzes_exercise_slide_7],
2712 exercise_tasks: vec![quizzes_exercise_task_7],
2713
2714 content: vec![
2715 paragraph(
2716 "Second chapters fifth page",
2717 Uuid::new_v5(&course.id, b"9a614406-e1b4-5920-8e0d-54d1a3ead5f3"),
2718 ),
2719 quizzes_exercise_block_7,
2720 ],
2721 },
2722 )
2723 .await?;
2724
2725 create_page(
2726 &mut conn,
2727 course.id,
2728 teacher_user_id,
2729 Some(chapter_2.id),
2730 CmsPageUpdate {
2731 url_path: "/chapter-2/page-6".to_string(),
2732 title: "Page 6".to_string(),
2733 chapter_id: Some(chapter_2.id),
2734 exercises: vec![quizzes_exercise_8],
2735 exercise_slides: vec![quizzes_exercise_slide_8],
2736 exercise_tasks: vec![quizzes_exercise_task_8],
2737 content: vec![
2738 paragraph(
2739 "Second chapters sixth page",
2740 Uuid::new_v5(&course.id, b"891de1ca-f3a9-506f-a268-3477ea4fdd27"),
2741 ),
2742 quizzes_exercise_block_8,
2743 ],
2744 },
2745 )
2746 .await?;
2747
2748 course_instance_enrollments::insert_enrollment_and_set_as_current(
2750 &mut conn,
2751 NewCourseInstanceEnrollment {
2752 course_id: course.id,
2753 course_instance_id: default_instance.id,
2754 user_id: langs_user_id,
2755 },
2756 )
2757 .await?;
2758 user_ai_usage_notice_acknowledgements::acknowledge(&mut conn, langs_user_id, course.id).await?;
2759
2760 Ok(course.id)
2761}
2762
2763pub async fn seed_peer_review_course_without_submissions(
2764 course_id: Uuid,
2765 course_name: &str,
2766 course_slug: &str,
2767 common_course_data: CommonCourseData,
2768) -> Result<Uuid> {
2769 let CommonCourseData {
2770 db_pool,
2771 organization_id: org,
2772 teacher_user_id,
2773 student_user_id: _,
2774 langs_user_id: _,
2775 example_normal_user_ids: _,
2776 jwt_key: _jwt_key,
2777 base_url: _base_url,
2778 } = common_course_data;
2779 let spec_fetcher = get_seed_spec_fetcher();
2780 info!("inserting sample course {}", course_name);
2781 let mut conn = db_pool.acquire().await?;
2782 let new_course = NewCourse {
2783 name: course_name.to_string(),
2784 organization_id: org,
2785 slug: course_slug.to_string(),
2786 language_code: "en".to_string(),
2787 teacher_in_charge_name: "admin".to_string(),
2788 teacher_in_charge_email: "admin@example.com".to_string(),
2789 description: "Sample course.".to_string(),
2790 is_draft: false,
2791 is_test_mode: false,
2792 is_unlisted: false,
2793 copy_user_permissions: false,
2794 is_joinable_by_code_only: false,
2795 join_code: None,
2796 ask_marketing_consent: false,
2797 flagged_answers_threshold: Some(3),
2798 can_add_chatbot: false,
2799 };
2800
2801 let (course, _front_page, _, default_module) = library::content_management::create_new_course(
2802 &mut conn,
2803 PKeyPolicy::Fixed(CreateNewCourseFixedIds {
2804 course_id,
2805 default_course_instance_id: Uuid::new_v5(
2806 &course_id,
2807 b"7344f1c8-b7ce-4c7d-ade2-5f39997bd454",
2808 ),
2809 }),
2810 new_course,
2811 teacher_user_id,
2812 &spec_fetcher,
2813 models_requests::fetch_service_info,
2814 )
2815 .await?;
2816 courses::set_cheater_detection_enabled(&mut conn, course.id, false).await?;
2817
2818 course_instances::insert(
2819 &mut conn,
2820 PKeyPolicy::Fixed(Uuid::new_v5(
2821 &course_id,
2822 b"67f077b4-0562-47ae-a2b9-db2f08f168a9",
2823 )),
2824 NewCourseInstance {
2825 course_id: course.id,
2826 name: Some("Non-default instance"),
2827 description: Some("This is a non-default instance"),
2828 support_email: Some("contact@example.com"),
2829 teacher_in_charge_name: "admin",
2830 teacher_in_charge_email: "admin@example.com",
2831 opening_time: None,
2832 closing_time: None,
2833 },
2834 )
2835 .await?;
2836
2837 let new_chapter = NewChapter {
2840 chapter_number: 1,
2841 course_id: course.id,
2842 front_page_id: None,
2843 name: "The Basics".to_string(),
2844 color: None,
2845 opens_at: None,
2846 deadline: Some(Utc.with_ymd_and_hms(2225, 1, 1, 23, 59, 59).unwrap()),
2847
2848 course_module_id: Some(default_module.id),
2849 };
2850
2851 let (chapter_1, _front_page_1) = library::content_management::create_new_chapter(
2852 &mut conn,
2853 PKeyPolicy::Fixed((
2854 Uuid::new_v5(&course_id, b"bfc557e1-0f8e-4f10-8e21-d7d8ffe50a3a"),
2855 Uuid::new_v5(&course_id, b"b1e392db-482a-494e-9cbb-c87bbc70e340"),
2856 )),
2857 &new_chapter,
2858 teacher_user_id,
2859 &spec_fetcher,
2860 models_requests::fetch_service_info,
2861 )
2862 .await?;
2863
2864 chapters::set_opens_at(&mut conn, chapter_1.id, Utc::now()).await?;
2865
2866 let welcome_page = NewCoursePage::new(
2867 course.id,
2868 1,
2869 "/welcome",
2870 "Welcome to Introduction to peer reviews",
2871 );
2872 let (_page, _) = pages::insert_course_page(&mut conn, &welcome_page, teacher_user_id).await?;
2873 let hidden_page = welcome_page
2874 .followed_by("/hidden", "Hidden Page")
2875 .set_hidden(true)
2876 .set_content(vec![GutenbergBlock::paragraph(
2877 "You found the secret of the project 331!",
2878 )]);
2879 let (_page, _) = pages::insert_course_page(&mut conn, &hidden_page, teacher_user_id).await?;
2880
2881 info!("sample exercises");
2882 let block_id_1 = Uuid::new_v5(&course_id, b"4ef933d8-170f-4437-a5af-bc7690cfac5a");
2883 let block_id_2 = Uuid::new_v5(&course_id, b"35510467-9a7b-46de-9878-d9d34a1821a4");
2884 let exercise_1_id = Uuid::new_v5(&course_id, b"bae98f14-9ffd-4647-8f28-fe4a5967d6e9");
2885 let exercise_1_slide_1_id = Uuid::new_v5(&course_id, b"6d3feb9c-fc95-4908-803f-1b0d0e3f2c18");
2886 let exercise_1_slide_1_task_1_id =
2887 Uuid::new_v5(&course_id, b"47517fe6-d5e2-4b8f-8d94-541a4d849aed");
2888 let exercise_1_slide_1_task_1_spec_1_id =
2889 Uuid::new_v5(&course_id, b"847a2144-e55b-4c2f-a6a7-98bbe7927d10");
2890 let exercise_1_slide_1_task_1_spec_2_id =
2891 Uuid::new_v5(&course_id, b"979a00a7-2e8a-4294-9e46-3367c372864f");
2892 let exercise_1_slide_1_task_1_spec_3_id =
2893 Uuid::new_v5(&course_id, b"b354830c-38c7-4b83-8370-0e7222272c56");
2894
2895 let (exercise_block_1, exercise_1, slide_1, task_1) = create_best_exercise(
2896 block_id_2,
2897 exercise_1_slide_1_task_1_spec_1_id,
2898 exercise_1_slide_1_task_1_spec_2_id,
2899 exercise_1_slide_1_task_1_spec_3_id,
2900 Some("ManualReviewEverything".to_string()),
2901 CommonExerciseData {
2902 exercise_id: exercise_1_id,
2903 exercise_slide_id: exercise_1_slide_1_id,
2904 exercise_task_id: exercise_1_slide_1_task_1_id,
2905 block_id: block_id_1,
2906 },
2907 );
2908
2909 create_page(
2910 &mut conn,
2911 course.id,
2912 teacher_user_id,
2913 Some(chapter_1.id),
2914 CmsPageUpdate {
2915 url_path: "/chapter-1/page-1".to_string(),
2916 title: "Page One".to_string(),
2917 chapter_id: Some(chapter_1.id),
2918 exercises: vec![exercise_1],
2919 exercise_slides: vec![slide_1],
2920 exercise_tasks: vec![task_1],
2921 content: vec![exercise_block_1],
2922 },
2923 )
2924 .await?;
2925
2926 create_best_peer_review(
2927 &mut conn,
2928 course_id,
2929 exercise_1_id,
2930 ManualReviewEverything,
2931 3.0,
2932 true,
2933 2,
2934 1,
2935 )
2936 .await?;
2937
2938 let block_id_3 = Uuid::new_v5(&course_id, b"4b57812a-6509-4783-a746-3e382adf5060");
2939 let block_id_4 = Uuid::new_v5(&course_id, b"d315f5bb-306f-478b-846c-ca5f1407f2db");
2940 let exercise_2_id = Uuid::new_v5(&course_id, b"39f23830-d2eb-4232-b6f7-78822f0e0fbd");
2941 let exercise_2_slide_1_id = Uuid::new_v5(&course_id, b"cbbbee55-511b-45be-9d95-1fa9273497ee");
2942 let exercise_2_slide_1_task_1_id =
2943 Uuid::new_v5(&course_id, b"a2ae64bd-9518-4c2b-88c1-49ba103f14ff");
2944 let exercise_2_slide_1_task_1_spec_1_id =
2945 Uuid::new_v5(&course_id, b"f1cd2f78-a489-4cae-a656-86aa574faf19");
2946 let exercise_2_slide_1_task_1_spec_2_id =
2947 Uuid::new_v5(&course_id, b"5435b9ae-d811-43b6-b208-23f64267eef1");
2948 let exercise_2_slide_1_task_1_spec_3_id =
2949 Uuid::new_v5(&course_id, b"9f6e4ad4-b9f5-40cf-b071-642da7058fec");
2950
2951 let (exercise_block_2, exercise_2, slide_1, task_1) = create_best_exercise(
2952 block_id_4,
2953 exercise_2_slide_1_task_1_spec_1_id,
2954 exercise_2_slide_1_task_1_spec_2_id,
2955 exercise_2_slide_1_task_1_spec_3_id,
2956 Some("AutomaticallyGradeOrManualReviewByAverage".to_string()),
2957 CommonExerciseData {
2958 exercise_id: exercise_2_id,
2959 exercise_slide_id: exercise_2_slide_1_id,
2960 exercise_task_id: exercise_2_slide_1_task_1_id,
2961 block_id: block_id_3,
2962 },
2963 );
2964
2965 create_page(
2966 &mut conn,
2967 course.id,
2968 teacher_user_id,
2969 Some(chapter_1.id),
2970 CmsPageUpdate {
2971 url_path: "/chapter-1/page-2".to_string(),
2972 title: "Page Two".to_string(),
2973 chapter_id: Some(chapter_1.id),
2974 exercises: vec![exercise_2],
2975 exercise_slides: vec![slide_1],
2976 exercise_tasks: vec![task_1],
2977 content: vec![exercise_block_2],
2978 },
2979 )
2980 .await?;
2981
2982 create_best_peer_review(
2983 &mut conn,
2984 course_id,
2985 exercise_2_id,
2986 AutomaticallyGradeOrManualReviewByAverage,
2987 3.0,
2988 true,
2989 2,
2990 1,
2991 )
2992 .await?;
2993
2994 let block_id_5 = Uuid::new_v5(&course_id, b"591b1612-36c8-4f02-841b-d5f95be9b410");
2995 let block_id_6 = Uuid::new_v5(&course_id, b"2adbaaef-6213-4b83-ba8f-827e5a4f084f");
2996 let exercise_3_id = Uuid::new_v5(&course_id, b"3b4e964b-8992-4595-92ad-bdb1721e9352");
2997 let exercise_3_slide_1_id = Uuid::new_v5(&course_id, b"d0596f5c-885b-483e-9f59-271b289e4220");
2998 let exercise_3_slide_1_task_1_id =
2999 Uuid::new_v5(&course_id, b"170a97c9-2e75-4817-af17-5e45bd362260");
3000 let exercise_3_slide_1_task_1_spec_1_id =
3001 Uuid::new_v5(&course_id, b"b74450cf-e8a5-4689-b2a4-7a0ed491dcbc");
3002 let exercise_3_slide_1_task_1_spec_2_id =
3003 Uuid::new_v5(&course_id, b"f27a8e35-2d72-406d-9c99-fd8b7c1991a3");
3004 let exercise_3_slide_1_task_1_spec_3_id =
3005 Uuid::new_v5(&course_id, b"31443721-fc55-4ea6-9b2a-2da8a6a991df");
3006
3007 let (exercise_block_3, exercise_3, slide_1, task_1) = create_best_exercise(
3008 block_id_6,
3009 exercise_3_slide_1_task_1_spec_1_id,
3010 exercise_3_slide_1_task_1_spec_2_id,
3011 exercise_3_slide_1_task_1_spec_3_id,
3012 Some("AutomaticallyGradeByAverage".to_string()),
3013 CommonExerciseData {
3014 exercise_id: exercise_3_id,
3015 exercise_slide_id: exercise_3_slide_1_id,
3016 exercise_task_id: exercise_3_slide_1_task_1_id,
3017 block_id: block_id_5,
3018 },
3019 );
3020
3021 create_page(
3022 &mut conn,
3023 course.id,
3024 teacher_user_id,
3025 Some(chapter_1.id),
3026 CmsPageUpdate {
3027 url_path: "/chapter-1/page-3".to_string(),
3028 title: "Page Three".to_string(),
3029 chapter_id: Some(chapter_1.id),
3030 exercises: vec![exercise_3],
3031 exercise_slides: vec![slide_1],
3032 exercise_tasks: vec![task_1],
3033 content: vec![exercise_block_3],
3034 },
3035 )
3036 .await?;
3037
3038 create_best_peer_review(
3039 &mut conn,
3040 course_id,
3041 exercise_3_id,
3042 AutomaticallyGradeByAverage,
3043 3.0,
3044 true,
3045 2,
3046 1,
3047 )
3048 .await?;
3049
3050 let block_id_7 = Uuid::new_v5(&course_id, b"80e97fbc-ebc1-46f3-a19c-04cdb9f3d349");
3051 let block_id_8 = Uuid::new_v5(&course_id, b"db818c1f-0667-4050-9289-7224a8ca3c5c");
3052 let exercise_4_id = Uuid::new_v5(&course_id, b"65cde761-6ccd-4804-8343-c85b1d3d6fc4");
3053 let exercise_4_slide_1_id = Uuid::new_v5(&course_id, b"b37771bc-37d0-4cae-b06d-c35256f289a5");
3054 let exercise_4_slide_1_task_1_id =
3055 Uuid::new_v5(&course_id, b"0ecaff02-d8cf-44c3-be8c-ea2449c02d0f");
3056 let exercise_4_slide_1_task_1_spec_1_id =
3057 Uuid::new_v5(&course_id, b"caaf7ec5-fd2b-4e07-b185-58b8070b059e");
3058 let exercise_4_slide_1_task_1_spec_2_id =
3059 Uuid::new_v5(&course_id, b"f92ba66c-fe8a-4711-b25a-73a13c451543");
3060 let exercise_4_slide_1_task_1_spec_3_id =
3061 Uuid::new_v5(&course_id, b"c17f23ca-7daa-40dd-b390-1ac8531dd17d");
3062
3063 let (exercise_block_1, exercise_1, slide_1, task_1) = create_best_exercise(
3064 block_id_8,
3065 exercise_4_slide_1_task_1_spec_1_id,
3066 exercise_4_slide_1_task_1_spec_2_id,
3067 exercise_4_slide_1_task_1_spec_3_id,
3068 Some("ManualReviewEverything2".to_string()),
3069 CommonExerciseData {
3070 exercise_id: exercise_4_id,
3071 exercise_slide_id: exercise_4_slide_1_id,
3072 exercise_task_id: exercise_4_slide_1_task_1_id,
3073 block_id: block_id_7,
3074 },
3075 );
3076
3077 create_page(
3078 &mut conn,
3079 course.id,
3080 teacher_user_id,
3081 Some(chapter_1.id),
3082 CmsPageUpdate {
3083 url_path: "/chapter-1/page-4".to_string(),
3084 title: "Page Four".to_string(),
3085 chapter_id: Some(chapter_1.id),
3086 exercises: vec![exercise_1],
3087 exercise_slides: vec![slide_1],
3088 exercise_tasks: vec![task_1],
3089 content: vec![exercise_block_1],
3090 },
3091 )
3092 .await?;
3093
3094 create_best_peer_review(
3095 &mut conn,
3096 course_id,
3097 exercise_4_id,
3098 ManualReviewEverything,
3099 3.0,
3100 true,
3101 2,
3102 1,
3103 )
3104 .await?;
3105
3106 let block_id_9 = Uuid::new_v5(&course_id, b"54349cc8-dbba-4223-b5e0-71fafdfe8fd3");
3107 let block_id_10 = Uuid::new_v5(&course_id, b"ee05ad17-07dc-4c3b-be63-67bd2a4ac46a");
3108 let exercise_5_id = Uuid::new_v5(&course_id, b"31717e20-8fe5-451c-a7d3-bca09d0ea14f");
3109 let exercise_5_slide_1_id = Uuid::new_v5(&course_id, b"9bd990d1-3cd6-4e23-b372-8860ebd8bac5");
3110 let exercise_5_slide_1_task_1_id =
3111 Uuid::new_v5(&course_id, b"fe5da9f8-aaae-4b05-9cf9-29f3cde55bd7");
3112 let exercise_5_slide_1_task_1_spec_1_id =
3113 Uuid::new_v5(&course_id, b"5efb1377-70af-455f-ad78-cddd0bd6cbb1");
3114 let exercise_5_slide_1_task_1_spec_2_id =
3115 Uuid::new_v5(&course_id, b"f92ba66c-fe8a-4711-b25a-73a13c451543");
3116 let exercise_5_slide_1_task_1_spec_3_id =
3117 Uuid::new_v5(&course_id, b"75bbc9f6-84f2-4182-80d1-07bd7c435d6c");
3118
3119 let (exercise_block_1, exercise_1, slide_1, task_1) = create_best_exercise(
3120 block_id_10,
3121 exercise_5_slide_1_task_1_spec_1_id,
3122 exercise_5_slide_1_task_1_spec_2_id,
3123 exercise_5_slide_1_task_1_spec_3_id,
3124 Some("Can give extra reviews".to_string()),
3125 CommonExerciseData {
3126 exercise_id: exercise_5_id,
3127 exercise_slide_id: exercise_5_slide_1_id,
3128 exercise_task_id: exercise_5_slide_1_task_1_id,
3129 block_id: block_id_9,
3130 },
3131 );
3132
3133 create_page(
3134 &mut conn,
3135 course.id,
3136 teacher_user_id,
3137 Some(chapter_1.id),
3138 CmsPageUpdate {
3139 url_path: "/chapter-1/can-give-extra-reviews".to_string(),
3140 title: "Can give extra peer reviews".to_string(),
3141 chapter_id: Some(chapter_1.id),
3142 exercises: vec![exercise_1],
3143 exercise_slides: vec![slide_1],
3144 exercise_tasks: vec![task_1],
3145 content: vec![exercise_block_1],
3146 },
3147 )
3148 .await?;
3149
3150 create_best_peer_review(
3151 &mut conn,
3152 course_id,
3153 exercise_5_id,
3154 AutomaticallyGradeByAverage,
3155 3.0,
3156 true,
3157 3,
3158 2,
3159 )
3160 .await?;
3161
3162 Ok(course.id)
3163}