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 .automatic_completion(Some(1), Some(1), false)
75 .chapter(
76 ChapterBuilder::new(1, "The Basics")
77 .opens(Utc::now())
78 .fixed_ids(cx.v5(b"chapter:1"), cx.v5(b"chapter:1:instance"))
79 .page(
80 PageBuilder::new("/chapter-1/page-1", "Page One")
81 .block(paragraph(
82 "This is a simple introduction to the basics.",
83 cx.v5(b"page:1:1:block:intro"),
84 ))
85 .exercise(ExerciseBuilder::example_exercise(
86 "Simple multiple choice with peer review",
87 ExerciseIds {
88 exercise_id: cx.v5(b"exercise:1:1:e"),
89 slide_id: cx.v5(b"exercise:1:1:s"),
90 task_id: cx.v5(b"exercise:1:1:t"),
91 block_id: cx.v5(b"exercise:1:1:b"),
92 },
93 vec![paragraph(
94 "What is 2 + 2?",
95 cx.v5(b"exercise:1:1:prompt"),
96 )],
97 json!([
98 {
99 "name": "3",
100 "correct": false,
101 "id": cx.v5(b"exercise:1:1:option:1")
102 },
103 {
104 "name": "4",
105 "correct": true,
106 "id": cx.v5(b"exercise:1:1:option:2")
107 },
108 {
109 "name": "5",
110 "correct": false,
111 "id": cx.v5(b"exercise:1:1:option:3")
112 }
113 ]),
114 true,
115 Some(CmsPeerOrSelfReviewConfig {
116 id: cx.v5(b"peer-review:1"),
117 course_id,
118 exercise_id: Some(cx.v5(b"exercise:1:1:e")),
119 peer_reviews_to_give: 2,
120 peer_reviews_to_receive: 1,
121 accepting_threshold: 2.1,
122 processing_strategy:
123 PeerReviewProcessingStrategy::AutomaticallyGradeOrManualReviewByAverage,
124 reset_answer_if_zero_points_from_review: false,
125 points_are_all_or_nothing: true,
126 review_instructions: None,
127 }),
128 Some(vec![CmsPeerOrSelfReviewQuestion {
129 id: cx.v5(b"peer-review:1:q1"),
130 peer_or_self_review_config_id: cx.v5(b"peer-review:1"),
131 order_number: 1,
132 question: "Good answer?".to_string(),
133 question_type:
134 headless_lms_models::peer_or_self_review_questions::PeerOrSelfReviewQuestionType::Scale,
135 answer_required: true,
136 weight: 0.0,
137 }]),
138 ))
139 .exercise(ExerciseBuilder::example_exercise(
140 "Simple multiple choice with automatic reset on zero score",
141 ExerciseIds {
142 exercise_id: cx.v5(b"exercise:2:1:e"),
143 slide_id: cx.v5(b"exercise:2:1:s"),
144 task_id: cx.v5(b"exercise:2:1:t"),
145 block_id: cx.v5(b"exercise:2:1:b"),
146 },
147 vec![paragraph(
148 "What is 2 + 2?",
149 cx.v5(b"exercise:2:1:prompt"),
150 )],
151 json!([
152 {
153 "name": "3",
154 "correct": false,
155 "id": cx.v5(b"exercise:2:1:option:1")
156 },
157 {
158 "name": "4",
159 "correct": true,
160 "id": cx.v5(b"exercise:2:1:option:2")
161 },
162 {
163 "name": "5",
164 "correct": false,
165 "id": cx.v5(b"exercise:2:1:option:3")
166 }
167 ]),
168 true,
169 Some(CmsPeerOrSelfReviewConfig {
170 id: cx.v5(b"peer-review:2"),
171 course_id,
172 exercise_id: Some(cx.v5(b"exercise:2:1:e")),
173 peer_reviews_to_give: 2,
174 peer_reviews_to_receive: 1,
175 accepting_threshold: 2.1,
176 processing_strategy:
177 PeerReviewProcessingStrategy::AutomaticallyGradeByAverage,
178 reset_answer_if_zero_points_from_review: true,
179 points_are_all_or_nothing: true,
180 review_instructions: None,
181 }),
182 Some(vec![CmsPeerOrSelfReviewQuestion {
183 id: cx.v5(b"peer-review:2:q1"),
184 peer_or_self_review_config_id: cx.v5(b"peer-review:2"),
185 order_number: 1,
186 question: "Good answer?".to_string(),
187 question_type:
188 headless_lms_models::peer_or_self_review_questions::PeerOrSelfReviewQuestionType::Scale,
189 answer_required: true,
190 weight: 0.0,
191 }]),
192 )),
193 ),
194 ),
195 );
196 let (course, _default_instance, _last_module) = course.seed(&mut conn, app_config, &cx).await?;
197 Ok(course.id)
198}