headless_lms_server/programs/seed/seed_courses/
seed_course_with_peer_review.rs1use crate::programs::seed::builder::chapter::ChapterBuilder;
2use crate::programs::seed::builder::context::SeedContext;
3use crate::programs::seed::builder::course::{CourseBuilder, CourseInstanceConfig};
4use crate::programs::seed::builder::exercise::{ExerciseBuilder, ExerciseIds};
5use crate::programs::seed::builder::module::ModuleBuilder;
6use crate::programs::seed::builder::page::PageBuilder;
7use crate::programs::seed::seed_courses::CommonCourseData;
8use crate::programs::seed::seed_helpers::paragraph;
9use anyhow::Result;
10use chrono::Utc;
11
12use headless_lms_base::config::ApplicationConfiguration;
13use headless_lms_models::peer_or_self_review_configs::{
14 CmsPeerOrSelfReviewConfig, PeerReviewProcessingStrategy,
15};
16use headless_lms_models::peer_or_self_review_questions::CmsPeerOrSelfReviewQuestion;
17use headless_lms_models::roles::UserRole;
18use serde_json::json;
19use tracing::info;
20use uuid::Uuid;
21
22use super::super::seed_users::SeedUsersResult;
23
24#[allow(clippy::too_many_arguments)]
25pub async fn seed_peer_review_course(
26 app_config: &ApplicationConfiguration,
27 course_id: Uuid,
28 course_name: &str,
29 course_slug: &str,
30 common_course_data: CommonCourseData,
31 seed_users_result: SeedUsersResult,
32 flagged_answers_skip_manual_review_and_allow_retry: bool,
33 flagged_answers_threshold: Option<i32>,
34) -> Result<Uuid> {
35 let CommonCourseData {
36 db_pool,
37 organization_id: org,
38 teacher_user_id,
39 student_user_id: _student,
40 langs_user_id: _langs_user_id,
41 example_normal_user_ids: _users,
42 jwt_key: _jwt_key,
43 base_url: _base_url,
44 } = common_course_data;
45
46 let mut conn = db_pool.acquire().await?;
47 let cx = SeedContext {
48 teacher: teacher_user_id,
49 org,
50 base_course_ns: course_id,
51 };
52
53 info!("Inserting sample course {}", course_name);
54 let course = CourseBuilder::new(course_name, course_slug)
55 .desc("Sample course for testing reject and reset-feature in manual review after peer review.")
56 .chatbot(false)
57 .course_id(course_id)
58 .flagged_answers_skip_manual_review_and_allow_retry(flagged_answers_skip_manual_review_and_allow_retry)
59 .flagged_answers_threshold(flagged_answers_threshold)
60 .instance(CourseInstanceConfig {
61 name: None,
62 description: None,
63 support_email: None,
64 teacher_in_charge_name: "admin".to_string(),
65 teacher_in_charge_email: "admin@example.com".to_string(),
66 opening_time: None,
67 closing_time: None,
68 instance_id: Some(cx.v5(b"instance:default")),
69 })
70 .role(seed_users_result.teacher_user_id, UserRole::Teacher)
71 .module(
72 ModuleBuilder::new()
73 .order(0)
74 .register_to_open_university(false)
75 .automatic_completion(Some(1), Some(1), false)
76 .chapter(
77 ChapterBuilder::new(1, "The Basics")
78 .opens(Utc::now())
79 .fixed_ids(cx.v5(b"chapter:1"), cx.v5(b"chapter:1:instance"))
80 .page(
81 PageBuilder::new("/chapter-1/page-1", "Page One")
82 .block(paragraph(
83 "This is a simple introduction to the basics.",
84 cx.v5(b"page:1:1:block:intro"),
85 ))
86 .exercise(ExerciseBuilder::example_exercise(
87 "Simple multiple choice with peer review",
88 ExerciseIds {
89 exercise_id: cx.v5(b"exercise:1:1:e"),
90 slide_id: cx.v5(b"exercise:1:1:s"),
91 task_id: cx.v5(b"exercise:1:1:t"),
92 block_id: cx.v5(b"exercise:1:1:b"),
93 },
94 vec![paragraph(
95 "What is 2 + 2?",
96 cx.v5(b"exercise:1:1:prompt"),
97 )],
98 json!([
99 {
100 "name": "3",
101 "correct": false,
102 "id": cx.v5(b"exercise:1:1:option:1")
103 },
104 {
105 "name": "4",
106 "correct": true,
107 "id": cx.v5(b"exercise:1:1:option:2")
108 },
109 {
110 "name": "5",
111 "correct": false,
112 "id": cx.v5(b"exercise:1:1:option:3")
113 }
114 ]),
115 true,
116 Some(CmsPeerOrSelfReviewConfig {
117 id: cx.v5(b"peer-review:1"),
118 course_id,
119 exercise_id: Some(cx.v5(b"exercise:1:1:e")),
120 peer_reviews_to_give: 2,
121 peer_reviews_to_receive: 1,
122 accepting_threshold: 2.1,
123 processing_strategy:
124 PeerReviewProcessingStrategy::AutomaticallyGradeOrManualReviewByAverage,
125 reset_answer_if_zero_points_from_review: false,
126 points_are_all_or_nothing: true,
127 review_instructions: None,
128 }),
129 Some(vec![CmsPeerOrSelfReviewQuestion {
130 id: cx.v5(b"peer-review:1:q1"),
131 peer_or_self_review_config_id: cx.v5(b"peer-review:1"),
132 order_number: 1,
133 question: "Good answer?".to_string(),
134 question_type:
135 headless_lms_models::peer_or_self_review_questions::PeerOrSelfReviewQuestionType::Scale,
136 answer_required: true,
137 weight: 0.0,
138 }]),
139 ))
140 .exercise(ExerciseBuilder::example_exercise(
141 "Simple multiple choice with automatic reset on zero score",
142 ExerciseIds {
143 exercise_id: cx.v5(b"exercise:2:1:e"),
144 slide_id: cx.v5(b"exercise:2:1:s"),
145 task_id: cx.v5(b"exercise:2:1:t"),
146 block_id: cx.v5(b"exercise:2:1:b"),
147 },
148 vec![paragraph(
149 "What is 2 + 2?",
150 cx.v5(b"exercise:2:1:prompt"),
151 )],
152 json!([
153 {
154 "name": "3",
155 "correct": false,
156 "id": cx.v5(b"exercise:2:1:option:1")
157 },
158 {
159 "name": "4",
160 "correct": true,
161 "id": cx.v5(b"exercise:2:1:option:2")
162 },
163 {
164 "name": "5",
165 "correct": false,
166 "id": cx.v5(b"exercise:2:1:option:3")
167 }
168 ]),
169 true,
170 Some(CmsPeerOrSelfReviewConfig {
171 id: cx.v5(b"peer-review:2"),
172 course_id,
173 exercise_id: Some(cx.v5(b"exercise:2:1:e")),
174 peer_reviews_to_give: 2,
175 peer_reviews_to_receive: 1,
176 accepting_threshold: 2.1,
177 processing_strategy:
178 PeerReviewProcessingStrategy::AutomaticallyGradeByAverage,
179 reset_answer_if_zero_points_from_review: true,
180 points_are_all_or_nothing: true,
181 review_instructions: None,
182 }),
183 Some(vec![CmsPeerOrSelfReviewQuestion {
184 id: cx.v5(b"peer-review:2:q1"),
185 peer_or_self_review_config_id: cx.v5(b"peer-review:2"),
186 order_number: 1,
187 question: "Good answer?".to_string(),
188 question_type:
189 headless_lms_models::peer_or_self_review_questions::PeerOrSelfReviewQuestionType::Scale,
190 answer_required: true,
191 weight: 0.0,
192 }]),
193 )),
194 ),
195 ),
196 );
197 let (course, _default_instance, _last_module) = course.seed(&mut conn, app_config, &cx).await?;
198 Ok(course.id)
199}