headless_lms_server/programs/seed/
seed_courses.rs

1use std::sync::Arc;
2
3use crate::domain::models_requests::{self, JwtKey};
4use crate::programs::seed::builder::chapter::ChapterBuilder;
5use crate::programs::seed::builder::context::SeedContext;
6use crate::programs::seed::builder::course::{CourseBuilder, CourseInstanceConfig};
7use crate::programs::seed::builder::exercise::{ExerciseBuilder, ExerciseIds};
8use crate::programs::seed::builder::module::ModuleBuilder;
9use crate::programs::seed::builder::page::PageBuilder;
10use crate::programs::seed::seed_helpers::{
11    create_best_exercise, create_best_peer_review, create_page, example_exercise_flexible,
12    paragraph, quizzes_exercise, submit_and_grade,
13};
14use anyhow::Result;
15use chrono::{TimeZone, Utc};
16
17use serde_json::json;
18
19use headless_lms_models::{
20    PKeyPolicy, certificate_configuration_to_requirements, certificate_configurations, chapters,
21    chapters::NewChapter,
22    course_instance_enrollments,
23    course_instance_enrollments::NewCourseInstanceEnrollment,
24    course_instances::{self, NewCourseInstance},
25    course_modules::{self, NewCourseModule},
26    courses::NewCourse,
27    feedback,
28    feedback::{FeedbackBlock, NewFeedback},
29    file_uploads, glossary, library,
30    library::content_management::CreateNewCourseFixedIds,
31    page_history::HistoryChangeReason,
32    pages::CmsPageUpdate,
33    pages::{self, NewCoursePage},
34    peer_or_self_review_configs::PeerReviewProcessingStrategy::{
35        AutomaticallyGradeByAverage, AutomaticallyGradeOrManualReviewByAverage,
36        ManualReviewEverything,
37    },
38    proposed_block_edits::NewProposedBlockEdit,
39    proposed_page_edits,
40    proposed_page_edits::NewProposedPageEdits,
41    url_redirections,
42};
43use headless_lms_models::{certificate_configurations::DatabaseCertificateConfiguration, roles};
44use headless_lms_models::{
45    pages::PageUpdateArgs,
46    roles::{RoleDomain, UserRole},
47};
48use headless_lms_utils::{attributes, document_schema_processor::GutenbergBlock};
49
50use sqlx::{Pool, Postgres};
51use tracing::info;
52use uuid::Uuid;
53
54use super::{
55    seed_helpers::{CommonExerciseData, get_seed_spec_fetcher, heading},
56    seed_users::SeedUsersResult,
57};
58
59#[derive(Clone)]
60pub struct CommonCourseData {
61    pub db_pool: Pool<Postgres>,
62    pub organization_id: Uuid,
63    pub teacher_user_id: Uuid,
64    pub student_user_id: Uuid,
65    pub langs_user_id: Uuid,
66    pub example_normal_user_ids: Arc<Vec<Uuid>>,
67    pub jwt_key: Arc<JwtKey>,
68    pub base_url: String,
69}
70
71pub async fn seed_sample_course(
72    course_id: Uuid,
73    course_name: &str,
74    course_slug: &str,
75    common_course_data: CommonCourseData,
76    can_add_chatbot: bool,
77    seed_users_result: SeedUsersResult,
78) -> Result<Uuid> {
79    let CommonCourseData {
80        db_pool,
81        organization_id: org,
82        teacher_user_id,
83        student_user_id: student,
84        langs_user_id,
85        example_normal_user_ids: users,
86        jwt_key: _jwt_key,
87        base_url: _base_url,
88    } = common_course_data;
89    let spec_fetcher = get_seed_spec_fetcher();
90    info!("inserting sample course {}", course_name);
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: serde_json::json!([
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: serde_json::json!([
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: serde_json::json!([
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: serde_json::json!([
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: serde_json::json!([
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: serde_json::json!([
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: serde_json::json!([
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: serde_json::json!([
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: serde_json::json!([
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: serde_json::json!([
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        );
1255    create_page(
1256        &mut conn,
1257        course.id,
1258        teacher_user_id,
1259        Some(chapter_1.id),
1260        CmsPageUpdate {
1261            url_path: "/chapter-1/complicated-exercise".to_string(),
1262            title: "Complicated exercise page".to_string(),
1263            chapter_id: Some(chapter_1.id),
1264            exercises: vec![multi_exercise_1],
1265            exercise_slides: multi_exercise_1_slides,
1266            exercise_tasks: multi_exercise_1_tasks,
1267            content: serde_json::json!([
1268                paragraph(
1269                    "This page has a complicated exercise.",
1270                    Uuid::new_v5(&course_id, b"86f1b595-ec82-43a6-954f-c1f8de3d53ac")
1271                ),
1272                multi_exercise_block_1
1273            ]),
1274        },
1275    )
1276    .await?;
1277
1278    let exercise_5_id = Uuid::new_v5(&course_id, b"8bb4faf4-9a34-4df7-a166-89ade530d0f6");
1279    let exercise_5_slide_1_id = Uuid::new_v5(&course_id, b"b99d1041-7835-491e-a1c8-b47eee8e7ab4");
1280    let exercise_5_slide_1_task_1_id =
1281        Uuid::new_v5(&course_id, b"a6508b8a-f58e-43ac-9f02-785575e716f5");
1282    let exercise_5_slide_1_task_1_spec_1_id =
1283        Uuid::new_v5(&course_id, b"fe464d17-2365-4e65-8b33-e0ebb5a67836");
1284    let exercise_5_slide_1_task_1_spec_2_id =
1285        Uuid::new_v5(&course_id, b"6633ffc7-c76e-4049-840e-90eefa6b49e8");
1286    let exercise_5_slide_1_task_1_spec_3_id =
1287        Uuid::new_v5(&course_id, b"d77fb97d-322c-4c5f-a405-8978a8cfb0a9");
1288    let (exercise_block_5, exercise_5, exercise_slide_5, exercise_task_5) = create_best_exercise(
1289        Uuid::new_v5(&course_id, b"fe464d17-2365-4e65-8b33-e0ebb5a67836"),
1290        exercise_5_slide_1_task_1_spec_1_id,
1291        exercise_5_slide_1_task_1_spec_2_id,
1292        exercise_5_slide_1_task_1_spec_3_id,
1293        Some("Best exercise".to_string()),
1294        CommonExerciseData {
1295            exercise_id: exercise_5_id,
1296            exercise_slide_id: exercise_5_slide_1_id,
1297            exercise_task_id: exercise_5_slide_1_task_1_id,
1298            block_id: Uuid::new_v5(&course_id, b"e869c471-b1b7-42a0-af05-dffd1d86a7bb"),
1299        },
1300    );
1301    create_page(
1302        &mut conn,
1303        course.id,
1304        teacher_user_id,
1305        Some(chapter_2.id),
1306        CmsPageUpdate {
1307            url_path: "/chapter-2/intro".to_string(),
1308            title: "In the second chapter...".to_string(),
1309            chapter_id: Some(chapter_2.id),
1310            exercises: vec![exercise_5],
1311            exercise_slides: vec![exercise_slide_5],
1312            exercise_tasks: vec![exercise_task_5],
1313            content: serde_json::json!([exercise_block_5]),
1314        },
1315    )
1316    .await?;
1317
1318    let multi_exercise_2_id = Uuid::new_v5(&course_id, b"057def52-6895-4374-a7f5-1849d136f1f4");
1319    let multi_exercise_2_slide_1_id =
1320        Uuid::new_v5(&course_id, b"fa02d232-8e33-4e20-9c20-d3b03fa89eb5");
1321    let multi_exercise_2_slide_1_task_1_id =
1322        Uuid::new_v5(&course_id, b"6c72f989-4d7e-4b22-b63c-3c51c631abcb");
1323    let multi_exercise_2_slide_1_task_2_id =
1324        Uuid::new_v5(&course_id, b"9445e8a3-6a86-4492-96b8-971f7b7acedd");
1325    let multi_exercise_2_slide_1_task_3_id =
1326        Uuid::new_v5(&course_id, b"8fbdbc4d-0c62-4b70-bb31-4c5fbb4ea6dd");
1327    let (multi_exercise_block_2, multi_exercise_2, multi_exercise_2_slides, multi_exercise_2_tasks) =
1328        example_exercise_flexible(
1329            multi_exercise_2_id,
1330            "Multiple task quizzes exercise".to_string(),
1331            vec![(
1332                multi_exercise_2_slide_1_id,
1333                vec![
1334                    (
1335                        multi_exercise_2_slide_1_task_1_id,
1336                        "quizzes".to_string(),
1337                        serde_json::json!([paragraph(
1338                            "First question.",
1339                            Uuid::new_v5(&course_id, b"c8414adc-4e99-4d93-b926-e257517ff934")
1340                        )]),
1341                        serde_json::json!({
1342                            "id": "e8a81dad-d616-44ab-bd6e-ec5430b454be",
1343                            "body": "very hard",
1344                            "open": "2021-12-17T07:15:33.479Z",
1345                            "part": 0,
1346                            "items": [{
1347                                "id": "ba2b179a-fab7-4eb7-896f-ef841eeda8e5",
1348                                "body": null,
1349                                "type": "multiple-choice",
1350                                "multi": false,
1351                                "multipleChoiceMultipleOptionsGradingPolicy": "default",
1352                                "order": 0,
1353                                "title": "Select all correct answers from below",
1354                                "quizId": "e8a81dad-d616-44ab-bd6e-ec5430b454be",
1355                                "options": [
1356                                    {
1357                                        "id": "bb172040-753d-40ef-bded-a487b668905a",
1358                                        "body": "Correct",
1359                                        "order": 1,
1360                                        "title": null,
1361                                        "quizItemId": "ba2b179a-fab7-4eb7-896f-ef841eeda8e5",
1362                                        "correct":true,
1363                                        "messageAfterSubmissionWhenSelected": "This is correct option",
1364                                        "additionalCorrectnessExplanationOnModelSolution": null
1365                                    },
1366                                    {
1367                                        "id": "a1534c77-3379-4462-b67c-f55a17aa6499",
1368                                        "body": "Correct",
1369                                        "order": 2,
1370                                        "title": null,
1371                                        "quizItemId": "ba2b179a-fab7-4eb7-896f-ef841eeda8e5",
1372                                        "correct":true,
1373                                        "messageAfterSubmissionWhenSelected": "This is correct option",
1374                                        "additionalCorrectnessExplanationOnModelSolution": null,
1375                                    },
1376                                    {
1377                                        "id": "828328e6-5491-4ccb-b6f7-1df0796db44e",
1378                                        "body": "Incorrect",
1379                                        "order": 3,
1380                                        "title": null,
1381                                        "quizItemId": "ba2b179a-fab7-4eb7-896f-ef841eeda8e5",
1382                                        "correct":false,
1383                                        "messageAfterSubmissionWhenSelected": "This is incorrect option",
1384                                        "additionalCorrectnessExplanationOnModelSolution": null
1385                                    },
1386                                ],
1387                                "allAnswersCorrect": false,
1388                                "sharedOptionFeedbackMessage": null,
1389                                "usesSharedOptionFeedbackMessage": false
1390                            }],
1391                            "title": "Pretty good exercise",
1392                            "tries": 1,
1393                            "points": 2,
1394                            "section": 0,
1395                            "courseId": "39c7879a-e61f-474a-8f18-7fc476ccc3a0",
1396                            "deadline": "2021-12-17T07:15:33.479Z",
1397                            "createdAt": "2021-12-17T07:15:33.479Z",
1398                            "updatedAt": "2021-12-17T07:15:33.479Z",
1399                            "autoReject": false,
1400                            "autoConfirm": true,
1401                            "randomizeOptions": false,
1402                            "triesLimited": true,
1403                            "submitMessage": "This is an extra submit message from the teacher.",
1404                            "excludedFromScore": true,
1405                            "grantPointsPolicy": "grant_whenever_possible",
1406                            "awardPointsEvenIfWrong": false}),
1407                    ),
1408                    (
1409                        multi_exercise_2_slide_1_task_2_id,
1410                        "quizzes".to_string(),
1411                        serde_json::json!([paragraph(
1412                            "Second question.",
1413                            Uuid::new_v5(&course_id, b"fcdeb228-a36e-499b-9cf0-dfb264a2cf34")
1414                        )]),
1415                        serde_json::json!({
1416                            "id": "67fc1eea-541c-4247-a852-090c71d7a9d1",
1417                            "body": "very hard",
1418                            "open": "2021-12-17T07:15:33.479Z",
1419                            "part": 0,
1420                            "items": [{
1421                                "id": "7640b8db-eee0-4685-b031-dde26f183c9c",
1422                                "body": null,
1423                                "type": "multiple-choice",
1424                                "multi": false,
1425                                "multipleChoiceMultipleOptionsGradingPolicy": "default",
1426                                "order": 0,
1427                                "title": "Select all correct answers from below",
1428                                "quizId": "67fc1eea-541c-4247-a852-090c71d7a9d1",
1429                                "options": [
1430                                    {
1431                                        "id": "446034b8-e049-4973-a634-5561da4b6d8e",
1432                                        "body": "Correct",
1433                                        "order": 1,
1434                                        "title": null,
1435                                        "quizItemId": "7640b8db-eee0-4685-b031-dde26f183c9c",
1436                                        "correct":true,
1437                                        "messageAfterSubmissionWhenSelected": "This is correct option",
1438                                        "additionalCorrectnessExplanationOnModelSolution": null
1439                                    },
1440                                    {
1441                                        "id": "a4a0c48a-b171-4855-b738-b248f1e50561",
1442                                        "body": "Incorrect",
1443                                        "order": 2,
1444                                        "title": null,
1445                                        "quizItemId": "7640b8db-eee0-4685-b031-dde26f183c9c",
1446                                        "correct":false,
1447                                        "messageAfterSubmissionWhenSelected": "This is incorrect option",
1448                                        "additionalCorrectnessExplanationOnModelSolution": null,
1449                                    },
1450                                    {
1451                                        "id": "f65330da-de15-47f3-9a4d-9f47eb6a5f5a",
1452                                        "body": "Correct",
1453                                        "order": 3,
1454                                        "title": null,
1455                                        "quizItemId": "7640b8db-eee0-4685-b031-dde26f183c9c",
1456                                        "correct":true,
1457                                        "messageAfterSubmissionWhenSelected": "This is correct option",
1458                                        "additionalCorrectnessExplanationOnModelSolution": null
1459                                    },
1460                                ],
1461                                "allAnswersCorrect": false,
1462                                "sharedOptionFeedbackMessage": null,
1463                                "usesSharedOptionFeedbackMessage": false
1464                            }],
1465                            "title": "Pretty good exercise",
1466                            "tries": 1,
1467                            "points": 2,
1468                            "section": 0,
1469                            "courseId": "39c7879a-e61f-474a-8f18-7fc476ccc3a0",
1470                            "deadline": "2021-12-17T07:15:33.479Z",
1471                            "createdAt": "2021-12-17T07:15:33.479Z",
1472                            "updatedAt": "2021-12-17T07:15:33.479Z",
1473                            "autoReject": false,
1474                            "autoConfirm": true,
1475                            "randomizeOptions": false,
1476                            "triesLimited": true,
1477                            "submitMessage": "This is an extra submit message from the teacher.",
1478                            "excludedFromScore": true,
1479                            "grantPointsPolicy": "grant_whenever_possible",
1480                            "awardPointsEvenIfWrong": false}),
1481                    ),
1482                    (
1483                        multi_exercise_2_slide_1_task_3_id,
1484                        "quizzes".to_string(),
1485                        serde_json::json!([paragraph(
1486                            "Third question.",
1487                            Uuid::new_v5(&course_id, b"13b75f4e-b02d-41fa-b5bc-79adf22d9aef")
1488                        )]),
1489                        serde_json::json!({
1490                            "id": "3f332295-b409-4fa8-a690-e5afd4e06b7a",
1491                            "body": "very hard",
1492                            "open": "2021-12-17T07:15:33.479Z",
1493                            "part": 0,
1494                            "items": [{
1495                                "id": "a72b53f5-97c4-4385-899b-560d06592aec",
1496                                "body": null,
1497                                "type": "multiple-choice",
1498                                "multi": false,
1499                                "multipleChoiceMultipleOptionsGradingPolicy": "default",
1500                                "order": 0,
1501                                "title": "Pick all the correct answers from below",
1502                                "quizId": "3f332295-b409-4fa8-a690-e5afd4e06b7a",
1503                                "options": [
1504                                    {
1505                                        "id": "d606fec9-6854-4b40-9b37-e1f53f4d4a0f",
1506                                        "body": "Incorrect",
1507                                        "order": 1,
1508                                        "title": null,
1509                                        "quizItemId": "a72b53f5-97c4-4385-899b-560d06592aec",
1510                                        "correct":false,
1511                                        "messageAfterSubmissionWhenSelected": "This is incorrect option",
1512                                        "additionalCorrectnessExplanationOnModelSolution": null
1513                                    },
1514                                    {
1515                                        "id": "9c69312d-c1e1-48bd-b920-309b39d2a7db",
1516                                        "body": "Correct",
1517                                        "order": 2,
1518                                        "title": null,
1519                                        "quizItemId": "a72b53f5-97c4-4385-899b-560d06592aec",
1520                                        "correct":true,
1521                                        "messageAfterSubmissionWhenSelected": "This is correct option",
1522                                        "additionalCorrectnessExplanationOnModelSolution": null,
1523                                    },
1524                                    {
1525                                        "id": "fef8854d-fee0-40ad-ab81-f4ed66daadeb",
1526                                        "body": "Correct",
1527                                        "order": 3,
1528                                        "title": null,
1529                                        "quizItemId": "a72b53f5-97c4-4385-899b-560d06592aec",
1530                                        "correct":true,
1531                                        "messageAfterSubmissionWhenSelected": "This is correct option",
1532                                        "additionalCorrectnessExplanationOnModelSolution": null
1533                                    },
1534                                ],
1535                                "allAnswersCorrect": false,
1536                                "sharedOptionFeedbackMessage": null,
1537                                "usesSharedOptionFeedbackMessage": false
1538                            }],
1539                            "title": "Pretty good exercise",
1540                            "tries": 1,
1541                            "points": 2,
1542                            "section": 0,
1543                            "courseId": "39c7879a-e61f-474a-8f18-7fc476ccc3a0",
1544                            "deadline": "2021-12-17T07:15:33.479Z",
1545                            "createdAt": "2021-12-17T07:15:33.479Z",
1546                            "updatedAt": "2021-12-17T07:15:33.479Z",
1547                            "autoReject": false,
1548                            "autoConfirm": true,
1549                            "randomizeOptions": false,
1550                            "triesLimited": true,
1551                            "submitMessage": "This is an extra submit message from the teacher.",
1552                            "excludedFromScore": true,
1553                            "grantPointsPolicy": "grant_whenever_possible",
1554                            "awardPointsEvenIfWrong": false}),
1555                    ),
1556                ],
1557            )],
1558            Uuid::new_v5(&course_id, b"9e70076a-9137-4d65-989c-0c0951027c53"),
1559        );
1560
1561    create_page(
1562        &mut conn,
1563        course.id,
1564        teacher_user_id,
1565        Some(chapter_1.id),
1566        CmsPageUpdate {
1567            url_path: "/chapter-1/complicated-quizzes-exercise".to_string(),
1568            title: "Complicated quizzes exercise page".to_string(),
1569            chapter_id: Some(chapter_1.id),
1570            exercises: vec![multi_exercise_2],
1571            exercise_slides: multi_exercise_2_slides,
1572            exercise_tasks: multi_exercise_2_tasks,
1573            content: serde_json::json!([
1574                paragraph(
1575                    "This page has a complicated quizzes exercise.",
1576                    Uuid::new_v5(&course_id, b"ea0eaf34-3c92-4007-aae4-9abff7ad1e4c")
1577                ),
1578                multi_exercise_block_2
1579            ]),
1580        },
1581    )
1582    .await?;
1583
1584    create_page(
1585        &mut conn,
1586        course.id,
1587        teacher_user_id,
1588        Some(chapter_1.id),
1589        CmsPageUpdate {
1590            url_path: "/chapter-1/the-authors".to_string(),
1591            title: "The Author Block".to_string(),
1592            chapter_id: Some(chapter_1.id),
1593            exercises: vec![],
1594            exercise_slides: vec![],
1595            exercise_tasks: vec![],
1596            content: serde_json::json!([GutenbergBlock {
1597                name: "moocfi/author".to_string(),
1598                is_valid: true,
1599                client_id: Uuid::parse_str("eb27eddd-6fc7-46f8-b7aa-968b16f86f1f").unwrap(),
1600                attributes: attributes! {},
1601                inner_blocks: vec![GutenbergBlock {
1602                    name: "moocfi/author-inner-block".to_string(),
1603                    is_valid: true,
1604                    client_id: Uuid::parse_str("b5565362-e8e3-4837-9546-014dc98af686").unwrap(),
1605                    attributes: attributes! {},
1606                    inner_blocks: vec![GutenbergBlock {
1607                        name: "core/columns".to_string(),
1608                        is_valid: true,
1609                        client_id: Uuid::parse_str("d8df9ead-9be3-4d25-96ec-c6e591db261b").unwrap(),
1610                        attributes: attributes! { "isStackedOnMobile": true },
1611                        inner_blocks: vec![GutenbergBlock {
1612                            name: "core/column".to_string(),
1613                            is_valid: true,
1614                            client_id: Uuid::parse_str("6435c2f7-ccc0-4cec-9c38-19bd688b057c").unwrap(),
1615                            attributes: attributes! {},
1616                                inner_blocks: vec![GutenbergBlock {
1617                                name: "core/image".to_string(),
1618                                is_valid: true,
1619                                client_id: Uuid::parse_str("f700cf35-0c8e-4905-88ed-475ad60bdf82").unwrap(),
1620                                attributes: attributes! {
1621                                    "alt": "Add alt",
1622                                    "anchor": "author-photo",
1623                                    "blurDataUrl": "",
1624                                    "href": "http://project-331.local/api/v0/files/uploads/jpgs/lilo-and-stitch.jpg",
1625                                    "linkDestination": "media",
1626                                    "sizeSlug": "full",
1627                                    "url": "http://project-331.local/api/v0/files/uploads/jpgs/lilo-and-stitch.jpg",
1628                                },
1629                                inner_blocks: vec![],
1630                            }],
1631                        },
1632                        GutenbergBlock {
1633                            name: "core/column".to_string(),
1634                            is_valid: true,
1635                            client_id: Uuid::parse_str("fe8b2efc-e5da-407e-9293-f156847cc571").unwrap(),
1636                            attributes: attributes! {},
1637                            inner_blocks: vec![GutenbergBlock {
1638                                name: "core/paragraph".to_string(),
1639                                is_valid: true,
1640                                client_id: Uuid::parse_str("6d0e2979-9a57-492a-af6f-9f62381f1ede").unwrap(),
1641                                attributes: attributes! {
1642                                    "align": "left",
1643                                    "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",
1644                                    "dropCap": false,
1645                                    "placeholder": "Insert author's bio text..."
1646                                },
1647                                inner_blocks: vec![],
1648                            }],
1649                        },
1650                        ],
1651
1652                        },
1653                    ],
1654                }]
1655            }])
1656        },
1657
1658    )
1659    .await?;
1660
1661    create_page(
1662        &mut conn,
1663        course.id,
1664        teacher_user_id,
1665        None,
1666        CmsPageUpdate {
1667            url_path: "/glossary".to_string(),
1668            title: "Glossary".to_string(),
1669            chapter_id: None,
1670            exercises: vec![],
1671            exercise_slides: vec![],
1672            exercise_tasks: vec![],
1673            content: serde_json::json!([GutenbergBlock {
1674                name: "moocfi/glossary".to_string(),
1675                is_valid: true,
1676                client_id: Uuid::parse_str("3a388f47-4aa7-409f-af14-a0290b916225").unwrap(),
1677                attributes: attributes! {},
1678                inner_blocks: vec![]
1679            }]),
1680        },
1681    )
1682    .await?;
1683
1684    // enrollments, user exercise states, submissions, grades
1685    info!("sample enrollments, user exercise states, submissions, grades");
1686    for user_id in users.iter().copied() {
1687        course_instance_enrollments::insert_enrollment_and_set_as_current(
1688            &mut conn,
1689            NewCourseInstanceEnrollment {
1690                course_id,
1691                course_instance_id: default_instance.id,
1692                user_id,
1693            },
1694        )
1695        .await?;
1696
1697        submit_and_grade(
1698            &mut conn,
1699            b"8c447aeb-1791-4236-8471-204d8bc27507",
1700            exercise_1_id,
1701            exercise_1_slide_1_id,
1702            course.id,
1703            exercise_1_slide_1_task_1_id,
1704            user_id,
1705            default_instance.id,
1706            exercise_1_slide_1_task_1_spec_1_id.to_string(),
1707            100.0,
1708        )
1709        .await?;
1710        // this submission is for the same exercise, but no points are removed due to the update strategy
1711        submit_and_grade(
1712            &mut conn,
1713            b"a719fe25-5721-412d-adea-4696ccb3d883",
1714            exercise_1_id,
1715            exercise_1_slide_1_id,
1716            course.id,
1717            exercise_1_slide_1_task_1_id,
1718            user_id,
1719            default_instance.id,
1720            exercise_1_slide_1_task_1_spec_2_id.to_string(),
1721            1.0,
1722        )
1723        .await?;
1724        submit_and_grade(
1725            &mut conn,
1726            b"bbc16d4b-1f91-4bd0-a47f-047665a32196",
1727            exercise_1_id,
1728            exercise_1_slide_1_id,
1729            course.id,
1730            exercise_1_slide_1_task_1_id,
1731            user_id,
1732            default_instance.id,
1733            exercise_1_slide_1_task_1_spec_3_id.to_string(),
1734            0.0,
1735        )
1736        .await?;
1737        submit_and_grade(
1738            &mut conn,
1739            b"c60bf5e5-9b67-4f62-9df7-16d268c1b5f5",
1740            exercise_1_id,
1741            exercise_1_slide_1_id,
1742            course.id,
1743            exercise_1_slide_1_task_1_id,
1744            user_id,
1745            default_instance.id,
1746            exercise_1_slide_1_task_1_spec_1_id.to_string(),
1747            60.0,
1748        )
1749        .await?;
1750        submit_and_grade(
1751            &mut conn,
1752            b"e0ec1386-72aa-4eed-8b91-72bba420c23b",
1753            exercise_2_id,
1754            exercise_2_slide_1_id,
1755            course.id,
1756            exercise_2_slide_1_task_1_id,
1757            user_id,
1758            default_instance.id,
1759            exercise_2_slide_1_task_1_spec_1_id.to_string(),
1760            70.0,
1761        )
1762        .await?;
1763        submit_and_grade(
1764            &mut conn,
1765            b"02c9e1ad-6e4c-4473-a3e9-dbfab018a055",
1766            exercise_5_id,
1767            exercise_5_slide_1_id,
1768            course.id,
1769            exercise_5_slide_1_task_1_id,
1770            user_id,
1771            default_instance.id,
1772            exercise_5_slide_1_task_1_spec_1_id.to_string(),
1773            80.0,
1774        )
1775        .await?;
1776        submit_and_grade(
1777            &mut conn,
1778            b"75df4600-d337-4083-99d1-e8e3b6bf6192",
1779            exercise_1_id,
1780            exercise_1_slide_1_id,
1781            course.id,
1782            exercise_1_slide_1_task_1_id,
1783            user_id,
1784            default_instance.id,
1785            exercise_1_slide_1_task_1_spec_1_id.to_string(),
1786            90.0,
1787        )
1788        .await?;
1789    }
1790    course_instance_enrollments::insert_enrollment_and_set_as_current(
1791        &mut conn,
1792        NewCourseInstanceEnrollment {
1793            course_id,
1794            course_instance_id: default_instance.id,
1795            user_id: langs_user_id,
1796        },
1797    )
1798    .await?;
1799
1800    // feedback
1801    info!("sample feedback");
1802    let new_feedback = NewFeedback {
1803        feedback_given: "this part was unclear to me".to_string(),
1804        selected_text: Some("blanditiis".to_string()),
1805        related_blocks: vec![FeedbackBlock {
1806            id: block_id_4,
1807            text: Some(
1808                "blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas"
1809                    .to_string(),
1810            ),
1811            order_number: Some(0),
1812        }],
1813        page_id: page_3,
1814    };
1815    let feedback = feedback::insert(
1816        &mut conn,
1817        PKeyPolicy::Generate,
1818        Some(student),
1819        course.id,
1820        new_feedback,
1821    )
1822    .await?;
1823    feedback::mark_as_read(&mut conn, feedback, true).await?;
1824    let new_feedback = NewFeedback {
1825        feedback_given: "I dont think we need these paragraphs".to_string(),
1826        selected_text: Some("verything".to_string()),
1827        related_blocks: vec![
1828            FeedbackBlock {
1829                id: block_id_1,
1830                text: Some("verything is a big topic.".to_string()),
1831                order_number: Some(0),
1832            },
1833            FeedbackBlock {
1834                id: block_id_4,
1835                text: Some("So big, that we need many paragraphs.".to_string()),
1836                order_number: Some(1),
1837            },
1838            FeedbackBlock {
1839                id: block_id_5,
1840                text: Some("Like th".to_string()),
1841                order_number: Some(2),
1842            },
1843        ],
1844        page_id: page_3,
1845    };
1846    feedback::insert(
1847        &mut conn,
1848        PKeyPolicy::Generate,
1849        Some(student),
1850        course.id,
1851        new_feedback,
1852    )
1853    .await?;
1854    feedback::insert(
1855        &mut conn,
1856        PKeyPolicy::Generate,
1857        None,
1858        course.id,
1859        NewFeedback {
1860            feedback_given: "Anonymous feedback".to_string(),
1861            selected_text: None,
1862            related_blocks: vec![FeedbackBlock {
1863                id: block_id_1,
1864                text: None,
1865                order_number: Some(0),
1866            }],
1867            page_id: page_3,
1868        },
1869    )
1870    .await?;
1871    feedback::insert(
1872        &mut conn,
1873        PKeyPolicy::Generate,
1874        None,
1875        course.id,
1876        NewFeedback {
1877            feedback_given: "Anonymous unrelated feedback".to_string(),
1878            selected_text: None,
1879            related_blocks: vec![],
1880            page_id: page_3,
1881        },
1882    )
1883    .await?;
1884
1885    // edit proposals
1886    info!("sample edit proposals");
1887    let edits = NewProposedPageEdits {
1888        page_id: page_c1_1,
1889        block_edits: vec![NewProposedBlockEdit {
1890            block_id: block_id_4,
1891            block_attribute: "content".to_string(),
1892            original_text: "So bg, that we need many paragraphs.".to_string(),
1893            changed_text: "So bg, that we need many, many paragraphs.".to_string(),
1894        }],
1895    };
1896    proposed_page_edits::insert(
1897        &mut conn,
1898        PKeyPolicy::Generate,
1899        course.id,
1900        Some(student),
1901        &edits,
1902    )
1903    .await?;
1904    let edits = NewProposedPageEdits {
1905        page_id: page_c1_1,
1906        block_edits: vec![
1907            NewProposedBlockEdit {
1908                block_id: block_id_1,
1909                block_attribute: "content".to_string(),
1910                original_text: "Everything is a big topic.".to_string(),
1911                changed_text: "Everything is a very big topic.".to_string(),
1912            },
1913            NewProposedBlockEdit {
1914                block_id: block_id_5,
1915                block_attribute: "content".to_string(),
1916                original_text: "Like this.".to_string(),
1917                changed_text: "Like this!".to_string(),
1918            },
1919        ],
1920    };
1921    proposed_page_edits::insert(
1922        &mut conn,
1923        PKeyPolicy::Generate,
1924        course.id,
1925        Some(student),
1926        &edits,
1927    )
1928    .await?;
1929
1930    // acronyms
1931    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?;
1932    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?;
1933    glossary::insert(&mut conn, "SSD", "Solid-state drive. A solid-state drive is a hard drive that's a few gigabytes in size, but a solid-state drive is one where data loads are big enough and fast enough that you can comfortably write to it over long distances. This is what drives do. You need to remember that a good solid-state drive has a lot of data: it stores files on disks and has a few data centers. A good solid-state drive makes for a nice little library: its metadata includes information about everything it stores, including any data it can access, but does not store anything that does not exist outside of those files. It also stores large amounts of data from one location, which can cause problems since the data might be different in different places, or in different ways, than what you would expect to see when driving big data applications. The drives that make up a solid-state drive are called drives that use a variety of storage technologies. These drive technology technologies are called \"super drives,\" and they store some of that data in a solid-state drive. Super drives are designed to be fast but very big: they aren't built to store everything, but to store many kinds of data: including data about the data they contain, and more, like the data they are supposed to hold in them. The super drives that make up a solid-state drive can have capacities of up to 50,000 hard disks. These can be used to store files if",  course.id).await?;
1934    glossary::insert(&mut conn, "KB", "Keyboard.", course.id).await?;
1935
1936    // create_best_peer_review(&mut conn, course.id, Some(exercise_1_id)).await?;
1937
1938    // certificate configuration
1939    let background_svg_path = "svgs/certificate-background.svg".to_string();
1940    let background_svg_file_upload_id = file_uploads::insert(
1941        &mut conn,
1942        &format!("background-{}.svg", module.id),
1943        &background_svg_path,
1944        "image/svg+xml",
1945        None,
1946    )
1947    .await?;
1948    let configuration = DatabaseCertificateConfiguration {
1949        id: Uuid::new_v5(&course_id, b"886d3e22-5007-4371-94d7-e0ad93a2391c"),
1950        certificate_owner_name_y_pos: None,
1951        certificate_owner_name_x_pos: None,
1952        certificate_owner_name_font_size: None,
1953        certificate_owner_name_text_color: None,
1954        certificate_owner_name_text_anchor: None,
1955        certificate_validate_url_y_pos: None,
1956        certificate_validate_url_x_pos: None,
1957        certificate_validate_url_font_size: None,
1958        certificate_validate_url_text_color: None,
1959        certificate_validate_url_text_anchor: None,
1960        certificate_date_y_pos: None,
1961        certificate_date_x_pos: None,
1962        certificate_date_font_size: None,
1963        certificate_date_text_color: None,
1964        certificate_date_text_anchor: None,
1965        certificate_locale: None,
1966        paper_size: None,
1967        background_svg_path,
1968        background_svg_file_upload_id,
1969        overlay_svg_path: None,
1970        overlay_svg_file_upload_id: None,
1971        render_certificate_grade: false,
1972        certificate_grade_y_pos: None,
1973        certificate_grade_x_pos: None,
1974        certificate_grade_font_size: None,
1975        certificate_grade_text_color: None,
1976        certificate_grade_text_anchor: None,
1977    };
1978    let database_configuration =
1979        certificate_configurations::insert(&mut conn, &configuration).await?;
1980    certificate_configuration_to_requirements::insert(
1981        &mut conn,
1982        database_configuration.id,
1983        Some(default_module.id),
1984    )
1985    .await?;
1986
1987    // Add roles
1988    roles::insert(
1989        &mut conn,
1990        seed_users_result.teacher_user_id,
1991        UserRole::Teacher,
1992        RoleDomain::Course(course.id),
1993    )
1994    .await?;
1995
1996    Ok(course.id)
1997}
1998
1999pub async fn seed_switching_course_instances_course(
2000    course_id: Uuid,
2001    course_name: &str,
2002    course_slug: &str,
2003    common_course_data: CommonCourseData,
2004    can_add_chatbot: bool,
2005    seed_users_result: SeedUsersResult,
2006) -> Result<Uuid> {
2007    let CommonCourseData {
2008        db_pool,
2009        organization_id: org,
2010        teacher_user_id,
2011        student_user_id: _student,
2012        langs_user_id: _langs_user_id,
2013        example_normal_user_ids: _users,
2014        jwt_key: _jwt_key,
2015        base_url: _base_url,
2016    } = common_course_data;
2017
2018    let mut conn = db_pool.acquire().await?;
2019    let mut cx = SeedContext {
2020        conn: &mut conn,
2021        teacher: teacher_user_id,
2022        org,
2023        base_course_ns: course_id,
2024    };
2025
2026    info!(
2027        "Inserting switching course instances course {}",
2028        course_name
2029    );
2030
2031    let course = CourseBuilder::new(course_name, course_slug)
2032        .desc("Sample course.")
2033        .chatbot(can_add_chatbot)
2034        .course_id(course_id)
2035        .instance(CourseInstanceConfig {
2036            name: None,
2037            description: None,
2038            support_email: None,
2039            teacher_in_charge_name: "admin".to_string(),
2040            teacher_in_charge_email: "admin@example.com".to_string(),
2041            opening_time: None,
2042            closing_time: None,
2043            instance_id: Some(cx.v5(b"instance:default")),
2044        })
2045        .instance(CourseInstanceConfig {
2046            name: Some("Non-default instance".to_string()),
2047            description: Some("This is a non-default instance".to_string()),
2048            support_email: Some("contact@example.com".to_string()),
2049            teacher_in_charge_name: "admin".to_string(),
2050            teacher_in_charge_email: "admin@example.com".to_string(),
2051            opening_time: None,
2052            closing_time: None,
2053            instance_id: Some(cx.v5(b"instance:non-default")),
2054        })
2055        .role(seed_users_result.teacher_user_id, UserRole::Teacher)
2056        .module(
2057            ModuleBuilder::new()
2058                .order(0)
2059                .register_to_open_university(false)
2060                .automatic_completion(Some(1), Some(1), false)
2061                .chapter(
2062                    ChapterBuilder::new(1, "The Basics")
2063                        .opens(Utc::now())
2064                        .deadline(Utc.with_ymd_and_hms(2225, 1, 1, 23, 59, 59).unwrap())
2065                        .fixed_ids(cx.v5(b"chapter:1"), cx.v5(b"chapter:1:instance"))
2066                        .page(
2067                            PageBuilder::new("/chapter-1/page-1", "Page One")
2068                                .block(paragraph(
2069                                    "This is a simple introduction to the basics.",
2070                                    cx.v5(b"page:1:1:block:intro"),
2071                                ))
2072                                .exercise(ExerciseBuilder::example_exercise(
2073                                    "Simple multiple choice",
2074                                    ExerciseIds {
2075                                        exercise_id: cx.v5(b"exercise:1:1:e"),
2076                                        slide_id: cx.v5(b"exercise:1:1:s"),
2077                                        task_id: cx.v5(b"exercise:1:1:t"),
2078                                        block_id: cx.v5(b"exercise:1:1:b"),
2079                                    },
2080                                    vec![paragraph(
2081                                        "What is 2 + 2?",
2082                                        cx.v5(b"exercise:1:1:prompt"),
2083                                    )],
2084                                    json!([
2085                                        {
2086                                            "name": "3",
2087                                            "correct": false,
2088                                            "id": cx.v5(b"exercise:1:1:option:1")
2089                                        },
2090                                        {
2091                                            "name": "4",
2092                                            "correct": true,
2093                                            "id": cx.v5(b"exercise:1:1:option:2")
2094                                        },
2095                                        {
2096                                            "name": "5",
2097                                            "correct": false,
2098                                            "id": cx.v5(b"exercise:1:1:option:3")
2099                                        }
2100                                    ]),
2101                                )),
2102                        ),
2103                ),
2104        )
2105        .module(
2106            ModuleBuilder::new()
2107                .order(1)
2108                .name("Another module")
2109                .automatic_completion(Some(1), Some(1), false)
2110                .ects(5.0)
2111                .chapter(
2112                    ChapterBuilder::new(2, "Another chapter")
2113                        .fixed_ids(cx.v5(b"chapter:2"), cx.v5(b"chapter:2:instance"))
2114                        .page(
2115                            PageBuilder::new("/chapter-2/page-1", "Simple Page")
2116                                .block(paragraph(
2117                                    "This is another simple page with basic content.",
2118                                    cx.v5(b"page:2:1:block:intro"),
2119                                ))
2120                                .exercise(ExerciseBuilder::example_exercise(
2121                                    "Simple question",
2122                                    ExerciseIds {
2123                                        exercise_id: cx.v5(b"exercise:2:1:e"),
2124                                        slide_id: cx.v5(b"exercise:2:1:s"),
2125                                        task_id: cx.v5(b"exercise:2:1:t"),
2126                                        block_id: cx.v5(b"exercise:2:1:b"),
2127                                    },
2128                                    vec![paragraph(
2129                                        "What color is the sky?",
2130                                        cx.v5(b"exercise:2:1:prompt"),
2131                                    )],
2132                                    json!([
2133                                        {
2134                                            "name": "Red",
2135                                            "correct": false,
2136                                            "id": cx.v5(b"exercise:2:1:option:1")
2137                                        },
2138                                        {
2139                                            "name": "Blue",
2140                                            "correct": true,
2141                                            "id": cx.v5(b"exercise:2:1:option:2")
2142                                        },
2143                                        {
2144                                            "name": "Green",
2145                                            "correct": false,
2146                                            "id": cx.v5(b"exercise:2:1:option:3")
2147                                        }
2148                                    ]),
2149                                )),
2150                        ),
2151                ),
2152        )
2153        .module(
2154            ModuleBuilder::new()
2155                .order(2)
2156                .name("Bonus module")
2157                .register_to_open_university(true)
2158                .automatic_completion(None, Some(1), false)
2159                .chapter(
2160                    ChapterBuilder::new(3, "Bonus chapter")
2161                        .fixed_ids(cx.v5(b"chapter:3"), cx.v5(b"chapter:3:instance"))
2162                        .page(
2163                            PageBuilder::new("/chapter-3/page-1", "Bonus Page")
2164                                .block(paragraph(
2165                                    "This is a bonus page with simple content.",
2166                                    cx.v5(b"page:3:1:block:intro"),
2167                                ))
2168                                .exercise(ExerciseBuilder::example_exercise(
2169                                    "Bonus question",
2170                                    ExerciseIds {
2171                                        exercise_id: cx.v5(b"exercise:3:1:e"),
2172                                        slide_id: cx.v5(b"exercise:3:1:s"),
2173                                        task_id: cx.v5(b"exercise:3:1:t"),
2174                                        block_id: cx.v5(b"exercise:3:1:b"),
2175                                    },
2176                                    vec![paragraph(
2177                                        "What is the capital of France?",
2178                                        cx.v5(b"exercise:3:1:assignment"),
2179                                    )],
2180                                    json!([
2181                                        {
2182                                            "name": "London",
2183                                            "correct": false,
2184                                            "id": cx.v5(b"exercise:3:1:option:1")
2185                                        },
2186                                        {
2187                                            "name": "Paris",
2188                                            "correct": true,
2189                                            "id": cx.v5(b"exercise:3:1:option:2")
2190                                        },
2191                                        {
2192                                            "name": "Berlin",
2193                                            "correct": false,
2194                                            "id": cx.v5(b"exercise:3:1:option:3")
2195                                        }
2196                                    ]),
2197                                )),
2198                        ),
2199                ),
2200        );
2201
2202    let (course, _default_instance, _last_module) = course.seed(&mut cx).await?;
2203
2204    Ok(course.id)
2205}
2206
2207pub async fn create_glossary_course(
2208    course_id: Uuid,
2209    common_course_data: CommonCourseData,
2210) -> Result<Uuid> {
2211    let CommonCourseData {
2212        db_pool,
2213        organization_id: org_id,
2214        teacher_user_id,
2215        student_user_id: _,
2216        langs_user_id: _,
2217        example_normal_user_ids: _,
2218        jwt_key: _jwt_key,
2219        base_url: _base_url,
2220    } = common_course_data;
2221    let mut conn = db_pool.acquire().await?;
2222
2223    // Create new course
2224    let new_course = NewCourse {
2225        name: "Glossary Tooltip".to_string(),
2226        organization_id: org_id,
2227        slug: "glossary-tooltip".to_string(),
2228        language_code: "en-US".to_string(),
2229        teacher_in_charge_name: "admin".to_string(),
2230        teacher_in_charge_email: "admin@example.com".to_string(),
2231        description: "Sample course.".to_string(),
2232        is_draft: false,
2233        is_test_mode: false,
2234        is_unlisted: false,
2235        copy_user_permissions: false,
2236        is_joinable_by_code_only: false,
2237        join_code: None,
2238        ask_marketing_consent: false,
2239        flagged_answers_threshold: Some(3),
2240        can_add_chatbot: false,
2241    };
2242
2243    let (course, _front_page, _default_instance, default_module) =
2244        library::content_management::create_new_course(
2245            &mut conn,
2246            PKeyPolicy::Fixed(CreateNewCourseFixedIds {
2247                course_id,
2248                default_course_instance_id: Uuid::new_v5(
2249                    &course_id,
2250                    b"7344f1c8-b7ce-4c7d-ade2-5f39997bd454",
2251                ),
2252            }),
2253            new_course,
2254            teacher_user_id,
2255            get_seed_spec_fetcher(),
2256            models_requests::fetch_service_info,
2257        )
2258        .await?;
2259
2260    // Create course instance
2261    course_instances::insert(
2262        &mut conn,
2263        PKeyPolicy::Fixed(Uuid::new_v5(
2264            &course_id,
2265            b"67f077b4-0562-47ae-a2b9-db2f08f168a9",
2266        )),
2267        NewCourseInstance {
2268            course_id: course.id,
2269            name: Some("Non-default instance"),
2270            description: Some("This is a non-default instance"),
2271            support_email: Some("contact@example.com"),
2272            teacher_in_charge_name: "admin",
2273            teacher_in_charge_email: "admin@example.com",
2274            opening_time: None,
2275            closing_time: None,
2276        },
2277    )
2278    .await?;
2279
2280    // Chapter & Main page
2281    let new_chapter = NewChapter {
2282        chapter_number: 1,
2283        course_id: course.id,
2284        front_page_id: None,
2285        name: "Glossary".to_string(),
2286        color: None,
2287        opens_at: None,
2288        deadline: Some(Utc.with_ymd_and_hms(2225, 1, 1, 23, 59, 59).unwrap()),
2289        course_module_id: Some(default_module.id),
2290    };
2291    let (chapter, _front_page) = library::content_management::create_new_chapter(
2292        &mut conn,
2293        PKeyPolicy::Fixed((
2294            Uuid::new_v5(&course_id, b"3d1d7303-b654-428a-8b46-1dbfe908d38a"),
2295            Uuid::new_v5(&course_id, b"97568e97-0d6c-4702-9534-77d6e2784c8a"),
2296        )),
2297        &new_chapter,
2298        teacher_user_id,
2299        get_seed_spec_fetcher(),
2300        models_requests::fetch_service_info,
2301    )
2302    .await?;
2303    chapters::set_opens_at(&mut conn, chapter.id, Utc::now()).await?;
2304
2305    // Create page
2306    create_page(
2307        &mut conn,
2308        course.id,
2309        teacher_user_id,
2310        Some(chapter.id),
2311        CmsPageUpdate {
2312            url_path: "/tooltip".to_string(),
2313            title: "Tooltip".to_string(),
2314            chapter_id: Some(chapter.id),
2315            exercises: vec![],
2316            exercise_slides: vec![],
2317            exercise_tasks: vec![],
2318            content: serde_json::json!([paragraph(
2319                "Use the KB to write sentences for your CS-courses.",
2320                Uuid::new_v5(&course.id, b"6903cf16-4f79-4985-a354-4257be1193a2")
2321            ),]),
2322        },
2323    )
2324    .await?;
2325
2326    // Setup glossary
2327    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?;
2328    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?;
2329    glossary::insert(&mut conn, "SSD", "Solid-state drive. A solid-state drive is a hard drive that's a few gigabytes in size, but a solid-state drive is one where data loads are big enough and fast enough that you can comfortably write to it over long distances. This is what drives do. You need to remember that a good solid-state drive has a lot of data: it stores files on disks and has a few data centers. A good solid-state drive makes for a nice little library: its metadata includes information about everything it stores, including any data it can access, but does not store anything that does not exist outside of those files. It also stores large amounts of data from one location, which can cause problems since the data might be different in different places, or in different ways, than what you would expect to see when driving big data applications. The drives that make up a solid-state drive are called drives that use a variety of storage technologies. These drive technology technologies are called \"super drives,\" and they store some of that data in a solid-state drive. Super drives are designed to be fast but very big: they aren't built to store everything, but to store many kinds of data: including data about the data they contain, and more, like the data they are supposed to hold in them. The super drives that make up a solid-state drive can have capacities of up to 50,000 hard disks. These can be used to store files if",  course.id).await?;
2330    glossary::insert(&mut conn, "KB", "Keyboard.", course.id).await?;
2331
2332    Ok(course.id)
2333}
2334
2335pub async fn seed_cs_course_material(
2336    db_pool: &Pool<Postgres>,
2337    org: Uuid,
2338    teacher_user_id: Uuid,
2339    langs_user_id: Uuid,
2340    _base_url: String,
2341) -> Result<Uuid> {
2342    let mut conn = db_pool.acquire().await?;
2343    let spec_fetcher = get_seed_spec_fetcher();
2344    // Create new course
2345    let new_course = NewCourse {
2346        name: "Introduction to Course Material".to_string(),
2347        organization_id: org,
2348        slug: "introduction-to-course-material".to_string(),
2349        language_code: "en-US".to_string(),
2350        teacher_in_charge_name: "admin".to_string(),
2351        teacher_in_charge_email: "admin@example.com".to_string(),
2352        description: "The definitive introduction to course material.".to_string(),
2353        is_draft: false,
2354        is_test_mode: false,
2355        is_unlisted: false,
2356        copy_user_permissions: false,
2357        is_joinable_by_code_only: false,
2358        join_code: None,
2359        ask_marketing_consent: false,
2360        flagged_answers_threshold: Some(3),
2361        can_add_chatbot: false,
2362    };
2363    let (course, front_page, default_instance, default_module) =
2364        library::content_management::create_new_course(
2365            &mut conn,
2366            PKeyPolicy::Fixed(CreateNewCourseFixedIds {
2367                course_id: Uuid::parse_str("d6b52ddc-6c34-4a59-9a59-7e8594441007")?,
2368                default_course_instance_id: Uuid::parse_str(
2369                    "8e6c35cd-43f2-4982-943b-11e3ffb1b2f8",
2370                )?,
2371            }),
2372            new_course,
2373            teacher_user_id,
2374            &spec_fetcher,
2375            models_requests::fetch_service_info,
2376        )
2377        .await?;
2378
2379    // Exercises
2380    let (
2381        quizzes_exercise_block_5,
2382        quizzes_exercise_5,
2383        quizzes_exercise_slide_5,
2384        quizzes_exercise_task_5,
2385    ) = quizzes_exercise(
2386        "Best quizzes exercise".to_string(),
2387        Uuid::new_v5(&course.id, b"58e71279-81e1-4679-83e6-8f5f23ec055a"),
2388        false,
2389        serde_json::json!({
2390                "id": "3a1b3e10-2dd5-4cb9-9460-4c08f19e16d3",
2391                "body": "very hard",
2392                "part": 3,
2393                "items": [{
2394                    "id": "7b0049ea-de8b-4eef-a4a9-164e0e874ecc",
2395                    "body": "",
2396                    "type": "multiple-choice",
2397                    "direction": "row",
2398                    "multi": false,
2399                    "multipleChoiceMultipleOptionsGradingPolicy": "default",
2400                    "order": 0,
2401                    "title": "Choose the first answer",
2402                    "quizId": "3a1b3e10-2dd5-4cb9-9460-4c08f19e16d3",
2403                    "options": [{
2404                        "id": "d5124283-4e84-4b4f-84c0-a91961b0ef21",
2405                        "body": "This is first option",
2406                        "order": 1,
2407                        "title": null,
2408                        "quizItemId": "7b0049ea-de8b-4eef-a4a9-164e0e874ecc",
2409                        "correct":true,
2410                        "messageAfterSubmissionWhenSelected": "Correct! This is indeed the first answer",
2411                        "additionalCorrectnessExplanationOnModelSolution": null,
2412                    },{
2413                        "id": "846c09e2-653a-4471-81ae-25726486b003",
2414                        "body": "This is second option",
2415                        "order": 1,
2416                        "title": null,
2417                        "quizItemId": "7b0049ea-de8b-4eef-a4a9-164e0e874ecc",
2418                        "correct":false,
2419                        "messageAfterSubmissionWhenSelected": "Incorrect. This is not the first answer",
2420                        "additionalCorrectnessExplanationOnModelSolution": null,
2421                    },{
2422                        "id": "8107ae39-96aa-4f54-aa78-1a33362a19c1",
2423                        "body": "This is third option",
2424                        "order": 1,
2425                        "title": null,
2426                        "quizItemId": "7b0049ea-de8b-4eef-a4a9-164e0e874ecc",
2427                        "correct":false,
2428                        "messageAfterSubmissionWhenSelected": "Incorrect. This is not the first answer",
2429                        "additionalCorrectnessExplanationOnModelSolution": null,
2430                    },],
2431                    "allAnswersCorrect": false,
2432                    "sharedOptionFeedbackMessage": null,
2433                    "usesSharedOptionFeedbackMessage": false
2434                }],
2435                "title": "Very good exercise",
2436                "tries": 1,
2437                "points": 3,
2438                "section": 0,
2439                "courseId": "d6b52ddc-6c34-4a59-9a59-7e8594441007",
2440                "deadline": "2021-12-17T07:15:33.479Z",
2441                "createdAt": "2021-12-17T07:15:33.479Z",
2442                "updatedAt": "2021-12-17T07:15:33.479Z",
2443                "autoReject": false,
2444                "autoConfirm": true,
2445                "randomizeOptions": false,
2446                "triesLimited": true,
2447                "submitMessage": "This is an extra submit message from the teacher.",
2448                "excludedFromScore": true,
2449                "grantPointsPolicy": "grant_whenever_possible",
2450                "awardPointsEvenIfWrong": false}),
2451        Some(Utc.with_ymd_and_hms(2125, 1, 1, 23, 59, 59).unwrap()),
2452        CommonExerciseData {
2453            exercise_id: Uuid::new_v5(&course.id, b"cd3aa815-620e-43b3-b291-0fb10beca030"),
2454            exercise_slide_id: Uuid::new_v5(&course.id, b"0b1bbfb0-df56-4e40-92f1-df0a33f1fc70"),
2455            exercise_task_id: Uuid::new_v5(&course.id, b"7f011d0e-1cbf-4870-bacf-1873cf360c15"),
2456            block_id: Uuid::new_v5(&course.id, b"b9446b94-0edf-465c-9a9a-57708b7ef180"),
2457        },
2458    );
2459
2460    let (
2461        quizzes_exercise_block_6,
2462        quizzes_exercise_6,
2463        quizzes_exercise_slide_6,
2464        quizzes_exercise_task_6,
2465    ) = quizzes_exercise(
2466        "Best quizzes exercise".to_string(),
2467        Uuid::new_v5(&course.id, b"085b60ec-aa9d-11ec-b500-7b1e176646f8"),
2468        false,
2469        serde_json::from_str(include_str!(
2470            "../../assets/quizzes-multiple-choice-additional-feedback.json"
2471        ))?,
2472        Some(Utc.with_ymd_and_hms(2125, 1, 1, 23, 59, 59).unwrap()),
2473        CommonExerciseData {
2474            exercise_id: Uuid::new_v5(&course.id, b"925d4a89-0f25-4e8e-bc11-350393d8d894"),
2475            exercise_slide_id: Uuid::new_v5(&course.id, b"ff92ca4a-aa9c-11ec-ac56-475e57747ad3"),
2476            exercise_task_id: Uuid::new_v5(&course.id, b"9037cb17-3841-4a79-8f50-bbe595a4f785"),
2477            block_id: Uuid::new_v5(&course.id, b"d6d80ae0-97a1-4db1-8a3b-2bdde3cfbe9a"),
2478        },
2479    );
2480
2481    let (
2482        quizzes_exercise_block_7,
2483        quizzes_exercise_7,
2484        quizzes_exercise_slide_7,
2485        quizzes_exercise_task_7,
2486    ) = quizzes_exercise(
2487        "Best quizzes exercise".to_string(),
2488        Uuid::new_v5(&course.id, b"6365746e-aa9d-11ec-8718-0b5628cbe29f"),
2489        false,
2490        serde_json::json!({
2491                "id": "33cd47ea-aa9d-11ec-897c-5b22513d61ee",
2492                "body": "very hard",
2493                "part": 5,
2494                "items": [{
2495                    "id": "395888c8-aa9d-11ec-bb81-cb3a3f2609e4",
2496                    "body": "",
2497                    "type": "multiple-choice",
2498                    "direction": "column",
2499                    "multi": false,
2500                    "multipleChoiceMultipleOptionsGradingPolicy": "default",
2501                    "order": 0,
2502                    "title": "Choose the first answer",
2503                    "quizId": "33cd47ea-aa9d-11ec-897c-5b22513d61ee",
2504                    "options": [{
2505                        "id": "490543d8-aa9d-11ec-a20f-07269e5c09df",
2506                        "body": "This is first option",
2507                        "order": 1,
2508                        "title": null,
2509                        "quizItemId": "395888c8-aa9d-11ec-bb81-cb3a3f2609e4",
2510                        "correct":true,
2511                        "messageAfterSubmissionWhenSelected": "Correct! This is indeed the first answer",
2512                        "additionalCorrectnessExplanationOnModelSolution": null,
2513                    },{
2514                        "id": "45e77450-aa9d-11ec-abea-6b824f5ae1f6",
2515                        "body": "This is second option",
2516                        "order": 1,
2517                        "title": null,
2518                        "quizItemId": "395888c8-aa9d-11ec-bb81-cb3a3f2609e4",
2519                        "correct":false,
2520                        "messageAfterSubmissionWhenSelected": "Incorrect. This is not the first answer",
2521                        "additionalCorrectnessExplanationOnModelSolution": null,
2522                    },{
2523                        "id": "43428140-aa9d-11ec-a6b3-83ec8e2dfb88",
2524                        "body": "This is third option",
2525                        "order": 1,
2526                        "title": null,
2527                        "quizItemId": "395888c8-aa9d-11ec-bb81-cb3a3f2609e4",
2528                        "correct":false,
2529                        "messageAfterSubmissionWhenSelected": "Incorrect. This is not the first answer",
2530                        "additionalCorrectnessExplanationOnModelSolution": null,
2531                    },],
2532                    "allAnswersCorrect": false,
2533                    "sharedOptionFeedbackMessage": null,
2534                    "usesSharedOptionFeedbackMessage": false
2535                }],
2536                "title": "Very good exercise",
2537                "tries": 1,
2538                "points": 3,
2539                "section": 0,
2540                "courseId": "d6b52ddc-6c34-4a59-9a59-7e8594441007",
2541                "deadline": "2021-12-17T07:15:33.479Z",
2542                "createdAt": "2021-12-17T07:15:33.479Z",
2543                "updatedAt": "2021-12-17T07:15:33.479Z",
2544                "autoReject": false,
2545                "autoConfirm": true,
2546                "randomizeOptions": false,
2547                "triesLimited": true,
2548                "submitMessage": "This is an extra submit message from the teacher.",
2549                "excludedFromScore": true,
2550                "grantPointsPolicy": "grant_whenever_possible",
2551                "awardPointsEvenIfWrong": false}),
2552        Some(Utc.with_ymd_and_hms(2125, 1, 1, 23, 59, 59).unwrap()),
2553        CommonExerciseData {
2554            exercise_id: Uuid::new_v5(&course.id, b"57905c8a-aa9d-11ec-92d4-47ab996cb70c"),
2555            exercise_slide_id: Uuid::new_v5(&course.id, b"5b058552-aa9d-11ec-bc36-57e1c5f8407a"),
2556            exercise_task_id: Uuid::new_v5(&course.id, b"5d953894-aa9d-11ec-97e7-2ff4d73f69f1"),
2557            block_id: Uuid::new_v5(&course.id, b"604dae7c-aa9d-11ec-8df1-575042832340"),
2558        },
2559    );
2560
2561    let (
2562        quizzes_exercise_block_8,
2563        quizzes_exercise_8,
2564        quizzes_exercise_slide_8,
2565        quizzes_exercise_task_8,
2566    ) = quizzes_exercise(
2567        "Best quizzes exercise".to_string(),
2568        Uuid::new_v5(&course.id, b"01b69776-3e82-4694-98a9-5ce53f2a4ab5"),
2569        false,
2570        serde_json::json!({
2571                "id": "9a186f2b-7616-472e-b839-62ab0f2f0a6c",
2572                "body": "very hard",
2573                "part": 6,
2574                "items": [{
2575                    "id": "871c3640-aa9d-11ec-8103-633d645899a3",
2576                    "body": "",
2577                    "type": "multiple-choice",
2578                    "direction": "column",
2579                    "multi": false,
2580                    "multipleChoiceMultipleOptionsGradingPolicy": "default",
2581                    "order": 0,
2582                    "title": "Choose the first answer",
2583                    "quizId": "9a186f2b-7616-472e-b839-62ab0f2f0a6c",
2584                    "options": [{
2585                        "id": "4435ed30-c1da-46a0-80b8-c5b9ee923dd4",
2586                        "body": "This is first option",
2587                        "order": 1,
2588                        "title": null,
2589                        "quizItemId": "871c3640-aa9d-11ec-8103-633d645899a3",
2590                        "correct":true,
2591                        "messageAfterSubmissionWhenSelected": "Correct! This is indeed the first answer",
2592                        "additionalCorrectnessExplanationOnModelSolution": null,
2593                    },{
2594                        "id": "1d5de4d0-8499-4ac1-b44c-21c1562639cb",
2595                        "body": "This is second option",
2596                        "order": 1,
2597                        "title": null,
2598                        "quizItemId": "871c3640-aa9d-11ec-8103-633d645899a3",
2599                        "correct":false,
2600                        "messageAfterSubmissionWhenSelected": "Incorrect. This is not the first answer",
2601                        "additionalCorrectnessExplanationOnModelSolution": null,
2602                    },{
2603                        "id": "93fe358e-aa9d-11ec-9aa1-f3d18a09d58c",
2604                        "body": "This is third option",
2605                        "order": 1,
2606                        "title": null,
2607                        "quizItemId": "871c3640-aa9d-11ec-8103-633d645899a3",
2608                        "correct":false,
2609                        "messageAfterSubmissionWhenSelected": "Incorrect. This is not the first answer",
2610                        "additionalCorrectnessExplanationOnModelSolution": null,
2611                    },],
2612                    "allAnswersCorrect": false,
2613                    "sharedOptionFeedbackMessage": null,
2614                    "usesSharedOptionFeedbackMessage": false
2615                }],
2616                "title": "Very good exercise",
2617                "tries": 1,
2618                "points": 3,
2619                "section": 0,
2620                "courseId": "d6b52ddc-6c34-4a59-9a59-7e8594441007",
2621                "deadline": "2021-12-17T07:15:33.479Z",
2622                "createdAt": "2021-12-17T07:15:33.479Z",
2623                "updatedAt": "2021-12-17T07:15:33.479Z",
2624                "autoReject": false,
2625                "autoConfirm": true,
2626                "randomizeOptions": false,
2627                "triesLimited": true,
2628                "submitMessage": "This is an extra submit message from the teacher.",
2629                "excludedFromScore": true,
2630                "grantPointsPolicy": "grant_whenever_possible",
2631                "awardPointsEvenIfWrong": false}),
2632        Some(Utc.with_ymd_and_hms(2125, 1, 1, 23, 59, 59).unwrap()),
2633        CommonExerciseData {
2634            exercise_id: Uuid::new_v5(&course.id, b"c1a4831c-cc78-4f42-be18-2a35a7f3b506"),
2635            exercise_slide_id: Uuid::new_v5(&course.id, b"75045b18-aa9d-11ec-b3d1-6f64c2d6d46d"),
2636            exercise_task_id: Uuid::new_v5(&course.id, b"712fd37c-e3d7-4569-8a64-371d7dda9c19"),
2637            block_id: Uuid::new_v5(&course.id, b"6799021d-ff0c-4e4d-b5db-c2c19fba7fb9"),
2638        },
2639    );
2640
2641    pages::update_page(
2642        &mut conn,
2643        PageUpdateArgs {
2644            page_id: front_page.id,
2645            author: teacher_user_id,
2646            cms_page_update: CmsPageUpdate {
2647                title: "Introduction to Course Material".to_string(),
2648                url_path: "/".to_string(),
2649                chapter_id: None,
2650                content: serde_json::to_value(&[
2651                    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.")
2652                    .with_id(Uuid::parse_str("6ad81525-0010-451f-85e5-4832e3e364a8")?),
2653                    GutenbergBlock::course_objective_section()
2654                        .with_id(Uuid::parse_str("2eec7ad7-a95f-406f-acfe-f3a332b86e26")?),
2655                    GutenbergBlock::empty_block_from_name("moocfi/course-chapter-grid".to_string())
2656                        .with_id(Uuid::parse_str("bb51d61b-fd19-44a0-8417-7ffc6058b247")?),
2657                    GutenbergBlock::empty_block_from_name("moocfi/course-progress".to_string())
2658                        .with_id(Uuid::parse_str("1d7c28ca-86ab-4318-8b10-3e5b7cd6e465")?),
2659                ])
2660                .unwrap(),
2661                exercises: vec![],
2662                exercise_slides: vec![],
2663                exercise_tasks: vec![],
2664            },
2665            retain_ids: true,
2666            history_change_reason: HistoryChangeReason::PageSaved,
2667            is_exam_page: false
2668        },
2669        &spec_fetcher,
2670        models_requests::fetch_service_info,
2671    )
2672    .await?;
2673    // FAQ, we should add card/accordion block to visualize here.
2674
2675    let (_page, _history) = pages::insert_course_page(
2676        &mut conn,
2677        &NewCoursePage::new(course.id, 1, "/faq", "FAQ"),
2678        teacher_user_id,
2679    )
2680    .await?;
2681
2682    // Chapter-1
2683    let new_chapter = NewChapter {
2684        chapter_number: 1,
2685        course_id: course.id,
2686        front_page_id: None,
2687        name: "User Interface".to_string(),
2688        color: None,
2689        opens_at: None,
2690        deadline: None,
2691        course_module_id: Some(default_module.id),
2692    };
2693    let (chapter_1, front_page_ch_1) = library::content_management::create_new_chapter(
2694        &mut conn,
2695        PKeyPolicy::Fixed((
2696            Uuid::new_v5(&course.id, b"77e95910-2289-452f-a1dd-8b8bf4a829a0"),
2697            Uuid::new_v5(&course.id, b"91b6887f-8bc0-4df6-89a4-5687890bc955"),
2698        )),
2699        &new_chapter,
2700        teacher_user_id,
2701        &spec_fetcher,
2702        models_requests::fetch_service_info,
2703    )
2704    .await?;
2705    chapters::set_opens_at(&mut conn, chapter_1.id, Utc::now()).await?;
2706
2707    pages::update_page(
2708        &mut conn,
2709        PageUpdateArgs {
2710            page_id: front_page_ch_1.id,
2711            author: teacher_user_id,
2712            cms_page_update: CmsPageUpdate {
2713                title: "User Interface".to_string(),
2714                url_path: "/chapter-1".to_string(),
2715                chapter_id: Some(chapter_1.id),
2716                content: serde_json::to_value(&[
2717                    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.")
2718                    .with_id(Uuid::parse_str("848ac898-81c0-4ebc-881f-6f84e9eaf472")?),
2719                GutenbergBlock::empty_block_from_name("moocfi/pages-in-chapter".to_string())
2720                    .with_id(Uuid::parse_str("c8b36f58-5366-4d6b-b4ec-9fc0bd65950e")?),
2721                GutenbergBlock::empty_block_from_name("moocfi/exercises-in-chapter".to_string())
2722                    .with_id(Uuid::parse_str("457431b0-55db-46ac-90ae-03965f48b27e")?),
2723                ])
2724                .unwrap(),
2725                exercises: vec![],
2726                exercise_slides: vec![],
2727                exercise_tasks: vec![],
2728            },
2729            retain_ids: true,
2730            history_change_reason: HistoryChangeReason::PageSaved,
2731            is_exam_page: false
2732        },
2733        &spec_fetcher,
2734        models_requests::fetch_service_info,
2735    )
2736    .await?;
2737
2738    // /chapter-1/design
2739    let design_content = CmsPageUpdate {
2740        url_path: "/chapter-1/design".to_string(),
2741        title: "Design".to_string(),
2742        chapter_id: Some(chapter_1.id),
2743        exercises: vec![],
2744        exercise_slides: vec![],
2745        exercise_tasks: vec![],
2746        content: serde_json::json!([
2747            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.")
2748                .with_id(Uuid::parse_str("98729704-9dd8-4309-aa08-402f9b2a6071")?),
2749            heading("First heading", Uuid::parse_str("731aa55f-238b-42f4-8c40-c093dd95ee7f")?, 2),
2750            GutenbergBlock::block_with_name_and_attributes(
2751                "core/paragraph",
2752                attributes!{
2753                  "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.",
2754                  "dropCap": false
2755                },
2756            )
2757                .with_id(Uuid::parse_str("9ebddb78-23f6-4440-8d8f-5e4b33abb16f")?),
2758                heading("Second heading", Uuid::parse_str("a70aac40-acda-48e3-8f53-b64370be4585")?, 3),
2759            GutenbergBlock::block_with_name_and_attributes(
2760                "core/paragraph",
2761                attributes!{
2762                  "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.",
2763                  "dropCap": false
2764                },
2765            )
2766                .with_id(Uuid::parse_str("029ae4b5-08b0-49f7-8baf-d916b5f879a2")?),
2767            GutenbergBlock::block_with_name_and_attributes(
2768                "core/paragraph",
2769                attributes!{
2770                  "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.",
2771                  "dropCap": false
2772                },
2773            )
2774            .with_id(Uuid::parse_str("3693e92b-9cf0-485a-b026-2851de58e9cf")?),
2775            heading("Third heading", Uuid::parse_str("4d16bfea-4fa9-4355-bbd4-4c61e33d3d7c")?, 2),
2776            GutenbergBlock::block_with_name_and_attributes(
2777                "core/paragraph",
2778                attributes!{
2779                  "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.",
2780                  "dropCap": false
2781                },
2782            )
2783                .with_id(Uuid::parse_str("4ef39962-634d-488c-be82-f44e5db19421")?),
2784            GutenbergBlock::block_with_name_and_attributes(
2785                "core/paragraph",
2786                attributes!{
2787                  "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.",
2788                  "dropCap": false
2789                },
2790            )
2791            .with_id(Uuid::parse_str("0d47c02a-194e-42a4-927e-fb29a4fda39c")?),
2792        ]),
2793    };
2794    create_page(
2795        &mut conn,
2796        course.id,
2797        teacher_user_id,
2798        Some(chapter_1.id),
2799        design_content,
2800    )
2801    .await?;
2802
2803    // /chapter-1/human-machine-interface
2804    let content_b = CmsPageUpdate {
2805        chapter_id: Some(chapter_1.id),
2806        url_path: "/chapter-1/human-machine-interface".to_string(),
2807        title: "Human-machine interface".to_string(),
2808        exercises: vec![],
2809        exercise_slides: vec![],
2810        exercise_tasks: vec![],
2811        content: serde_json::json!([
2812            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.")
2813                .with_id(Uuid::parse_str("ae22ae64-c0e5-42e1-895a-4a49411a72e8")?),
2814            GutenbergBlock::block_with_name_and_attributes(
2815                "core/paragraph",
2816                attributes!{
2817                  "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.",
2818                  "dropCap": false
2819                },
2820            )
2821                .with_id(Uuid::parse_str("b05a62ad-e5f7-432c-8c88-2976d971e7e1")?),
2822            GutenbergBlock::block_with_name_and_attributes(
2823                "core/paragraph",
2824                attributes!{
2825                    "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.",
2826                    "dropCap": false
2827                },
2828            )
2829                .with_id(Uuid::parse_str("db20e302-d4e2-4f56-a0b9-e48a4fbd5fa8")?),
2830            GutenbergBlock::block_with_name_and_attributes(
2831                "core/paragraph",
2832                attributes!{
2833                  "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.",
2834                  "dropCap": false
2835                },
2836            )
2837            .with_id(Uuid::parse_str("c96f56d5-ea35-4aae-918a-72a36847a49c")?),
2838        ]),
2839    };
2840    create_page(
2841        &mut conn,
2842        course.id,
2843        teacher_user_id,
2844        Some(chapter_1.id),
2845        content_b,
2846    )
2847    .await?;
2848
2849    // Chapter-2
2850    let new_chapter_2 = NewChapter {
2851        chapter_number: 2,
2852        course_id: course.id,
2853        front_page_id: None,
2854        name: "User Experience".to_string(),
2855        color: None,
2856        opens_at: None,
2857        deadline: None,
2858        course_module_id: Some(default_module.id),
2859    };
2860    let (chapter_2, front_page_ch_2) = library::content_management::create_new_chapter(
2861        &mut conn,
2862        PKeyPolicy::Fixed((
2863            Uuid::new_v5(&course.id, b"5adff726-8910-4163-9fdb-e2f0f45c04d7"),
2864            Uuid::new_v5(&course.id, b"4d916791-5a09-4e3c-8201-c46509e0b2c7"),
2865        )),
2866        &new_chapter_2,
2867        teacher_user_id,
2868        &spec_fetcher,
2869        models_requests::fetch_service_info,
2870    )
2871    .await?;
2872    chapters::set_opens_at(&mut conn, chapter_2.id, Utc::now()).await?;
2873
2874    pages::update_page(
2875        &mut conn,
2876        PageUpdateArgs {
2877            page_id: front_page_ch_2.id,
2878            author: teacher_user_id,
2879            cms_page_update: CmsPageUpdate {
2880                url_path: "/chapter-2".to_string(),
2881                title: "User Experience".to_string(),
2882                chapter_id: Some(chapter_2.id),
2883                content: serde_json::to_value(&[
2884                    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.")
2885                        .with_id(Uuid::parse_str("c5c623f9-c7ca-4f8e-b04b-e91cecef217a")?),
2886                    GutenbergBlock::empty_block_from_name("moocfi/pages-in-chapter".to_string())
2887                        .with_id(Uuid::parse_str("37bbc4e9-2e96-45ea-a6f8-bbc7dc7f6be3")?),
2888                    GutenbergBlock::empty_block_from_name("moocfi/exercises-in-chapter".to_string())
2889                        .with_id(Uuid::parse_str("1bf7e311-75e8-48ec-bd55-e8f1185d76d0")?),
2890                ])
2891                .unwrap(),
2892                exercises: vec![],
2893                exercise_slides: vec![],
2894                exercise_tasks: vec![],
2895            },
2896            retain_ids: true,
2897            history_change_reason: HistoryChangeReason::PageSaved,
2898            is_exam_page: false
2899        },
2900        &spec_fetcher,
2901        models_requests::fetch_service_info,
2902    )
2903    .await?;
2904    // /chapter-2/user-research
2905    let page_content = CmsPageUpdate {
2906        chapter_id: Some(chapter_2.id),
2907        content: serde_json::json!([
2908            GutenbergBlock::hero_section("User research", "User research focuses on understanding user behaviors, needs, and motivations through observation techniques, task analysis, and other feedback methodologies.")
2909                .with_id(Uuid::parse_str("a43f5460-b588-44ac-84a3-5fdcabd5d3f7")?),
2910            GutenbergBlock::block_with_name_and_attributes(
2911                "core/paragraph",
2912                attributes!{
2913                  "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.",
2914                  "dropCap": false
2915                },
2916            )
2917                .with_id(Uuid::parse_str("816310e3-bbd7-44ae-87cb-3f40633a4b08")?),
2918            GutenbergBlock::block_with_name_and_attributes(
2919                "core/paragraph",
2920                attributes!{
2921                  "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.",
2922                  "dropCap": false
2923                },
2924            )
2925                .with_id(Uuid::parse_str("37aa6421-768e-49b9-b447-5f457e5192bc")?),
2926            GutenbergBlock::block_with_name_and_attributes(
2927                "core/paragraph",
2928                attributes!{
2929                    "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.",
2930                  "dropCap": false
2931                },
2932            )
2933            .with_id(Uuid::parse_str("cf11a0fb-f56e-4e0d-bc12-51d920dbc278")?),
2934        ]),
2935        exercises: vec![],
2936        exercise_slides: vec![],
2937        exercise_tasks: vec![],
2938        url_path: "/chapter-2/user-research".to_string(),
2939        title: "User research".to_string(),
2940    };
2941    create_page(
2942        &mut conn,
2943        course.id,
2944        teacher_user_id,
2945        Some(chapter_2.id),
2946        page_content,
2947    )
2948    .await?;
2949
2950    let page_content = include_str!("../../assets/example-page.json");
2951    let parse_page_content = serde_json::from_str(page_content)?;
2952    create_page(
2953        &mut conn,
2954        course.id,
2955        teacher_user_id,
2956        Some(chapter_2.id),
2957        CmsPageUpdate {
2958            content: parse_page_content,
2959            exercises: vec![],
2960            exercise_slides: vec![],
2961            exercise_tasks: vec![],
2962            url_path: "/chapter-2/content-rendering".to_string(),
2963            title: "Content rendering".to_string(),
2964            chapter_id: Some(chapter_2.id),
2965        },
2966    )
2967    .await?;
2968
2969    // Multiple choice
2970
2971    create_page(
2972        &mut conn,
2973        course.id,
2974        teacher_user_id,
2975        Some(chapter_2.id),
2976        CmsPageUpdate {
2977            url_path: "/chapter-2/page-3".to_string(),
2978            title: "Page 3".to_string(),
2979            chapter_id: Some(chapter_2.id),
2980            exercises: vec![quizzes_exercise_5],
2981            exercise_slides: vec![quizzes_exercise_slide_5],
2982            exercise_tasks: vec![quizzes_exercise_task_5],
2983            content: serde_json::json!([
2984                paragraph(
2985                    "Second chapters third page",
2986                    Uuid::new_v5(&course.id, b"4ebd0208-8328-5d69-8c44-ec50939c0967")
2987                ),
2988                quizzes_exercise_block_5,
2989            ]),
2990        },
2991    )
2992    .await?;
2993
2994    create_page(
2995        &mut conn,
2996        course.id,
2997        teacher_user_id,
2998        Some(chapter_2.id),
2999        CmsPageUpdate {
3000            url_path: "/chapter-2/page-4".to_string(),
3001            title: "Page 4".to_string(),
3002            chapter_id: Some(chapter_2.id),
3003            exercises: vec![quizzes_exercise_6],
3004            exercise_slides: vec![quizzes_exercise_slide_6],
3005            exercise_tasks: vec![quizzes_exercise_task_6],
3006            content: serde_json::json!([
3007                paragraph(
3008                    "Second chapters fourth page",
3009                    Uuid::new_v5(&course.id, b"4841cabb-77a0-53cf-b539-39fbd060e73b")
3010                ),
3011                quizzes_exercise_block_6,
3012            ]),
3013        },
3014    )
3015    .await?;
3016
3017    create_page(
3018        &mut conn,
3019        course.id,
3020        teacher_user_id,
3021        Some(chapter_2.id),
3022        CmsPageUpdate {
3023            url_path: "/chapter-2/page-5".to_string(),
3024            title: "Page 5".to_string(),
3025            chapter_id: Some(chapter_2.id),
3026            exercises: vec![quizzes_exercise_7],
3027            exercise_slides: vec![quizzes_exercise_slide_7],
3028            exercise_tasks: vec![quizzes_exercise_task_7],
3029
3030            content: serde_json::json!([
3031                paragraph(
3032                    "Second chapters fifth page",
3033                    Uuid::new_v5(&course.id, b"9a614406-e1b4-5920-8e0d-54d1a3ead5f3")
3034                ),
3035                quizzes_exercise_block_7,
3036            ]),
3037        },
3038    )
3039    .await?;
3040
3041    create_page(
3042        &mut conn,
3043        course.id,
3044        teacher_user_id,
3045        Some(chapter_2.id),
3046        CmsPageUpdate {
3047            url_path: "/chapter-2/page-6".to_string(),
3048            title: "Page 6".to_string(),
3049            chapter_id: Some(chapter_2.id),
3050            exercises: vec![quizzes_exercise_8],
3051            exercise_slides: vec![quizzes_exercise_slide_8],
3052            exercise_tasks: vec![quizzes_exercise_task_8],
3053            content: serde_json::json!([
3054                paragraph(
3055                    "Second chapters sixth page",
3056                    Uuid::new_v5(&course.id, b"891de1ca-f3a9-506f-a268-3477ea4fdd27")
3057                ),
3058                quizzes_exercise_block_8,
3059            ]),
3060        },
3061    )
3062    .await?;
3063
3064    // enrollments
3065    course_instance_enrollments::insert_enrollment_and_set_as_current(
3066        &mut conn,
3067        NewCourseInstanceEnrollment {
3068            course_id: course.id,
3069            course_instance_id: default_instance.id,
3070            user_id: langs_user_id,
3071        },
3072    )
3073    .await?;
3074
3075    Ok(course.id)
3076}
3077
3078pub async fn seed_peer_review_course_without_submissions(
3079    course_id: Uuid,
3080    course_name: &str,
3081    course_slug: &str,
3082    common_course_data: CommonCourseData,
3083) -> Result<Uuid> {
3084    let CommonCourseData {
3085        db_pool,
3086        organization_id: org,
3087        teacher_user_id,
3088        student_user_id: _,
3089        langs_user_id: _,
3090        example_normal_user_ids: _,
3091        jwt_key: _jwt_key,
3092        base_url: _base_url,
3093    } = common_course_data;
3094    let spec_fetcher = get_seed_spec_fetcher();
3095    info!("inserting sample course {}", course_name);
3096    let mut conn = db_pool.acquire().await?;
3097    let new_course = NewCourse {
3098        name: course_name.to_string(),
3099        organization_id: org,
3100        slug: course_slug.to_string(),
3101        language_code: "en-US".to_string(),
3102        teacher_in_charge_name: "admin".to_string(),
3103        teacher_in_charge_email: "admin@example.com".to_string(),
3104        description: "Sample course.".to_string(),
3105        is_draft: false,
3106        is_test_mode: false,
3107        is_unlisted: false,
3108        copy_user_permissions: false,
3109        is_joinable_by_code_only: false,
3110        join_code: None,
3111        ask_marketing_consent: false,
3112        flagged_answers_threshold: Some(3),
3113        can_add_chatbot: false,
3114    };
3115
3116    let (course, _front_page, _, default_module) = library::content_management::create_new_course(
3117        &mut conn,
3118        PKeyPolicy::Fixed(CreateNewCourseFixedIds {
3119            course_id,
3120            default_course_instance_id: Uuid::new_v5(
3121                &course_id,
3122                b"7344f1c8-b7ce-4c7d-ade2-5f39997bd454",
3123            ),
3124        }),
3125        new_course,
3126        teacher_user_id,
3127        &spec_fetcher,
3128        models_requests::fetch_service_info,
3129    )
3130    .await?;
3131
3132    course_instances::insert(
3133        &mut conn,
3134        PKeyPolicy::Fixed(Uuid::new_v5(
3135            &course_id,
3136            b"67f077b4-0562-47ae-a2b9-db2f08f168a9",
3137        )),
3138        NewCourseInstance {
3139            course_id: course.id,
3140            name: Some("Non-default instance"),
3141            description: Some("This is a non-default instance"),
3142            support_email: Some("contact@example.com"),
3143            teacher_in_charge_name: "admin",
3144            teacher_in_charge_email: "admin@example.com",
3145            opening_time: None,
3146            closing_time: None,
3147        },
3148    )
3149    .await?;
3150
3151    // chapters and pages
3152
3153    let new_chapter = NewChapter {
3154        chapter_number: 1,
3155        course_id: course.id,
3156        front_page_id: None,
3157        name: "The Basics".to_string(),
3158        color: None,
3159        opens_at: None,
3160        deadline: Some(Utc.with_ymd_and_hms(2225, 1, 1, 23, 59, 59).unwrap()),
3161
3162        course_module_id: Some(default_module.id),
3163    };
3164
3165    let (chapter_1, _front_page_1) = library::content_management::create_new_chapter(
3166        &mut conn,
3167        PKeyPolicy::Fixed((
3168            Uuid::new_v5(&course_id, b"bfc557e1-0f8e-4f10-8e21-d7d8ffe50a3a"),
3169            Uuid::new_v5(&course_id, b"b1e392db-482a-494e-9cbb-c87bbc70e340"),
3170        )),
3171        &new_chapter,
3172        teacher_user_id,
3173        &spec_fetcher,
3174        models_requests::fetch_service_info,
3175    )
3176    .await?;
3177
3178    chapters::set_opens_at(&mut conn, chapter_1.id, Utc::now()).await?;
3179
3180    let welcome_page = NewCoursePage::new(
3181        course.id,
3182        1,
3183        "/welcome",
3184        "Welcome to Introduction to peer reviews",
3185    );
3186    let (_page, _) = pages::insert_course_page(&mut conn, &welcome_page, teacher_user_id).await?;
3187    let hidden_page = welcome_page
3188        .followed_by("/hidden", "Hidden Page")
3189        .set_hidden(true)
3190        .set_content(vec![GutenbergBlock::paragraph(
3191            "You found the secret of the project 331!",
3192        )]);
3193    let (_page, _) = pages::insert_course_page(&mut conn, &hidden_page, teacher_user_id).await?;
3194
3195    info!("sample exercises");
3196    let block_id_1 = Uuid::new_v5(&course_id, b"4ef933d8-170f-4437-a5af-bc7690cfac5a");
3197    let block_id_2 = Uuid::new_v5(&course_id, b"35510467-9a7b-46de-9878-d9d34a1821a4");
3198    let exercise_1_id = Uuid::new_v5(&course_id, b"bae98f14-9ffd-4647-8f28-fe4a5967d6e9");
3199    let exercise_1_slide_1_id = Uuid::new_v5(&course_id, b"6d3feb9c-fc95-4908-803f-1b0d0e3f2c18");
3200    let exercise_1_slide_1_task_1_id =
3201        Uuid::new_v5(&course_id, b"47517fe6-d5e2-4b8f-8d94-541a4d849aed");
3202    let exercise_1_slide_1_task_1_spec_1_id =
3203        Uuid::new_v5(&course_id, b"847a2144-e55b-4c2f-a6a7-98bbe7927d10");
3204    let exercise_1_slide_1_task_1_spec_2_id =
3205        Uuid::new_v5(&course_id, b"979a00a7-2e8a-4294-9e46-3367c372864f");
3206    let exercise_1_slide_1_task_1_spec_3_id =
3207        Uuid::new_v5(&course_id, b"b354830c-38c7-4b83-8370-0e7222272c56");
3208
3209    let (exercise_block_1, exercise_1, slide_1, task_1) = create_best_exercise(
3210        block_id_2,
3211        exercise_1_slide_1_task_1_spec_1_id,
3212        exercise_1_slide_1_task_1_spec_2_id,
3213        exercise_1_slide_1_task_1_spec_3_id,
3214        Some("ManualReviewEverything".to_string()),
3215        CommonExerciseData {
3216            exercise_id: exercise_1_id,
3217            exercise_slide_id: exercise_1_slide_1_id,
3218            exercise_task_id: exercise_1_slide_1_task_1_id,
3219            block_id: block_id_1,
3220        },
3221    );
3222
3223    create_page(
3224        &mut conn,
3225        course.id,
3226        teacher_user_id,
3227        Some(chapter_1.id),
3228        CmsPageUpdate {
3229            url_path: "/chapter-1/page-1".to_string(),
3230            title: "Page One".to_string(),
3231            chapter_id: Some(chapter_1.id),
3232            exercises: vec![exercise_1],
3233            exercise_slides: vec![slide_1],
3234            exercise_tasks: vec![task_1],
3235            content: serde_json::json!([exercise_block_1,]),
3236        },
3237    )
3238    .await?;
3239
3240    create_best_peer_review(
3241        &mut conn,
3242        course_id,
3243        exercise_1_id,
3244        ManualReviewEverything,
3245        3.0,
3246        true,
3247        2,
3248        1,
3249    )
3250    .await?;
3251
3252    let block_id_3 = Uuid::new_v5(&course_id, b"4b57812a-6509-4783-a746-3e382adf5060");
3253    let block_id_4 = Uuid::new_v5(&course_id, b"d315f5bb-306f-478b-846c-ca5f1407f2db");
3254    let exercise_2_id = Uuid::new_v5(&course_id, b"39f23830-d2eb-4232-b6f7-78822f0e0fbd");
3255    let exercise_2_slide_1_id = Uuid::new_v5(&course_id, b"cbbbee55-511b-45be-9d95-1fa9273497ee");
3256    let exercise_2_slide_1_task_1_id =
3257        Uuid::new_v5(&course_id, b"a2ae64bd-9518-4c2b-88c1-49ba103f14ff");
3258    let exercise_2_slide_1_task_1_spec_1_id =
3259        Uuid::new_v5(&course_id, b"f1cd2f78-a489-4cae-a656-86aa574faf19");
3260    let exercise_2_slide_1_task_1_spec_2_id =
3261        Uuid::new_v5(&course_id, b"5435b9ae-d811-43b6-b208-23f64267eef1");
3262    let exercise_2_slide_1_task_1_spec_3_id =
3263        Uuid::new_v5(&course_id, b"9f6e4ad4-b9f5-40cf-b071-642da7058fec");
3264
3265    let (exercise_block_2, exercise_2, slide_1, task_1) = create_best_exercise(
3266        block_id_4,
3267        exercise_2_slide_1_task_1_spec_1_id,
3268        exercise_2_slide_1_task_1_spec_2_id,
3269        exercise_2_slide_1_task_1_spec_3_id,
3270        Some("AutomaticallyGradeOrManualReviewByAverage".to_string()),
3271        CommonExerciseData {
3272            exercise_id: exercise_2_id,
3273            exercise_slide_id: exercise_2_slide_1_id,
3274            exercise_task_id: exercise_2_slide_1_task_1_id,
3275            block_id: block_id_3,
3276        },
3277    );
3278
3279    create_page(
3280        &mut conn,
3281        course.id,
3282        teacher_user_id,
3283        Some(chapter_1.id),
3284        CmsPageUpdate {
3285            url_path: "/chapter-1/page-2".to_string(),
3286            title: "Page Two".to_string(),
3287            chapter_id: Some(chapter_1.id),
3288            exercises: vec![exercise_2],
3289            exercise_slides: vec![slide_1],
3290            exercise_tasks: vec![task_1],
3291            content: serde_json::json!([exercise_block_2]),
3292        },
3293    )
3294    .await?;
3295
3296    create_best_peer_review(
3297        &mut conn,
3298        course_id,
3299        exercise_2_id,
3300        AutomaticallyGradeOrManualReviewByAverage,
3301        3.0,
3302        true,
3303        2,
3304        1,
3305    )
3306    .await?;
3307
3308    let block_id_5 = Uuid::new_v5(&course_id, b"591b1612-36c8-4f02-841b-d5f95be9b410");
3309    let block_id_6 = Uuid::new_v5(&course_id, b"2adbaaef-6213-4b83-ba8f-827e5a4f084f");
3310    let exercise_3_id = Uuid::new_v5(&course_id, b"3b4e964b-8992-4595-92ad-bdb1721e9352");
3311    let exercise_3_slide_1_id = Uuid::new_v5(&course_id, b"d0596f5c-885b-483e-9f59-271b289e4220");
3312    let exercise_3_slide_1_task_1_id =
3313        Uuid::new_v5(&course_id, b"170a97c9-2e75-4817-af17-5e45bd362260");
3314    let exercise_3_slide_1_task_1_spec_1_id =
3315        Uuid::new_v5(&course_id, b"b74450cf-e8a5-4689-b2a4-7a0ed491dcbc");
3316    let exercise_3_slide_1_task_1_spec_2_id =
3317        Uuid::new_v5(&course_id, b"f27a8e35-2d72-406d-9c99-fd8b7c1991a3");
3318    let exercise_3_slide_1_task_1_spec_3_id =
3319        Uuid::new_v5(&course_id, b"31443721-fc55-4ea6-9b2a-2da8a6a991df");
3320
3321    let (exercise_block_3, exercise_3, slide_1, task_1) = create_best_exercise(
3322        block_id_6,
3323        exercise_3_slide_1_task_1_spec_1_id,
3324        exercise_3_slide_1_task_1_spec_2_id,
3325        exercise_3_slide_1_task_1_spec_3_id,
3326        Some("AutomaticallyGradeByAverage".to_string()),
3327        CommonExerciseData {
3328            exercise_id: exercise_3_id,
3329            exercise_slide_id: exercise_3_slide_1_id,
3330            exercise_task_id: exercise_3_slide_1_task_1_id,
3331            block_id: block_id_5,
3332        },
3333    );
3334
3335    create_page(
3336        &mut conn,
3337        course.id,
3338        teacher_user_id,
3339        Some(chapter_1.id),
3340        CmsPageUpdate {
3341            url_path: "/chapter-1/page-3".to_string(),
3342            title: "Page Three".to_string(),
3343            chapter_id: Some(chapter_1.id),
3344            exercises: vec![exercise_3],
3345            exercise_slides: vec![slide_1],
3346            exercise_tasks: vec![task_1],
3347            content: serde_json::json!([exercise_block_3,]),
3348        },
3349    )
3350    .await?;
3351
3352    create_best_peer_review(
3353        &mut conn,
3354        course_id,
3355        exercise_3_id,
3356        AutomaticallyGradeByAverage,
3357        3.0,
3358        true,
3359        2,
3360        1,
3361    )
3362    .await?;
3363
3364    let block_id_7 = Uuid::new_v5(&course_id, b"80e97fbc-ebc1-46f3-a19c-04cdb9f3d349");
3365    let block_id_8 = Uuid::new_v5(&course_id, b"db818c1f-0667-4050-9289-7224a8ca3c5c");
3366    let exercise_4_id = Uuid::new_v5(&course_id, b"65cde761-6ccd-4804-8343-c85b1d3d6fc4");
3367    let exercise_4_slide_1_id = Uuid::new_v5(&course_id, b"b37771bc-37d0-4cae-b06d-c35256f289a5");
3368    let exercise_4_slide_1_task_1_id =
3369        Uuid::new_v5(&course_id, b"0ecaff02-d8cf-44c3-be8c-ea2449c02d0f");
3370    let exercise_4_slide_1_task_1_spec_1_id =
3371        Uuid::new_v5(&course_id, b"caaf7ec5-fd2b-4e07-b185-58b8070b059e");
3372    let exercise_4_slide_1_task_1_spec_2_id =
3373        Uuid::new_v5(&course_id, b"f92ba66c-fe8a-4711-b25a-73a13c451543");
3374    let exercise_4_slide_1_task_1_spec_3_id =
3375        Uuid::new_v5(&course_id, b"c17f23ca-7daa-40dd-b390-1ac8531dd17d");
3376
3377    let (exercise_block_1, exercise_1, slide_1, task_1) = create_best_exercise(
3378        block_id_8,
3379        exercise_4_slide_1_task_1_spec_1_id,
3380        exercise_4_slide_1_task_1_spec_2_id,
3381        exercise_4_slide_1_task_1_spec_3_id,
3382        Some("ManualReviewEverything2".to_string()),
3383        CommonExerciseData {
3384            exercise_id: exercise_4_id,
3385            exercise_slide_id: exercise_4_slide_1_id,
3386            exercise_task_id: exercise_4_slide_1_task_1_id,
3387            block_id: block_id_7,
3388        },
3389    );
3390
3391    create_page(
3392        &mut conn,
3393        course.id,
3394        teacher_user_id,
3395        Some(chapter_1.id),
3396        CmsPageUpdate {
3397            url_path: "/chapter-1/page-4".to_string(),
3398            title: "Page Four".to_string(),
3399            chapter_id: Some(chapter_1.id),
3400            exercises: vec![exercise_1],
3401            exercise_slides: vec![slide_1],
3402            exercise_tasks: vec![task_1],
3403            content: serde_json::json!([exercise_block_1,]),
3404        },
3405    )
3406    .await?;
3407
3408    create_best_peer_review(
3409        &mut conn,
3410        course_id,
3411        exercise_4_id,
3412        ManualReviewEverything,
3413        3.0,
3414        true,
3415        2,
3416        1,
3417    )
3418    .await?;
3419
3420    let block_id_9 = Uuid::new_v5(&course_id, b"54349cc8-dbba-4223-b5e0-71fafdfe8fd3");
3421    let block_id_10 = Uuid::new_v5(&course_id, b"ee05ad17-07dc-4c3b-be63-67bd2a4ac46a");
3422    let exercise_5_id = Uuid::new_v5(&course_id, b"31717e20-8fe5-451c-a7d3-bca09d0ea14f");
3423    let exercise_5_slide_1_id = Uuid::new_v5(&course_id, b"9bd990d1-3cd6-4e23-b372-8860ebd8bac5");
3424    let exercise_5_slide_1_task_1_id =
3425        Uuid::new_v5(&course_id, b"fe5da9f8-aaae-4b05-9cf9-29f3cde55bd7");
3426    let exercise_5_slide_1_task_1_spec_1_id =
3427        Uuid::new_v5(&course_id, b"5efb1377-70af-455f-ad78-cddd0bd6cbb1");
3428    let exercise_5_slide_1_task_1_spec_2_id =
3429        Uuid::new_v5(&course_id, b"f92ba66c-fe8a-4711-b25a-73a13c451543");
3430    let exercise_5_slide_1_task_1_spec_3_id =
3431        Uuid::new_v5(&course_id, b"75bbc9f6-84f2-4182-80d1-07bd7c435d6c");
3432
3433    let (exercise_block_1, exercise_1, slide_1, task_1) = create_best_exercise(
3434        block_id_10,
3435        exercise_5_slide_1_task_1_spec_1_id,
3436        exercise_5_slide_1_task_1_spec_2_id,
3437        exercise_5_slide_1_task_1_spec_3_id,
3438        Some("Can give extra reviews".to_string()),
3439        CommonExerciseData {
3440            exercise_id: exercise_5_id,
3441            exercise_slide_id: exercise_5_slide_1_id,
3442            exercise_task_id: exercise_5_slide_1_task_1_id,
3443            block_id: block_id_9,
3444        },
3445    );
3446
3447    create_page(
3448        &mut conn,
3449        course.id,
3450        teacher_user_id,
3451        Some(chapter_1.id),
3452        CmsPageUpdate {
3453            url_path: "/chapter-1/can-give-extra-reviews".to_string(),
3454            title: "Can give extra peer reviews".to_string(),
3455            chapter_id: Some(chapter_1.id),
3456            exercises: vec![exercise_1],
3457            exercise_slides: vec![slide_1],
3458            exercise_tasks: vec![task_1],
3459            content: serde_json::json!([exercise_block_1,]),
3460        },
3461    )
3462    .await?;
3463
3464    create_best_peer_review(
3465        &mut conn,
3466        course_id,
3467        exercise_5_id,
3468        AutomaticallyGradeByAverage,
3469        3.0,
3470        true,
3471        3,
3472        2,
3473    )
3474    .await?;
3475
3476    Ok(course.id)
3477}