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