headless_lms_server/programs/seed/seed_organizations/
uh_mathstat.rs

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    // Passed to this function to ensure the seed file storage has been ran before this. This function will not work is seed file storage has not been ran
39    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    // configure automatic completions
315    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}