headless_lms_server/programs/seed/seed_courses/
mod.rs

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