Skip to main content

headless_lms_server/programs/seed/seed_courses/
mod.rs

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    // Seeded courses are completed in seconds by system tests, which would flag every seeded user
134    // and break the suite, so disable cheater detection. Callers that need detection on (e.g. the
135    // dedicated suspected-cheaters course) re-enable it after seeding.
136    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    // chapters and pages
163
164    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    // enrollments, user exercise states, submissions, grades
1703    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        // Pre-acknowledge the AI-usage notice for seeded enrollments so the dialog does not
1716        // block already-enrolled users (e.g. in system tests).
1717        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        // this submission is for the same exercise, but no points are removed due to the update strategy
1733        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    // feedback
1824    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    // edit proposals
1909    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    // acronyms
1954    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    // create_best_peer_review(&mut conn, course.id, Some(exercise_1_id)).await?;
1959
1960    // certificate configuration
1961    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    // Add roles
2010    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    // Create new course
2031    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    // Exercises
2067    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    // FAQ, we should add card/accordion block to visualize here.
2360
2361    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    // Chapter-1
2369    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    // /chapter-1/design
2424    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    // /chapter-1/human-machine-interface
2489    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    // Chapter-2
2535    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    // /chapter-2/user-research
2589    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    // Multiple choice
2654
2655    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    // enrollments
2749    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    // chapters and pages
2838
2839    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}