headless_lms_server/programs/seed/seed_courses/
mod.rs

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