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