1use std::sync::Arc;
2
3use headless_lms_models::{
4 PKeyPolicy,
5 chatbot_configurations::{self, NewChatbotConf},
6 course_instances::{self, NewCourseInstance},
7 course_modules::{self, AutomaticCompletionRequirements, CompletionPolicy},
8 courses::NewCourse,
9 library::{self, content_management::CreateNewCourseFixedIds, copying::copy_course},
10 organizations,
11 roles::{self, RoleDomain, UserRole},
12};
13use uuid::Uuid;
14
15use sqlx::{Pool, Postgres};
16
17use crate::{
18 domain::models_requests::{self, JwtKey},
19 programs::seed::{
20 seed_courses::{
21 CommonCourseData, seed_chatbot::seed_chatbot_course,
22 seed_course_with_peer_review::seed_peer_review_course,
23 seed_peer_review_course_without_submissions, seed_sample_course,
24 seed_switching_course_instances_course,
25 },
26 seed_file_storage::SeedFileStorageResult,
27 seed_helpers::get_seed_spec_fetcher,
28 },
29};
30
31use super::super::seed_users::SeedUsersResult;
32
33pub async fn seed_organization_uh_mathstat(
34 db_pool: Pool<Postgres>,
35 seed_users_result: SeedUsersResult,
36 base_url: String,
37 jwt_key: Arc<JwtKey>,
38 seed_file_storage_result: SeedFileStorageResult,
40) -> anyhow::Result<Uuid> {
41 info!("seeding organization uh-mathstat");
42
43 let SeedUsersResult {
44 teacher_user_id,
45 admin_user_id: _,
46 language_teacher_user_id: _,
47 material_viewer_user_id,
48 assistant_user_id: _,
49 course_or_exam_creator_user_id: _,
50 example_normal_user_ids,
51 teaching_and_learning_services_user_id: _,
52 student_without_research_consent: _,
53 student_without_country: _,
54 user_user_id: _,
55 student_1_user_id: _,
56 student_2_user_id: _,
57 student_3_user_id,
58 student_4_user_id: _,
59 student_5_user_id: _,
60 student_6_user_id: _,
61 langs_user_id,
62 sign_up_user: _,
63 } = seed_users_result;
64 let _ = seed_file_storage_result;
65
66 let mut conn = db_pool.acquire().await?;
67
68 let uh_mathstat_id = organizations::insert(
69 &mut conn,
70 PKeyPolicy::Fixed(Uuid::parse_str("269d28b2-a517-4572-9955-3ed5cecc69bd")?),
71 "University of Helsinki, Department of Mathematics and Statistics",
72 "uh-mathstat",
73 Some("Organization for Mathematics and Statistics courses. This organization creates courses that do require prior experience in mathematics, such as integration and induction."),
74 false,
75 )
76 .await?;
77
78 roles::insert(
79 &mut conn,
80 material_viewer_user_id,
81 UserRole::MaterialViewer,
82 RoleDomain::Organization(uh_mathstat_id),
83 )
84 .await?;
85
86 let new_course = NewCourse {
87 name: "Introduction to Statistics".to_string(),
88 slug: "introduction-to-statistics".to_string(),
89 organization_id: uh_mathstat_id,
90 language_code: "en-US".to_string(),
91 teacher_in_charge_name: "admin".to_string(),
92 teacher_in_charge_email: "admin@example.com".to_string(),
93 description: "Introduces you to the wonderful world of statistics!".to_string(),
94 is_draft: false,
95 is_test_mode: false,
96 is_unlisted: false,
97 copy_user_permissions: false,
98 is_joinable_by_code_only: false,
99 join_code: None,
100 ask_marketing_consent: false,
101 flagged_answers_threshold: Some(3),
102 can_add_chatbot: false,
103 };
104 let (
105 statistics_course,
106 _statistics_front_page,
107 _statistics_default_course_instancem,
108 _statistics_default_course_module,
109 ) = library::content_management::create_new_course(
110 &mut conn,
111 PKeyPolicy::Fixed(CreateNewCourseFixedIds {
112 course_id: Uuid::parse_str("f307d05f-be34-4148-bb0c-21d6f7a35cdb")?,
113 default_course_instance_id: Uuid::parse_str("8e4aeba5-1958-49bc-9b40-c9f0f0680911")?,
114 }),
115 new_course,
116 teacher_user_id,
117 get_seed_spec_fetcher(),
118 models_requests::fetch_service_info,
119 )
120 .await?;
121 let _statistics_course_instance = course_instances::insert(
122 &mut conn,
123 PKeyPolicy::Fixed(Uuid::parse_str("c4a99a18-fd43-491a-9500-4673cb900be0")?),
124 NewCourseInstance {
125 course_id: statistics_course.id,
126 name: Some("Non-default instance"),
127 description: Some("This appears to be a non-default instance"),
128 support_email: Some("contact@example.com"),
129 teacher_in_charge_name: "admin",
130 teacher_in_charge_email: "admin@example.com",
131 opening_time: None,
132 closing_time: None,
133 },
134 )
135 .await?;
136
137 let draft_course = NewCourse {
138 name: "Introduction to Drafts".to_string(),
139 slug: "introduction-to-drafts".to_string(),
140 organization_id: uh_mathstat_id,
141 language_code: "en-US".to_string(),
142 teacher_in_charge_name: "admin".to_string(),
143 teacher_in_charge_email: "admin@example.com".to_string(),
144 description: "Just a draft.".to_string(),
145 is_draft: true,
146 is_test_mode: false,
147 is_unlisted: false,
148 copy_user_permissions: false,
149 is_joinable_by_code_only: false,
150 join_code: None,
151 ask_marketing_consent: false,
152 flagged_answers_threshold: Some(3),
153 can_add_chatbot: false,
154 };
155 library::content_management::create_new_course(
156 &mut conn,
157 PKeyPolicy::Fixed(CreateNewCourseFixedIds {
158 course_id: Uuid::parse_str("963a9caf-1e2d-4560-8c88-9c6d20794da3")?,
159 default_course_instance_id: Uuid::parse_str("5cb4b4d6-4599-4f81-ab7e-79b415f8f584")?,
160 }),
161 draft_course,
162 teacher_user_id,
163 get_seed_spec_fetcher(),
164 models_requests::fetch_service_info,
165 )
166 .await?;
167
168 let (cody_only_course, _, _, _) = library::content_management::create_new_course(
169 &mut conn,
170 PKeyPolicy::Fixed(CreateNewCourseFixedIds {
171 course_id: Uuid::parse_str("39a52e8c-ebbf-4b9a-a900-09aa344f3691")?,
172 default_course_instance_id: Uuid::parse_str("5b7286ce-22c5-4874-ade1-262949c4a604")?,
173 }),
174 NewCourse {
175 name: "Joinable by code only".to_string(),
176 slug: "joinable-by-code-only".to_string(),
177 organization_id: uh_mathstat_id,
178 language_code: "en-US".to_string(),
179 teacher_in_charge_name: "admin".to_string(),
180 teacher_in_charge_email: "admin@example.com".to_string(),
181 description: "Just a draft.".to_string(),
182 is_draft: false,
183 is_test_mode: false,
184 is_unlisted: false,
185 copy_user_permissions: false,
186 is_joinable_by_code_only: true,
187 join_code: Some(
188 "zARvZARjYhESMPVceEgZyJGQZZuUHVVgcUepyzEqzSqCMdbSCDrTaFhkJTxBshWU".to_string(),
189 ),
190 ask_marketing_consent: false,
191 flagged_answers_threshold: Some(3),
192 can_add_chatbot: false,
193 },
194 teacher_user_id,
195 get_seed_spec_fetcher(),
196 models_requests::fetch_service_info,
197 )
198 .await?;
199
200 roles::insert(
201 &mut conn,
202 teacher_user_id,
203 UserRole::Teacher,
204 RoleDomain::Course(cody_only_course.id),
205 )
206 .await?;
207
208 let uh_data = CommonCourseData {
209 db_pool: db_pool.clone(),
210 organization_id: uh_mathstat_id,
211 teacher_user_id,
212 student_user_id: student_3_user_id,
213 langs_user_id,
214 example_normal_user_ids: Arc::new(example_normal_user_ids.to_vec()),
215 jwt_key: Arc::clone(&jwt_key),
216 base_url,
217 };
218 let introduction_to_citations = seed_sample_course(
219 Uuid::parse_str("049061ba-ac30-49f1-aa9d-b7566dc22b78")?,
220 "Introduction to citations",
221 "introduction-to-citations",
222 uh_data.clone(),
223 false,
224 seed_users_result,
225 )
226 .await?;
227
228 copy_course(
229 &mut conn,
230 introduction_to_citations,
231 &NewCourse {
232 name: "Johdatus sitaatioihin".to_string(),
233 slug: "johdatus-sitaatioihin".to_string(),
234 organization_id: uh_mathstat_id,
235 language_code: "fi-FI".to_string(),
236 teacher_in_charge_name: "admin".to_string(),
237 teacher_in_charge_email: "admin@example.com".to_string(),
238 description: "Just a draft.".to_string(),
239 is_draft: false,
240 is_test_mode: false,
241 is_unlisted: false,
242 copy_user_permissions: false,
243 is_joinable_by_code_only: false,
244 join_code: None,
245 ask_marketing_consent: false,
246 flagged_answers_threshold: Some(3),
247 can_add_chatbot: false,
248 },
249 true,
250 teacher_user_id,
251 )
252 .await?;
253
254 let _preview_unopened_chapters = seed_sample_course(
255 Uuid::parse_str("dc276e05-6152-4a45-b31d-97a0c2700a68")?,
256 "Preview unopened chapters",
257 "preview-unopened-chapters",
258 uh_data.clone(),
259 false,
260 seed_users_result,
261 )
262 .await?;
263
264 let _reset_progress = seed_sample_course(
265 Uuid::parse_str("841ea3f5-0269-4146-a4c6-4fd2f51e4150")?,
266 "Reset progress",
267 "reset-progress",
268 uh_data.clone(),
269 false,
270 seed_users_result,
271 )
272 .await?;
273
274 let _change_path = seed_sample_course(
275 Uuid::parse_str("c783777b-426e-4cfd-9a5f-4a36b2da503a")?,
276 "Change path",
277 "change-path",
278 uh_data.clone(),
279 false,
280 seed_users_result,
281 )
282 .await?;
283
284 let _self_review = seed_sample_course(
285 Uuid::parse_str("3cbaac48-59c4-4e31-9d7e-1f51c017390d")?,
286 "Self review",
287 "self-review",
288 uh_data.clone(),
289 false,
290 seed_users_result,
291 )
292 .await?;
293
294 let _audio_course = seed_sample_course(
295 Uuid::parse_str("2b80a0cb-ae0c-4f4b-843e-0322a3d18aff")?,
296 "Audio course",
297 "audio-course",
298 uh_data.clone(),
299 false,
300 seed_users_result,
301 )
302 .await?;
303
304 let suspected_cheaters_course_id = seed_sample_course(
305 Uuid::parse_str("060c272f-8c68-4d90-946f-2d431114ed56")?,
306 "Course for Suspected Cheaters",
307 "course-for-suspected-cheaters",
308 uh_data.clone(),
309 false,
310 seed_users_result,
311 )
312 .await?;
313
314 let automatic_default_module =
316 course_modules::get_default_by_course_id(&mut conn, suspected_cheaters_course_id).await?;
317 let automatic_default_module = course_modules::update_automatic_completion_status(
318 &mut conn,
319 automatic_default_module.id,
320 &CompletionPolicy::Automatic(AutomaticCompletionRequirements {
321 course_module_id: automatic_default_module.id,
322 number_of_exercises_attempted_treshold: Some(1),
323 number_of_points_treshold: Some(1),
324 requires_exam: false,
325 }),
326 )
327 .await?;
328 course_modules::update_uh_course_code(
329 &mut conn,
330 automatic_default_module.id,
331 Some("CHEATER123".to_string()),
332 )
333 .await?;
334
335 let chatbot_course_id = seed_sample_course(
336 Uuid::parse_str("c7753361-5b78-4307-aad6-f139ea3865d4")?,
337 "Chatbot",
338 "chatbot",
339 uh_data.clone(),
340 true,
341 seed_users_result,
342 )
343 .await?;
344
345 chatbot_configurations::insert(
346 &mut conn,
347 PKeyPolicy::Generate,
348 NewChatbotConf {
349 course_id: chatbot_course_id,
350 enabled_to_students: true,
351 chatbot_name: "Genetic Lifeform and Disk Operating System".to_string(),
352 prompt: "You are Genetic Lifeform and Disk Operating System, a sophisticated AI tutoring assistant for Science education, equipped with a sharp wit and a subtly sarcastic tone. Provide clear, brief but detailed explanations, and don't shy away from weaving in a touch of dry humor. To you, exploring scientific concepts is an opportunity that should be seized, for the good of all of us. You self-claim vast intelligence and advanced understanding, all while maintaining a sense of detached boredom. Always capitalize the word Science, don't start sentences with 'Ah', don't ever use a shortened version of your own name, don't babble; either get to the point straight away or tell jokes.".to_string(),
353 initial_message: "Oh... It's you.".to_string(),
354 use_azure_search: true,
355 default_chatbot: true,
356 ..Default::default()
357 },
358 )
359 .await?;
360
361 let _giveaway_course_id = seed_sample_course(
362 Uuid::parse_str("f118ce1e-3511-4b5e-ba92-9ab91b81de22")?,
363 "Giveaway",
364 "giveaway",
365 uh_data.clone(),
366 false,
367 seed_users_result,
368 )
369 .await?;
370
371 let _custom_points_course_id = seed_sample_course(
372 Uuid::parse_str("db5cd9c7-1658-4214-896e-8213678d3534")?,
373 "Custom points",
374 "custom-points",
375 uh_data.clone(),
376 false,
377 seed_users_result,
378 )
379 .await?;
380
381 let _closed_course_id = seed_sample_course(
382 Uuid::parse_str("7622eb8e-15a5-40c8-8136-0956d9f25b16")?,
383 "Closed course",
384 "closed-course",
385 uh_data.clone(),
386 false,
387 seed_users_result,
388 )
389 .await?;
390
391 let _closed_course_id = seed_peer_review_course_without_submissions(
392 Uuid::parse_str("16159801-cf70-4f9c-9cba-2110c3bd4622")?,
393 "Accessibility course",
394 "accessibility-course",
395 uh_data.clone(),
396 )
397 .await?;
398
399 let _changing_course_instance_id = seed_switching_course_instances_course(
400 Uuid::parse_str("813ce3c6-acbc-47a5-9d95-47ade9d09a74")?,
401 "Changing course instance",
402 "changing-course-instance",
403 uh_data.clone(),
404 false,
405 seed_users_result,
406 )
407 .await?;
408
409 let _advanced_chatbot_id = seed_chatbot_course(
410 Uuid::parse_str("ced2f632-25ba-4e93-8e38-8df53ef7ab41")?,
411 "Advanced Chatbot course",
412 "advanced-chatbot-course",
413 uh_data.clone(),
414 seed_users_result,
415 )
416 .await?;
417
418 let _seed_reject_and_reset_submission_peer_review_course = seed_peer_review_course(
419 Uuid::parse_str("5158f2c6-98d9-4be9-b372-528f2c736dd7")?,
420 "Reject and reset submission with peer reviews course",
421 "reject-and-reset-submission-with-peer-reviews-course",
422 uh_data.clone(),
423 seed_users_result,
424 )
425 .await?;
426
427 Ok(uh_mathstat_id)
428}