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