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