Skip to main content

headless_lms_server/programs/seed/seed_courses/
mod.rs

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