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