Full Code of Coursemology/coursemology2 for AI

master d82b31f13cd6 cached
4409 files
10.8 MB
3.1M tokens
10175 symbols
1 requests
Copy disabled (too large) Download .txt
Showing preview only (12,518K chars total). Download the full file to get everything.
Repository: Coursemology/coursemology2
Branch: master
Commit: d82b31f13cd6
Files: 4409
Total size: 10.8 MB

Directory structure:
gitextract_31rkx6m_/

├── .circleci/
│   └── config.yml
├── .codecov.yml
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── 1-bug-report.yml
│   │   ├── 2-feature-request.yml
│   │   └── config.yml
│   └── dependabot.yml
├── .gitignore
├── .gitmodules
├── .hound.yml
├── .rspec
├── .rubocop.unhound.yml
├── .rubocop.yml
├── .yardopts
├── CONTRIBUTING.md
├── Gemfile
├── LICENSE
├── README.md
├── Rakefile
├── app/
│   ├── README.md
│   ├── assets/
│   │   └── config/
│   │       └── manifest.js
│   ├── channels/
│   │   ├── application_cable/
│   │   │   ├── channel.rb
│   │   │   └── connection.rb
│   │   ├── concerns/
│   │   │   ├── application_cable_ability_concern.rb
│   │   │   ├── application_cable_authentication_concern.rb
│   │   │   ├── application_cable_component_concern.rb
│   │   │   ├── application_cable_course_concern.rb
│   │   │   └── application_cable_multitenancy_concern.rb
│   │   └── course/
│   │       ├── channel.rb
│   │       └── monitoring/
│   │           ├── heartbeat_channel.rb
│   │           └── live_monitoring_channel.rb
│   ├── controllers/
│   │   ├── announcements_controller.rb
│   │   ├── application_controller.rb
│   │   ├── attachment_references_controller.rb
│   │   ├── components/
│   │   │   └── course/
│   │   │       ├── achievements_component.rb
│   │   │       ├── announcements_component.rb
│   │   │       ├── assessments_component.rb
│   │   │       ├── codaveri_component.rb
│   │   │       ├── controller_component_host.rb
│   │   │       ├── discussion/
│   │   │       │   └── topics_component.rb
│   │   │       ├── duplication_component.rb
│   │   │       ├── experience_points_component.rb
│   │   │       ├── forums_component.rb
│   │   │       ├── groups_component.rb
│   │   │       ├── koditsu_platform_component.rb
│   │   │       ├── leaderboard_component.rb
│   │   │       ├── learning_map_component.rb
│   │   │       ├── lesson_plan_component.rb
│   │   │       ├── levels_component.rb
│   │   │       ├── materials_component.rb
│   │   │       ├── monitoring_component.rb
│   │   │       ├── multiple_reference_timelines_component.rb
│   │   │       ├── plagiarism_component.rb
│   │   │       ├── rag_wise_component.rb
│   │   │       ├── scholaistic_component.rb
│   │   │       ├── settings_component.rb
│   │   │       ├── statistics_component.rb
│   │   │       ├── stories_component.rb
│   │   │       ├── survey_component.rb
│   │   │       ├── users_component.rb
│   │   │       └── videos_component.rb
│   │   ├── concerns/
│   │   │   ├── application_ability_concern.rb
│   │   │   ├── application_announcements_concern.rb
│   │   │   ├── application_authentication_concern.rb
│   │   │   ├── application_components_concern.rb
│   │   │   ├── application_controller_multitenancy_concern.rb
│   │   │   ├── application_instance_user_concern.rb
│   │   │   ├── application_internationalization_concern.rb
│   │   │   ├── application_multitenancy.rb
│   │   │   ├── application_pagination_concern.rb
│   │   │   ├── application_user_concern.rb
│   │   │   ├── application_user_time_zone_concern.rb
│   │   │   ├── codaveri_language_concern.rb
│   │   │   ├── course/
│   │   │   │   ├── achievement_conditional_concern.rb
│   │   │   │   ├── activity_feeds_concern.rb
│   │   │   │   ├── assessment/
│   │   │   │   │   ├── answer/
│   │   │   │   │   │   └── update_answer_concern.rb
│   │   │   │   │   ├── koditsu_assessment_concern.rb
│   │   │   │   │   ├── koditsu_assessment_invitation_concern.rb
│   │   │   │   │   ├── live_feedback/
│   │   │   │   │   │   ├── file_concern.rb
│   │   │   │   │   │   ├── message_concern.rb
│   │   │   │   │   │   ├── message_file_concern.rb
│   │   │   │   │   │   └── thread_concern.rb
│   │   │   │   │   ├── monitoring/
│   │   │   │   │   │   └── seb_payload_concern.rb
│   │   │   │   │   ├── monitoring_concern.rb
│   │   │   │   │   ├── question/
│   │   │   │   │   │   ├── codaveri_question_concern.rb
│   │   │   │   │   │   ├── koditsu_question_concern.rb
│   │   │   │   │   │   ├── multiple_responses_concern.rb
│   │   │   │   │   │   ├── rubric_based_response_controller_concern.rb
│   │   │   │   │   │   └── rubric_based_response_question_concern.rb
│   │   │   │   │   ├── question_bundle_assignment_concern.rb
│   │   │   │   │   ├── submission/
│   │   │   │   │   │   ├── koditsu/
│   │   │   │   │   │   │   ├── answers_concern.rb
│   │   │   │   │   │   │   ├── submission_times_concern.rb
│   │   │   │   │   │   │   ├── submissions_concern.rb
│   │   │   │   │   │   │   ├── test_cases_concern.rb
│   │   │   │   │   │   │   └── users_concern.rb
│   │   │   │   │   │   ├── monitoring_concern.rb
│   │   │   │   │   │   └── submissions_controller_service_concern.rb
│   │   │   │   │   └── submission_concern.rb
│   │   │   │   ├── assessment_conditional_concern.rb
│   │   │   │   ├── cikgo_chats_concern.rb
│   │   │   │   ├── cikgo_push_concern.rb
│   │   │   │   ├── discussion/
│   │   │   │   │   └── posts_concern.rb
│   │   │   │   ├── forum/
│   │   │   │   │   ├── auto_answering_concern.rb
│   │   │   │   │   ├── topic_controller_hiding_concern.rb
│   │   │   │   │   ├── topic_controller_locking_concern.rb
│   │   │   │   │   └── topic_controller_subscription_concern.rb
│   │   │   │   ├── group/
│   │   │   │   │   └── group_manager_concern.rb
│   │   │   │   ├── koditsu_workspace_concern.rb
│   │   │   │   ├── lesson_plan/
│   │   │   │   │   ├── acts_as_lesson_plan_item_concern.rb
│   │   │   │   │   ├── learning_rate_concern.rb
│   │   │   │   │   ├── personalization_concern.rb
│   │   │   │   │   ├── stories_concern.rb
│   │   │   │   │   └── strategies/
│   │   │   │   │       ├── base_personalization_strategy.rb
│   │   │   │   │       ├── fixed_personalization_strategy.rb
│   │   │   │   │       ├── fomo_personalization_strategy.rb
│   │   │   │   │       ├── otot_personalization_strategy.rb
│   │   │   │   │       └── stragglers_personalization_strategy.rb
│   │   │   │   ├── reminder_service_concern.rb
│   │   │   │   ├── scholaistic/
│   │   │   │   │   └── concern.rb
│   │   │   │   ├── ssid_folder_concern.rb
│   │   │   │   ├── statistics/
│   │   │   │   │   ├── counts_concern.rb
│   │   │   │   │   ├── grades_concern.rb
│   │   │   │   │   ├── reference_times_concern.rb
│   │   │   │   │   ├── submissions_concern.rb
│   │   │   │   │   ├── times_concern.rb
│   │   │   │   │   └── users_concern.rb
│   │   │   │   ├── survey/
│   │   │   │   │   └── reordering_concern.rb
│   │   │   │   ├── unread_counts_concern.rb
│   │   │   │   └── users_controller_management_concern.rb
│   │   │   └── signals/
│   │   │       ├── emission_concern.rb
│   │   │       └── slices/
│   │   │           ├── announcements.rb
│   │   │           ├── assessment_submissions.rb
│   │   │           ├── cikgo_mission_control.rb
│   │   │           ├── cikgo_open_threads_count.rb
│   │   │           ├── comments.rb
│   │   │           ├── enrol_requests.rb
│   │   │           ├── forums.rb
│   │   │           └── videos.rb
│   │   ├── course/
│   │   │   ├── achievement/
│   │   │   │   ├── achievements_controller.rb
│   │   │   │   ├── condition/
│   │   │   │   │   ├── achievements_controller.rb
│   │   │   │   │   ├── assessments_controller.rb
│   │   │   │   │   ├── levels_controller.rb
│   │   │   │   │   ├── scholaistic_assessments_controller.rb
│   │   │   │   │   └── surveys_controller.rb
│   │   │   │   └── controller.rb
│   │   │   ├── admin/
│   │   │   │   ├── admin_controller.rb
│   │   │   │   ├── announcement_settings_controller.rb
│   │   │   │   ├── assessment_settings_controller.rb
│   │   │   │   ├── assessments/
│   │   │   │   │   ├── categories_controller.rb
│   │   │   │   │   └── tabs_controller.rb
│   │   │   │   ├── codaveri_settings_controller.rb
│   │   │   │   ├── component_settings_controller.rb
│   │   │   │   ├── controller.rb
│   │   │   │   ├── discussion/
│   │   │   │   │   └── topic_settings_controller.rb
│   │   │   │   ├── forum_settings_controller.rb
│   │   │   │   ├── leaderboard_settings_controller.rb
│   │   │   │   ├── lesson_plan_settings_controller.rb
│   │   │   │   ├── material_settings_controller.rb
│   │   │   │   ├── notification_settings_controller.rb
│   │   │   │   ├── rag_wise_settings_controller.rb
│   │   │   │   ├── scholaistic_settings_controller.rb
│   │   │   │   ├── sidebar_settings_controller.rb
│   │   │   │   ├── stories_settings_controller.rb
│   │   │   │   ├── video_settings_controller.rb
│   │   │   │   └── videos/
│   │   │   │       └── tabs_controller.rb
│   │   │   ├── announcements_controller.rb
│   │   │   ├── assessment/
│   │   │   │   ├── assessments_controller.rb
│   │   │   │   ├── categories_controller.rb
│   │   │   │   ├── component_controller.rb
│   │   │   │   ├── condition/
│   │   │   │   │   ├── achievements_controller.rb
│   │   │   │   │   ├── assessments_controller.rb
│   │   │   │   │   ├── levels_controller.rb
│   │   │   │   │   ├── scholaistic_assessments_controller.rb
│   │   │   │   │   └── surveys_controller.rb
│   │   │   │   ├── controller.rb
│   │   │   │   ├── mock_answers_controller.rb
│   │   │   │   ├── question/
│   │   │   │   │   ├── controller.rb
│   │   │   │   │   ├── forum_post_responses_controller.rb
│   │   │   │   │   ├── multiple_responses_controller.rb
│   │   │   │   │   ├── programming_controller.rb
│   │   │   │   │   ├── rubric_based_responses_controller.rb
│   │   │   │   │   ├── scribing_controller.rb
│   │   │   │   │   ├── text_responses_controller.rb
│   │   │   │   │   └── voice_responses_controller.rb
│   │   │   │   ├── question_bundle_assignments_controller.rb
│   │   │   │   ├── question_bundle_questions_controller.rb
│   │   │   │   ├── question_bundles_controller.rb
│   │   │   │   ├── question_groups_controller.rb
│   │   │   │   ├── questions_controller.rb
│   │   │   │   ├── rubrics_controller.rb
│   │   │   │   ├── sessions_controller.rb
│   │   │   │   ├── skill_branches_controller.rb
│   │   │   │   ├── skills_controller.rb
│   │   │   │   ├── submission/
│   │   │   │   │   ├── answer/
│   │   │   │   │   │   ├── answers_controller.rb
│   │   │   │   │   │   ├── controller.rb
│   │   │   │   │   │   ├── forum_post_response/
│   │   │   │   │   │   │   └── posts_controller.rb
│   │   │   │   │   │   ├── programming/
│   │   │   │   │   │   │   ├── annotations_controller.rb
│   │   │   │   │   │   │   ├── controller.rb
│   │   │   │   │   │   │   └── programming_controller.rb
│   │   │   │   │   │   ├── scribing/
│   │   │   │   │   │   │   ├── controller.rb
│   │   │   │   │   │   │   └── scribbles_controller.rb
│   │   │   │   │   │   └── text_response/
│   │   │   │   │   │       ├── controller.rb
│   │   │   │   │   │       └── text_response_controller.rb
│   │   │   │   │   ├── controller.rb
│   │   │   │   │   ├── live_feedback_controller.rb
│   │   │   │   │   ├── logs_controller.rb
│   │   │   │   │   └── submissions_controller.rb
│   │   │   │   ├── submission_question/
│   │   │   │   │   ├── comments_controller.rb
│   │   │   │   │   ├── controller.rb
│   │   │   │   │   └── submission_questions_controller.rb
│   │   │   │   └── submissions_controller.rb
│   │   │   ├── component_controller.rb
│   │   │   ├── condition/
│   │   │   │   ├── achievements_controller.rb
│   │   │   │   ├── assessments_controller.rb
│   │   │   │   ├── levels_controller.rb
│   │   │   │   ├── scholaistic_assessments_controller.rb
│   │   │   │   └── surveys_controller.rb
│   │   │   ├── conditions_controller.rb
│   │   │   ├── controller.rb
│   │   │   ├── courses_controller.rb
│   │   │   ├── discussion/
│   │   │   │   ├── posts_controller.rb
│   │   │   │   └── topics_controller.rb
│   │   │   ├── duplications_controller.rb
│   │   │   ├── enrol_requests_controller.rb
│   │   │   ├── experience_points/
│   │   │   │   ├── disbursement_controller.rb
│   │   │   │   └── forum_disbursement_controller.rb
│   │   │   ├── experience_points_records_controller.rb
│   │   │   ├── forum/
│   │   │   │   ├── component_controller.rb
│   │   │   │   ├── controller.rb
│   │   │   │   ├── forums_controller.rb
│   │   │   │   ├── posts_controller.rb
│   │   │   │   └── topics_controller.rb
│   │   │   ├── group/
│   │   │   │   ├── group_categories_controller.rb
│   │   │   │   └── groups_controller.rb
│   │   │   ├── leaderboards_controller.rb
│   │   │   ├── learning_map_controller.rb
│   │   │   ├── lesson_plan/
│   │   │   │   ├── controller.rb
│   │   │   │   ├── events_controller.rb
│   │   │   │   ├── items_controller.rb
│   │   │   │   ├── milestones_controller.rb
│   │   │   │   └── todos_controller.rb
│   │   │   ├── levels_controller.rb
│   │   │   ├── material/
│   │   │   │   ├── controller.rb
│   │   │   │   ├── folders_controller.rb
│   │   │   │   └── materials_controller.rb
│   │   │   ├── object_duplications_controller.rb
│   │   │   ├── personal_times_controller.rb
│   │   │   ├── plagiarism/
│   │   │   │   ├── assessments_controller.rb
│   │   │   │   ├── controller.rb
│   │   │   │   └── plagiarism_controller.rb
│   │   │   ├── reference_timelines_controller.rb
│   │   │   ├── reference_times_controller.rb
│   │   │   ├── rubrics_controller.rb
│   │   │   ├── scholaistic/
│   │   │   │   ├── assistants_controller.rb
│   │   │   │   ├── controller.rb
│   │   │   │   ├── scholaistic_assessments_controller.rb
│   │   │   │   └── submissions_controller.rb
│   │   │   ├── statistics/
│   │   │   │   ├── aggregate_controller.rb
│   │   │   │   ├── assessments_controller.rb
│   │   │   │   ├── controller.rb
│   │   │   │   ├── statistics_controller.rb
│   │   │   │   └── users_controller.rb
│   │   │   ├── stories/
│   │   │   │   └── stories_controller.rb
│   │   │   ├── survey/
│   │   │   │   ├── controller.rb
│   │   │   │   ├── questions_controller.rb
│   │   │   │   ├── responses_controller.rb
│   │   │   │   ├── sections_controller.rb
│   │   │   │   └── surveys_controller.rb
│   │   │   ├── user_email_subscriptions_controller.rb
│   │   │   ├── user_invitations_controller.rb
│   │   │   ├── user_notifications_controller.rb
│   │   │   ├── user_registrations_controller.rb
│   │   │   ├── users_controller.rb
│   │   │   ├── video/
│   │   │   │   ├── controller.rb
│   │   │   │   ├── submission/
│   │   │   │   │   ├── controller.rb
│   │   │   │   │   ├── sessions_controller.rb
│   │   │   │   │   └── submissions_controller.rb
│   │   │   │   ├── topics_controller.rb
│   │   │   │   └── videos_controller.rb
│   │   │   └── video_submissions_controller.rb
│   │   ├── csrf_token_controller.rb
│   │   ├── health_check_controller.rb
│   │   ├── instance_user_role_requests_controller.rb
│   │   ├── jobs_controller.rb
│   │   ├── system/
│   │   │   └── admin/
│   │   │       ├── admin_controller.rb
│   │   │       ├── announcements_controller.rb
│   │   │       ├── controller.rb
│   │   │       ├── courses_controller.rb
│   │   │       ├── get_help_controller.rb
│   │   │       ├── instance/
│   │   │       │   ├── admin_controller.rb
│   │   │       │   ├── announcements_controller.rb
│   │   │       │   ├── components_controller.rb
│   │   │       │   ├── controller.rb
│   │   │       │   ├── courses_controller.rb
│   │   │       │   ├── get_help_controller.rb
│   │   │       │   ├── user_invitations_controller.rb
│   │   │       │   └── users_controller.rb
│   │   │       ├── instances_controller.rb
│   │   │       └── users_controller.rb
│   │   ├── test/
│   │   │   ├── controller.rb
│   │   │   ├── factories_controller.rb
│   │   │   └── mailer_controller.rb
│   │   ├── user/
│   │   │   ├── confirmations_controller.rb
│   │   │   ├── emails_controller.rb
│   │   │   ├── passwords_controller.rb
│   │   │   ├── profiles_controller.rb
│   │   │   ├── registrations_controller.rb
│   │   │   └── sessions_controller.rb
│   │   └── users_controller.rb
│   ├── helpers/
│   │   ├── application_formatters_helper.rb
│   │   ├── application_helper.rb
│   │   ├── application_html_formatters_helper.rb
│   │   ├── application_jobs_helper.rb
│   │   ├── application_mailer_helper.rb
│   │   ├── application_notifications_helper.rb
│   │   ├── consolidated_opening_reminder_mailer_helper.rb
│   │   ├── course/
│   │   │   ├── achievement/
│   │   │   │   ├── achievements_helper.rb
│   │   │   │   └── controller_helper.rb
│   │   │   ├── assessment/
│   │   │   │   ├── answer/
│   │   │   │   │   └── programming_test_case_helper.rb
│   │   │   │   ├── assessments_helper.rb
│   │   │   │   ├── question/
│   │   │   │   │   └── programming_helper.rb
│   │   │   │   ├── submission/
│   │   │   │   │   └── submissions_helper.rb
│   │   │   │   └── submissions_helper.rb
│   │   │   ├── condition/
│   │   │   │   └── conditions_helper.rb
│   │   │   ├── controller_helper.rb
│   │   │   ├── discussion/
│   │   │   │   └── topics_helper.rb
│   │   │   ├── forum/
│   │   │   │   └── controller_helper.rb
│   │   │   ├── group/
│   │   │   │   └── group_categories_helper.rb
│   │   │   ├── leaderboards_helper.rb
│   │   │   ├── material/
│   │   │   │   └── folders_helper.rb
│   │   │   ├── object_duplications_helper.rb
│   │   │   └── users_helper.rb
│   │   ├── route_overrides_helper.rb
│   │   └── tmp_cleanup_helper.rb
│   ├── jobs/
│   │   ├── application_job.rb
│   │   ├── consolidated_item_email_job.rb
│   │   ├── course/
│   │   │   ├── announcement/
│   │   │   │   └── opening_reminder_job.rb
│   │   │   ├── assessment/
│   │   │   │   ├── answer/
│   │   │   │   │   ├── auto_grading_job.rb
│   │   │   │   │   ├── base_auto_grading_job.rb
│   │   │   │   │   ├── programming_codaveri_feedback_job.rb
│   │   │   │   │   └── reduce_priority_auto_grading_job.rb
│   │   │   │   ├── closing_reminder_job.rb
│   │   │   │   ├── invite_to_koditsu_job.rb
│   │   │   │   ├── plagiarism_check_job.rb
│   │   │   │   ├── question/
│   │   │   │   │   ├── answers_evaluation_job.rb
│   │   │   │   │   ├── codaveri_import_job.rb
│   │   │   │   │   └── programming_import_job.rb
│   │   │   │   └── submission/
│   │   │   │       ├── auto_feedback_job.rb
│   │   │   │       ├── auto_grading_job.rb
│   │   │   │       ├── csv_download_job.rb
│   │   │   │       ├── deleting_job.rb
│   │   │   │       ├── fetch_submissions_from_koditsu_job.rb
│   │   │   │       ├── force_submit_timed_submission_job.rb
│   │   │   │       ├── force_submitting_job.rb
│   │   │   │       ├── publishing_job.rb
│   │   │   │       ├── statistics_download_job.rb
│   │   │   │       ├── unsubmitting_job.rb
│   │   │   │       └── zip_download_job.rb
│   │   │   ├── conditional/
│   │   │   │   ├── conditional_satisfiability_evaluation_job.rb
│   │   │   │   └── coursewide_conditional_satisfiability_evaluation_job.rb
│   │   │   ├── discussion/
│   │   │   │   └── post/
│   │   │   │       └── codaveri_feedback_rating_job.rb
│   │   │   ├── duplication_job.rb
│   │   │   ├── experience_points_download_job.rb
│   │   │   ├── forum/
│   │   │   │   ├── auto_answering_job.rb
│   │   │   │   └── importing_job.rb
│   │   │   ├── lesson_plan/
│   │   │   │   └── coursewide_personalized_timeline_update_job.rb
│   │   │   ├── material/
│   │   │   │   ├── text_chunk_job.rb
│   │   │   │   └── zip_download_job.rb
│   │   │   ├── object_duplication_job.rb
│   │   │   ├── rubric/
│   │   │   │   └── rubric_evaluation_export_job.rb
│   │   │   ├── statistics/
│   │   │   │   └── assessments_score_summary_download_job.rb
│   │   │   ├── survey/
│   │   │   │   ├── closing_reminder_job.rb
│   │   │   │   └── survey_download_job.rb
│   │   │   ├── user_deletion_job.rb
│   │   │   └── video/
│   │   │       └── closing_reminder_job.rb
│   │   ├── read_marks_clean_up_job.rb
│   │   ├── user_email_database_cleanup_job.rb
│   │   └── video_statistic_update_job.rb
│   ├── mailers/
│   │   ├── activity_mailer.rb
│   │   ├── application_mailer.rb
│   │   ├── consolidated_opening_reminder_mailer.rb
│   │   ├── course/
│   │   │   └── mailer.rb
│   │   ├── instance/
│   │   │   └── mailer.rb
│   │   └── instance_user_role_request_mailer.rb
│   ├── models/
│   │   ├── .rubocop.yml
│   │   ├── ability.rb
│   │   ├── activity.rb
│   │   ├── application_record.rb
│   │   ├── attachment.rb
│   │   ├── attachment_reference.rb
│   │   ├── cikgo_user.rb
│   │   ├── components/
│   │   │   ├── ability_host.rb
│   │   │   ├── course/
│   │   │   │   ├── achievements_ability_component.rb
│   │   │   │   ├── announcements_ability_component.rb
│   │   │   │   ├── assessments_ability_component.rb
│   │   │   │   ├── conditions_ability_component.rb
│   │   │   │   ├── course_ability_component.rb
│   │   │   │   ├── course_user_ability_component.rb
│   │   │   │   ├── discussions_ability_component.rb
│   │   │   │   ├── duplication_ability_component.rb
│   │   │   │   ├── experience_points_disbursement_ability_component.rb
│   │   │   │   ├── experience_points_records_ability_component.rb
│   │   │   │   ├── forums_ability_component.rb
│   │   │   │   ├── groups_ability_component.rb
│   │   │   │   ├── learning_map_ability_component.rb
│   │   │   │   ├── lesson_plan_ability_component.rb
│   │   │   │   ├── levels_ability_component.rb
│   │   │   │   ├── materials_ability_component.rb
│   │   │   │   ├── model_component_host.rb
│   │   │   │   ├── monitoring_ability_component.rb
│   │   │   │   ├── plagiarism_ability_component.rb
│   │   │   │   ├── rag_wise_setting_ability_component.rb
│   │   │   │   ├── scholaistic_ability_component.rb
│   │   │   │   ├── statistics_ability_component.rb
│   │   │   │   ├── stories_ability_component.rb
│   │   │   │   ├── surveys_ability_component.rb
│   │   │   │   ├── timelines_ability_component.rb
│   │   │   │   ├── user_email_unsubscriptions_ability_component.rb
│   │   │   │   └── videos_ability_component.rb
│   │   │   ├── system/
│   │   │   │   └── admin/
│   │   │   │       ├── instance_admin_ability_component.rb
│   │   │   │       ├── instance_announcements_ability_component.rb
│   │   │   │       ├── system_admin_ability_component.rb
│   │   │   │       └── system_announcements_ability_component.rb
│   │   │   ├── user_notifications_ability_component.rb
│   │   │   └── users_ability_component.rb
│   │   ├── concerns/
│   │   │   ├── announcement_concern.rb
│   │   │   ├── application_acts_as_concern.rb
│   │   │   ├── application_userstamp_concern.rb
│   │   │   ├── cikgo/
│   │   │   │   └── pushable_item_concern.rb
│   │   │   ├── component_settings_concern.rb
│   │   │   ├── course/
│   │   │   │   ├── assessment/
│   │   │   │   │   ├── new_submission_concern.rb
│   │   │   │   │   ├── questions_concern.rb
│   │   │   │   │   ├── submission/
│   │   │   │   │   │   ├── answers_concern.rb
│   │   │   │   │   │   ├── cikgo_task_completion_concern.rb
│   │   │   │   │   │   ├── notification_concern.rb
│   │   │   │   │   │   ├── todo_concern.rb
│   │   │   │   │   │   └── workflow_event_concern.rb
│   │   │   │   │   └── todo_concern.rb
│   │   │   │   ├── closing_reminder_concern.rb
│   │   │   │   ├── course_components_concern.rb
│   │   │   │   ├── course_user_type_concern.rb
│   │   │   │   ├── discussion/
│   │   │   │   │   ├── post/
│   │   │   │   │   │   ├── ordering_concern.rb
│   │   │   │   │   │   └── retrieval_concern.rb
│   │   │   │   │   └── topic/
│   │   │   │   │       └── posts_concern.rb
│   │   │   │   ├── duplication_concern.rb
│   │   │   │   ├── forum_participation_concern.rb
│   │   │   │   ├── lesson_plan/
│   │   │   │   │   ├── item/
│   │   │   │   │   │   └── cikgo_push_concern.rb
│   │   │   │   │   └── item_todo_concern.rb
│   │   │   │   ├── levels_concern.rb
│   │   │   │   ├── material/
│   │   │   │   │   └── folder/
│   │   │   │   │       └── ordering_concern.rb
│   │   │   │   ├── material_concern.rb
│   │   │   │   ├── opening_reminder_concern.rb
│   │   │   │   ├── sanitize_description_concern.rb
│   │   │   │   ├── search_concern.rb
│   │   │   │   ├── settings/
│   │   │   │   │   └── lesson_plan_settings_concern.rb
│   │   │   │   ├── survey/
│   │   │   │   │   └── response/
│   │   │   │   │       ├── cikgo_task_completion_concern.rb
│   │   │   │   │       └── todo_concern.rb
│   │   │   │   └── video/
│   │   │   │       ├── interval_query_concern.rb
│   │   │   │       ├── submission/
│   │   │   │       │   ├── notification_concern.rb
│   │   │   │       │   ├── statistic/
│   │   │   │       │   │   └── cikgo_task_completion_concern.rb
│   │   │   │       │   └── todo_concern.rb
│   │   │   │       ├── url_concern.rb
│   │   │   │       └── watch_statistics_concern.rb
│   │   │   ├── course_component_query_concern.rb
│   │   │   ├── course_user/
│   │   │   │   ├── achievements_concern.rb
│   │   │   │   ├── level_progress_concern.rb
│   │   │   │   ├── staff_concern.rb
│   │   │   │   └── todo_concern.rb
│   │   │   ├── duplication_state_tracking_concern.rb
│   │   │   ├── generic/
│   │   │   │   └── collection_concern.rb
│   │   │   ├── instance/
│   │   │   │   └── course_components_concern.rb
│   │   │   ├── instance_user_search_concern.rb
│   │   │   ├── safe_mark_as_read_concern.rb
│   │   │   ├── time_zone_concern.rb
│   │   │   ├── user_authentication_concern.rb
│   │   │   ├── user_notifications_concern.rb
│   │   │   └── user_search_concern.rb
│   │   ├── course/
│   │   │   ├── achievement.rb
│   │   │   ├── announcement.rb
│   │   │   ├── assessment/
│   │   │   │   ├── answer/
│   │   │   │   │   ├── auto_grading.rb
│   │   │   │   │   ├── forum_post.rb
│   │   │   │   │   ├── forum_post_response.rb
│   │   │   │   │   ├── multiple_response.rb
│   │   │   │   │   ├── multiple_response_option.rb
│   │   │   │   │   ├── programming.rb
│   │   │   │   │   ├── programming_ability.rb
│   │   │   │   │   ├── programming_auto_grading.rb
│   │   │   │   │   ├── programming_auto_grading_test_result.rb
│   │   │   │   │   ├── programming_file.rb
│   │   │   │   │   ├── programming_file_annotation.rb
│   │   │   │   │   ├── rubric_based_response.rb
│   │   │   │   │   ├── rubric_based_response_selection.rb
│   │   │   │   │   ├── rubric_playground_answer_adapter.rb
│   │   │   │   │   ├── scribing.rb
│   │   │   │   │   ├── scribing_scribble.rb
│   │   │   │   │   ├── text_response.rb
│   │   │   │   │   └── voice_response.rb
│   │   │   │   ├── answer.rb
│   │   │   │   ├── assessment_ability.rb
│   │   │   │   ├── category.rb
│   │   │   │   ├── link.rb
│   │   │   │   ├── live_feedback/
│   │   │   │   │   ├── file.rb
│   │   │   │   │   ├── message.rb
│   │   │   │   │   ├── message_file.rb
│   │   │   │   │   ├── message_option.rb
│   │   │   │   │   ├── option.rb
│   │   │   │   │   └── thread.rb
│   │   │   │   ├── live_feedback.rb
│   │   │   │   ├── live_feedback_code.rb
│   │   │   │   ├── live_feedback_comment.rb
│   │   │   │   ├── plagiarism_check.rb
│   │   │   │   ├── question/
│   │   │   │   │   ├── forum_post_response.rb
│   │   │   │   │   ├── mock_answer/
│   │   │   │   │   │   └── answer_adapter.rb
│   │   │   │   │   ├── mock_answer.rb
│   │   │   │   │   ├── multiple_response.rb
│   │   │   │   │   ├── multiple_response_option.rb
│   │   │   │   │   ├── programming.rb
│   │   │   │   │   ├── programming_template_file.rb
│   │   │   │   │   ├── programming_test_case.rb
│   │   │   │   │   ├── question_rubric.rb
│   │   │   │   │   ├── rubric_based_response.rb
│   │   │   │   │   ├── rubric_based_response_category.rb
│   │   │   │   │   ├── rubric_based_response_criterion.rb
│   │   │   │   │   ├── scribing.rb
│   │   │   │   │   ├── text_response.rb
│   │   │   │   │   ├── text_response_comprehension_group.rb
│   │   │   │   │   ├── text_response_comprehension_point.rb
│   │   │   │   │   ├── text_response_comprehension_solution.rb
│   │   │   │   │   ├── text_response_solution.rb
│   │   │   │   │   └── voice_response.rb
│   │   │   │   ├── question.rb
│   │   │   │   ├── question_bundle.rb
│   │   │   │   ├── question_bundle_assignment.rb
│   │   │   │   ├── question_bundle_question.rb
│   │   │   │   ├── question_group.rb
│   │   │   │   ├── skill.rb
│   │   │   │   ├── skill_ability.rb
│   │   │   │   ├── skill_branch.rb
│   │   │   │   ├── submission/
│   │   │   │   │   └── log.rb
│   │   │   │   ├── submission.rb
│   │   │   │   ├── submission_question.rb
│   │   │   │   └── tab.rb
│   │   │   ├── assessment.rb
│   │   │   ├── condition/
│   │   │   │   ├── achievement.rb
│   │   │   │   ├── assessment.rb
│   │   │   │   ├── level.rb
│   │   │   │   ├── scholaistic_assessment.rb
│   │   │   │   ├── survey.rb
│   │   │   │   └── video.rb
│   │   │   ├── condition.rb
│   │   │   ├── discussion/
│   │   │   │   ├── post/
│   │   │   │   │   ├── codaveri_feedback.rb
│   │   │   │   │   └── vote.rb
│   │   │   │   ├── post.rb
│   │   │   │   ├── topic/
│   │   │   │   │   └── subscription.rb
│   │   │   │   └── topic.rb
│   │   │   ├── discussion.rb
│   │   │   ├── enrol_request.rb
│   │   │   ├── experience_points/
│   │   │   │   ├── disbursement.rb
│   │   │   │   └── forum_disbursement.rb
│   │   │   ├── experience_points_record.rb
│   │   │   ├── forum/
│   │   │   │   ├── discussion.rb
│   │   │   │   ├── discussion_reference.rb
│   │   │   │   ├── import.rb
│   │   │   │   ├── rag_auto_answering.rb
│   │   │   │   ├── search.rb
│   │   │   │   ├── subscription.rb
│   │   │   │   ├── topic/
│   │   │   │   │   └── view.rb
│   │   │   │   └── topic.rb
│   │   │   ├── forum.rb
│   │   │   ├── group.rb
│   │   │   ├── group_category.rb
│   │   │   ├── group_user.rb
│   │   │   ├── learning_map.rb
│   │   │   ├── learning_rate_record.rb
│   │   │   ├── lesson_plan/
│   │   │   │   ├── event.rb
│   │   │   │   ├── event_material.rb
│   │   │   │   ├── item.rb
│   │   │   │   ├── milestone.rb
│   │   │   │   └── todo.rb
│   │   │   ├── lesson_plan.rb
│   │   │   ├── level.rb
│   │   │   ├── material/
│   │   │   │   ├── folder.rb
│   │   │   │   ├── text_chunk.rb
│   │   │   │   ├── text_chunk_reference.rb
│   │   │   │   └── text_chunking.rb
│   │   │   ├── material.rb
│   │   │   ├── monitoring/
│   │   │   │   ├── browser_authorization/
│   │   │   │   │   ├── base.rb
│   │   │   │   │   ├── seb_config_key.rb
│   │   │   │   │   └── user_agent.rb
│   │   │   │   ├── heartbeat.rb
│   │   │   │   ├── monitor.rb
│   │   │   │   └── session.rb
│   │   │   ├── monitoring.rb
│   │   │   ├── notification.rb
│   │   │   ├── personal_time.rb
│   │   │   ├── question_assessment.rb
│   │   │   ├── reference_time.rb
│   │   │   ├── reference_timeline.rb
│   │   │   ├── registration.rb
│   │   │   ├── rubric/
│   │   │   │   ├── answer_evaluation/
│   │   │   │   │   └── selection.rb
│   │   │   │   ├── answer_evaluation.rb
│   │   │   │   ├── category/
│   │   │   │   │   └── criterion.rb
│   │   │   │   ├── category.rb
│   │   │   │   ├── mock_answer_evaluation/
│   │   │   │   │   └── selection.rb
│   │   │   │   ├── mock_answer_evaluation.rb
│   │   │   │   └── rubric_adapter.rb
│   │   │   ├── rubric.rb
│   │   │   ├── scholaistic_assessment.rb
│   │   │   ├── scholaistic_submission.rb
│   │   │   ├── settings/
│   │   │   │   ├── announcements_component.rb
│   │   │   │   ├── assessments_component.rb
│   │   │   │   ├── codaveri_component.rb
│   │   │   │   ├── component.rb
│   │   │   │   ├── components.rb
│   │   │   │   ├── email.rb
│   │   │   │   ├── forums_component.rb
│   │   │   │   ├── leaderboard_component.rb
│   │   │   │   ├── learning_map_component.rb
│   │   │   │   ├── lesson_plan_component.rb
│   │   │   │   ├── lesson_plan_items.rb
│   │   │   │   ├── materials_component.rb
│   │   │   │   ├── pan_component.rb
│   │   │   │   ├── rag_wise_component.rb
│   │   │   │   ├── scholaistic_component.rb
│   │   │   │   ├── sidebar.rb
│   │   │   │   ├── sidebar_item.rb
│   │   │   │   ├── stories_component.rb
│   │   │   │   ├── survey_component.rb
│   │   │   │   ├── topics_component.rb
│   │   │   │   ├── users_component.rb
│   │   │   │   └── videos_component.rb
│   │   │   ├── settings.rb
│   │   │   ├── story.rb
│   │   │   ├── survey/
│   │   │   │   ├── answer.rb
│   │   │   │   ├── answer_option.rb
│   │   │   │   ├── question.rb
│   │   │   │   ├── question_option.rb
│   │   │   │   ├── response.rb
│   │   │   │   └── section.rb
│   │   │   ├── survey.rb
│   │   │   ├── user_achievement.rb
│   │   │   ├── user_email_unsubscription.rb
│   │   │   ├── user_invitation.rb
│   │   │   ├── video/
│   │   │   │   ├── event.rb
│   │   │   │   ├── session.rb
│   │   │   │   ├── statistic.rb
│   │   │   │   ├── submission/
│   │   │   │   │   └── statistic.rb
│   │   │   │   ├── submission.rb
│   │   │   │   ├── tab.rb
│   │   │   │   └── topic.rb
│   │   │   └── video.rb
│   │   ├── course.rb
│   │   ├── course_user.rb
│   │   ├── duplication_traceable/
│   │   │   ├── assessment.rb
│   │   │   └── course.rb
│   │   ├── duplication_traceable.rb
│   │   ├── generic_announcement.rb
│   │   ├── instance/
│   │   │   ├── announcement.rb
│   │   │   ├── settings/
│   │   │   │   └── components.rb
│   │   │   ├── settings.rb
│   │   │   ├── user_invitation.rb
│   │   │   └── user_role_request.rb
│   │   ├── instance.rb
│   │   ├── instance_user.rb
│   │   ├── settings.rb
│   │   ├── system/
│   │   │   └── announcement.rb
│   │   ├── user/
│   │   │   ├── email.rb
│   │   │   └── identity.rb
│   │   ├── user.rb
│   │   └── user_notification.rb
│   ├── notifiers/
│   │   ├── course/
│   │   │   ├── achievement_notifier.rb
│   │   │   ├── announcement_notifier.rb
│   │   │   ├── assessment/
│   │   │   │   ├── answer/
│   │   │   │   │   └── comment_notifier.rb
│   │   │   │   └── submission_question/
│   │   │   │       └── comment_notifier.rb
│   │   │   ├── assessment_notifier.rb
│   │   │   ├── consolidated_opening_reminder_notifier.rb
│   │   │   ├── forum/
│   │   │   │   ├── post_notifier.rb
│   │   │   │   └── topic_notifier.rb
│   │   │   ├── level_notifier.rb
│   │   │   └── video_notifier.rb
│   │   └── notifier/
│   │       └── base.rb
│   ├── services/
│   │   ├── authentication/
│   │   │   ├── authentication_service.rb
│   │   │   ├── jwt_verification_service.rb
│   │   │   ├── keycloak_verification_service.rb
│   │   │   └── verification_service.rb
│   │   ├── cikgo/
│   │   │   ├── chats_service.rb
│   │   │   ├── resources_service.rb
│   │   │   ├── service.rb
│   │   │   ├── timelines_service.rb
│   │   │   └── users_service.rb
│   │   ├── codaveri_async_api_service.rb
│   │   ├── concerns/
│   │   │   ├── cikgo/
│   │   │   │   └── course_concern.rb
│   │   │   ├── course/
│   │   │   │   └── user_invitation_service/
│   │   │   │       ├── email_invitation_concern.rb
│   │   │   │       ├── parse_invitation_concern.rb
│   │   │   │       └── process_invitation_concern.rb
│   │   │   └── instance/
│   │   │       └── user_invitation_service/
│   │   │           ├── email_invitation_concern.rb
│   │   │           ├── parse_invitation_concern.rb
│   │   │           └── process_invitation_concern.rb
│   │   ├── course/
│   │   │   ├── announcement/
│   │   │   │   └── reminder_service.rb
│   │   │   ├── assessment/
│   │   │   │   ├── achievement_preload_service.rb
│   │   │   │   ├── answer/
│   │   │   │   │   ├── ai_generated_post_service.rb
│   │   │   │   │   ├── auto_grading_service.rb
│   │   │   │   │   ├── live_feedback/
│   │   │   │   │   │   ├── feedback_service.rb
│   │   │   │   │   │   └── thread_service.rb
│   │   │   │   │   ├── multiple_response_auto_grading_service.rb
│   │   │   │   │   ├── programming_auto_grading_service.rb
│   │   │   │   │   ├── programming_codaveri_async_feedback_service.rb
│   │   │   │   │   ├── programming_codaveri_auto_grading_service.rb
│   │   │   │   │   ├── prompts/
│   │   │   │   │   │   ├── rubric_auto_grading_output_format.json
│   │   │   │   │   │   ├── rubric_auto_grading_system_prompt.json
│   │   │   │   │   │   └── rubric_auto_grading_user_prompt.json
│   │   │   │   │   ├── rubric_auto_grading_service.rb
│   │   │   │   │   ├── rubric_based_response/
│   │   │   │   │   │   └── answer_adapter.rb
│   │   │   │   │   ├── text_response_auto_grading_service.rb
│   │   │   │   │   └── text_response_comprehension_auto_grading_service.rb
│   │   │   │   ├── authentication_service.rb
│   │   │   │   ├── koditsu_assessment_invitation_service.rb
│   │   │   │   ├── koditsu_assessment_service.rb
│   │   │   │   ├── monitoring_service.rb
│   │   │   │   ├── programming_codaveri_evaluation_service.rb
│   │   │   │   ├── programming_evaluation_service.rb
│   │   │   │   ├── question/
│   │   │   │   │   ├── answers_evaluation_service.rb
│   │   │   │   │   ├── codaveri_problem_generation_service.rb
│   │   │   │   │   ├── koditsu_question_service.rb
│   │   │   │   │   ├── mrq_generation_service.rb
│   │   │   │   │   ├── programming/
│   │   │   │   │   │   ├── c_sharp/
│   │   │   │   │   │   │   ├── c_sharp_makefile
│   │   │   │   │   │   │   └── c_sharp_package_service.rb
│   │   │   │   │   │   ├── cpp/
│   │   │   │   │   │   │   ├── cpp_autograde_include.cc
│   │   │   │   │   │   │   ├── cpp_autograde_post.cc
│   │   │   │   │   │   │   ├── cpp_autograde_pre.cc
│   │   │   │   │   │   │   ├── cpp_makefile
│   │   │   │   │   │   │   └── cpp_package_service.rb
│   │   │   │   │   │   ├── go/
│   │   │   │   │   │   │   ├── go_makefile
│   │   │   │   │   │   │   └── go_package_service.rb
│   │   │   │   │   │   ├── java/
│   │   │   │   │   │   │   ├── RunTests.java
│   │   │   │   │   │   │   ├── java_autograde_pre.java
│   │   │   │   │   │   │   ├── java_build.xml
│   │   │   │   │   │   │   ├── java_package_service.rb
│   │   │   │   │   │   │   ├── java_simple_makefile
│   │   │   │   │   │   │   └── java_standard_makefile
│   │   │   │   │   │   ├── java_script/
│   │   │   │   │   │   │   ├── java_script_makefile
│   │   │   │   │   │   │   └── java_script_package_service.rb
│   │   │   │   │   │   ├── language_package_service.rb
│   │   │   │   │   │   ├── programming_package_service.rb
│   │   │   │   │   │   ├── python/
│   │   │   │   │   │   │   ├── python_autograde_post.py
│   │   │   │   │   │   │   ├── python_autograde_pre.py
│   │   │   │   │   │   │   ├── python_makefile
│   │   │   │   │   │   │   └── python_package_service.rb
│   │   │   │   │   │   ├── r/
│   │   │   │   │   │   │   ├── r_makefile
│   │   │   │   │   │   │   └── r_package_service.rb
│   │   │   │   │   │   ├── rust/
│   │   │   │   │   │   │   ├── rust_makefile
│   │   │   │   │   │   │   └── rust_package_service.rb
│   │   │   │   │   │   └── type_script/
│   │   │   │   │   │       ├── type_script_makefile
│   │   │   │   │   │       └── type_script_package_service.rb
│   │   │   │   │   ├── programming_codaveri/
│   │   │   │   │   │   ├── c_sharp/
│   │   │   │   │   │   │   └── c_sharp_package_service.rb
│   │   │   │   │   │   ├── go/
│   │   │   │   │   │   │   └── go_package_service.rb
│   │   │   │   │   │   ├── java/
│   │   │   │   │   │   │   └── java_package_service.rb
│   │   │   │   │   │   ├── java_script/
│   │   │   │   │   │   │   └── java_script_package_service.rb
│   │   │   │   │   │   ├── language_package_service.rb
│   │   │   │   │   │   ├── programming_codaveri_package_service.rb
│   │   │   │   │   │   ├── python/
│   │   │   │   │   │   │   └── python_package_service.rb
│   │   │   │   │   │   ├── r/
│   │   │   │   │   │   │   └── r_package_service.rb
│   │   │   │   │   │   ├── rust/
│   │   │   │   │   │   │   └── rust_package_service.rb
│   │   │   │   │   │   └── type_script/
│   │   │   │   │   │       └── type_script_package_service.rb
│   │   │   │   │   ├── programming_codaveri_service.rb
│   │   │   │   │   ├── programming_import_service.rb
│   │   │   │   │   ├── prompts/
│   │   │   │   │   │   ├── mcq_generation_system_prompt.json
│   │   │   │   │   │   ├── mcq_generation_user_prompt.json
│   │   │   │   │   │   ├── mcq_mrq_generation_output_format.json
│   │   │   │   │   │   ├── mrq_generation_system_prompt.json
│   │   │   │   │   │   └── mrq_generation_user_prompt.json
│   │   │   │   │   ├── question_adapter.rb
│   │   │   │   │   ├── rubric_based_response/
│   │   │   │   │   │   └── rubric_adapter.rb
│   │   │   │   │   ├── scribing_import_service.rb
│   │   │   │   │   └── text_response_lemma_service.rb
│   │   │   │   ├── reminder_service.rb
│   │   │   │   ├── session_authentication_service.rb
│   │   │   │   ├── session_log_service.rb
│   │   │   │   └── submission/
│   │   │   │       ├── auto_grading_service.rb
│   │   │   │       ├── base_zip_download_service.rb
│   │   │   │       ├── calculate_exp_service.rb
│   │   │   │       ├── csv_download_service.rb
│   │   │   │       ├── koditsu_submission_service.rb
│   │   │   │       ├── monitoring_service.rb
│   │   │   │       ├── ssid_plagiarism_service.rb
│   │   │   │       ├── ssid_zip_download_service.rb
│   │   │   │       ├── statistics_download_service.rb
│   │   │   │       ├── update_service.rb
│   │   │   │       └── zip_download_service.rb
│   │   │   ├── conditional/
│   │   │   │   ├── conditional_satisfiability_evaluation_service.rb
│   │   │   │   └── satisfiability_graph_build_service.rb
│   │   │   ├── course_owner_preload_service.rb
│   │   │   ├── course_user_preload_service.rb
│   │   │   ├── discussion/
│   │   │   │   └── post/
│   │   │   │       └── codaveri_feedback_rating_service.rb
│   │   │   ├── duplication/
│   │   │   │   ├── base_service.rb
│   │   │   │   ├── course_duplication_service.rb
│   │   │   │   └── object_duplication_service.rb
│   │   │   ├── experience_points_download_service.rb
│   │   │   ├── group_manager_preload_service.rb
│   │   │   ├── koditsu_workspace_service.rb
│   │   │   ├── material/
│   │   │   │   ├── preload_service.rb
│   │   │   │   └── zip_download_service.rb
│   │   │   ├── reference_time/
│   │   │   │   └── time_offset_service.rb
│   │   │   ├── rubric/
│   │   │   │   ├── llm_service/
│   │   │   │   │   ├── answer_adapter.rb
│   │   │   │   │   ├── question_adapter.rb
│   │   │   │   │   └── rubric_adapter.rb
│   │   │   │   └── llm_service.rb
│   │   │   ├── skills_mastery_preload_service.rb
│   │   │   ├── ssid_folder_service.rb
│   │   │   ├── statistics/
│   │   │   │   └── assessments_score_summary_download_service.rb
│   │   │   ├── survey/
│   │   │   │   ├── reminder_service.rb
│   │   │   │   └── survey_download_service.rb
│   │   │   ├── user_invitation_service.rb
│   │   │   ├── user_registration_service.rb
│   │   │   └── video/
│   │   │       └── reminder_service.rb
│   │   ├── instance/
│   │   │   └── user_invitation_service.rb
│   │   ├── koditsu_async_api_service.rb
│   │   ├── rag_wise/
│   │   │   ├── chunking_service.rb
│   │   │   ├── discussion_extraction_service.rb
│   │   │   ├── llm_service.rb
│   │   │   ├── prompts/
│   │   │   │   ├── forum_assistant_system_prompt.json
│   │   │   │   └── guess_course_material_name_system_prompt_template.json
│   │   │   ├── rag_workflow_service.rb
│   │   │   ├── response_evaluation_service.rb
│   │   │   └── tools/
│   │   │       ├── course_forum_discussions_tool.rb
│   │   │       └── course_materials_tool.rb
│   │   ├── scholaistic_api_service.rb
│   │   ├── sidekiq_api_service.rb
│   │   ├── ssid_async_api_service.rb
│   │   └── user/
│   │       └── instance_preload_service.rb
│   ├── uploaders/
│   │   ├── file_uploader.rb
│   │   └── image_uploader.rb
│   └── views/
│       ├── announcements/
│       │   ├── _announcement_data.json.jbuilder
│       │   ├── _announcement_list_data.json.jbuilder
│       │   └── index.json.jbuilder
│       ├── application/
│       │   └── index.json.jbuilder
│       ├── attachment_references/
│       │   └── create.json.jbuilder
│       ├── attachments/
│       │   └── _attachment_reference.json.jbuilder
│       ├── course/
│       │   ├── achievement/
│       │   │   └── achievements/
│       │   │       ├── _achievement.json.jbuilder
│       │   │       ├── _achievement_conditional.json.jbuilder
│       │   │       ├── _achievement_data.json.jbuilder
│       │   │       ├── _achievement_list_data.json.jbuilder
│       │   │       ├── index.json.jbuilder
│       │   │       └── show.json.jbuilder
│       │   ├── admin/
│       │   │   ├── admin/
│       │   │   │   ├── index.json.jbuilder
│       │   │   │   └── time_zones.json.jbuilder
│       │   │   ├── announcement_settings/
│       │   │   │   └── edit.json.jbuilder
│       │   │   ├── assessment_settings/
│       │   │   │   └── edit.json.jbuilder
│       │   │   ├── codaveri_settings/
│       │   │   │   ├── assessment.json.jbuilder
│       │   │   │   └── edit.json.jbuilder
│       │   │   ├── component_settings/
│       │   │   │   └── edit.json.jbuilder
│       │   │   ├── discussion/
│       │   │   │   └── topic_settings/
│       │   │   │       └── edit.json.jbuilder
│       │   │   ├── forum_settings/
│       │   │   │   └── edit.json.jbuilder
│       │   │   ├── leaderboard_settings/
│       │   │   │   └── edit.json.jbuilder
│       │   │   ├── lesson_plan_settings/
│       │   │   │   └── edit.json.jbuilder
│       │   │   ├── material_settings/
│       │   │   │   └── edit.json.jbuilder
│       │   │   ├── notification_settings/
│       │   │   │   └── edit.json.jbuilder
│       │   │   ├── rag_wise_settings/
│       │   │   │   ├── courses.json.jbuilder
│       │   │   │   ├── edit.json.jbuilder
│       │   │   │   ├── folders.json.jbuilder
│       │   │   │   ├── forums.json.jbuilder
│       │   │   │   └── materials.json.jbuilder
│       │   │   ├── scholaistic_settings/
│       │   │   │   └── edit.json.jbuilder
│       │   │   ├── sidebar_settings/
│       │   │   │   ├── edit.json.jbuilder
│       │   │   │   └── show.json.jbuilder
│       │   │   ├── stories_settings/
│       │   │   │   └── edit.json.jbuilder
│       │   │   └── video_settings/
│       │   │       └── edit.json.jbuilder
│       │   ├── announcements/
│       │   │   └── index.json.jbuilder
│       │   ├── assessment/
│       │   │   ├── answer/
│       │   │   │   ├── forum_post_responses/
│       │   │   │   │   └── _forum_post_response.json.jbuilder
│       │   │   │   ├── multiple_responses/
│       │   │   │   │   └── _multiple_response.json.jbuilder
│       │   │   │   ├── programming/
│       │   │   │   │   ├── _annotations.json.jbuilder
│       │   │   │   │   └── _programming.json.jbuilder
│       │   │   │   ├── rubric_based_responses/
│       │   │   │   │   └── _rubric_based_response.json.jbuilder
│       │   │   │   ├── scribing/
│       │   │   │   │   └── _scribing.json.jbuilder
│       │   │   │   ├── text_responses/
│       │   │   │   │   └── _text_response.json.jbuilder
│       │   │   │   └── voice_responses/
│       │   │   │       └── _voice_response.json.jbuilder
│       │   │   ├── answers/
│       │   │   │   └── _answer.json.jbuilder
│       │   │   ├── assessments/
│       │   │   │   ├── _achievement_badges.json.jbuilder
│       │   │   │   ├── _assessment_actions.json.jbuilder
│       │   │   │   ├── _assessment_conditional.json.jbuilder
│       │   │   │   ├── _assessment_lesson_plan_item.json.jbuilder
│       │   │   │   ├── _assessment_list_data.json.jbuilder
│       │   │   │   ├── _assessment_question_bundle_buttons.html.slim
│       │   │   │   ├── _monitoring_details.json.jbuilder
│       │   │   │   ├── authenticate.json.jbuilder
│       │   │   │   ├── blocked_by_monitor.json.jbuilder
│       │   │   │   ├── edit.json.jbuilder
│       │   │   │   ├── index.json.jbuilder
│       │   │   │   ├── monitoring.json.jbuilder
│       │   │   │   └── show.json.jbuilder
│       │   │   ├── categories/
│       │   │   │   ├── _category.json.jbuilder
│       │   │   │   └── index.json.jbuilder
│       │   │   ├── mock_answers/
│       │   │   │   └── index.json.jbuilder
│       │   │   ├── programming_evaluations/
│       │   │   │   ├── _programming_evaluation.json.jbuilder
│       │   │   │   ├── allocate.json.jbuilder
│       │   │   │   ├── show.json.jbuilder
│       │   │   │   └── update_result.json.jbuilder
│       │   │   ├── question/
│       │   │   │   ├── _form.json.jbuilder
│       │   │   │   ├── _skills.json.jbuilder
│       │   │   │   ├── forum_post_responses/
│       │   │   │   │   ├── _form.json.jbuilder
│       │   │   │   │   ├── _forum_post_response.json.jbuilder
│       │   │   │   │   ├── edit.json.jbuilder
│       │   │   │   │   └── new.json.jbuilder
│       │   │   │   ├── multiple_responses/
│       │   │   │   │   ├── _form.json.jbuilder
│       │   │   │   │   ├── _multiple_response.json.jbuilder
│       │   │   │   │   ├── _multiple_response_details.json.jbuilder
│       │   │   │   │   ├── _switch_question_type_button.json.jbuilder
│       │   │   │   │   ├── edit.json.jbuilder
│       │   │   │   │   └── new.json.jbuilder
│       │   │   │   ├── programming/
│       │   │   │   │   ├── _form.json.jbuilder
│       │   │   │   │   ├── _import_result.json.jbuilder
│       │   │   │   │   ├── _languages.json.jbuilder
│       │   │   │   │   ├── _package_ui.json.jbuilder
│       │   │   │   │   ├── _programming.json.jbuilder
│       │   │   │   │   ├── _question.json.jbuilder
│       │   │   │   │   ├── _response.json.jbuilder
│       │   │   │   │   ├── _test_cases.json.jbuilder
│       │   │   │   │   ├── _test_ui.json.jbuilder
│       │   │   │   │   ├── edit.json.jbuilder
│       │   │   │   │   ├── import_result.json.jbuilder
│       │   │   │   │   ├── metadata/
│       │   │   │   │   │   ├── _c_cpp.json.jbuilder
│       │   │   │   │   │   ├── _csharp.json.jbuilder
│       │   │   │   │   │   ├── _default.json.jbuilder
│       │   │   │   │   │   ├── _golang.json.jbuilder
│       │   │   │   │   │   ├── _java.json.jbuilder
│       │   │   │   │   │   ├── _javascript.json.jbuilder
│       │   │   │   │   │   ├── _python.json.jbuilder
│       │   │   │   │   │   ├── _r.json.jbuilder
│       │   │   │   │   │   ├── _rust.json.jbuilder
│       │   │   │   │   │   ├── _typescript.json.jbuilder
│       │   │   │   │   │   └── partials/
│       │   │   │   │   │       ├── _file.json.jbuilder
│       │   │   │   │   │       └── _test_cases.json.jbuilder
│       │   │   │   │   └── new.json.jbuilder
│       │   │   │   ├── rubric_based_responses/
│       │   │   │   │   ├── _category_details.json.jbuilder
│       │   │   │   │   ├── _form.json.jbuilder
│       │   │   │   │   ├── _grade_details.json.jbuilder
│       │   │   │   │   ├── _rubric_based_response.json.jbuilder
│       │   │   │   │   ├── edit.json.jbuilder
│       │   │   │   │   └── new.json.jbuilder
│       │   │   │   ├── scribing/
│       │   │   │   │   ├── _scribing.json.jbuilder
│       │   │   │   │   └── _scribing_question.json.jbuilder
│       │   │   │   ├── text_responses/
│       │   │   │   │   ├── _form.json.jbuilder
│       │   │   │   │   ├── _solution_details.json.jbuilder
│       │   │   │   │   ├── _text_response.json.jbuilder
│       │   │   │   │   ├── edit.json.jbuilder
│       │   │   │   │   └── new.json.jbuilder
│       │   │   │   └── voice_responses/
│       │   │   │       ├── _form.json.jbuilder
│       │   │   │       ├── _voice_response.json.jbuilder
│       │   │   │       ├── edit.json.jbuilder
│       │   │   │       └── new.json.jbuilder
│       │   │   ├── question_bundle_assignments/
│       │   │   │   ├── _form.html.slim
│       │   │   │   ├── _validation_result.html.slim
│       │   │   │   ├── edit.html.slim
│       │   │   │   └── index.html.slim
│       │   │   ├── question_bundle_questions/
│       │   │   │   ├── _form.html.slim
│       │   │   │   ├── edit.html.slim
│       │   │   │   ├── index.html.slim
│       │   │   │   └── new.html.slim
│       │   │   ├── question_bundles/
│       │   │   │   ├── _form.html.slim
│       │   │   │   ├── edit.html.slim
│       │   │   │   ├── index.html.slim
│       │   │   │   └── new.html.slim
│       │   │   ├── question_groups/
│       │   │   │   ├── _form.html.slim
│       │   │   │   ├── edit.html.slim
│       │   │   │   ├── index.html.slim
│       │   │   │   └── new.html.slim
│       │   │   ├── questions/
│       │   │   │   └── show.json.jbuilder
│       │   │   ├── rubrics/
│       │   │   │   ├── fetch_answer_evaluations.json.jbuilder
│       │   │   │   ├── fetch_mock_answer_evaluations.json.jbuilder
│       │   │   │   ├── index.json.jbuilder
│       │   │   │   └── rubric_answers.json.jbuilder
│       │   │   ├── skill_branches/
│       │   │   │   ├── _skill_branch_list_data.json.jbuilder
│       │   │   │   └── _skill_branch_user_list_data.json.jbuilder
│       │   │   ├── skills/
│       │   │   │   ├── _options.json.jbuilder
│       │   │   │   ├── _skill_list_data.json.jbuilder
│       │   │   │   ├── _skill_user_list_data.json.jbuilder
│       │   │   │   └── index.json.jbuilder
│       │   │   ├── submission/
│       │   │   │   ├── answer/
│       │   │   │   │   ├── answers/
│       │   │   │   │   │   └── show.json.jbuilder
│       │   │   │   │   └── forum_post_response/
│       │   │   │   │       └── posts/
│       │   │   │   │           ├── _post_packs.json.jbuilder
│       │   │   │   │           └── selected.json.jbuilder
│       │   │   │   ├── logs/
│       │   │   │   │   ├── _info.json.jbuilder
│       │   │   │   │   ├── _logs.json.jbuilder
│       │   │   │   │   └── index.json.jbuilder
│       │   │   │   └── submissions/
│       │   │   │       ├── _answers.json.jbuilder
│       │   │   │       ├── _history.json.jbuilder
│       │   │   │       ├── _question.json.jbuilder
│       │   │   │       ├── _questions.json.jbuilder
│       │   │   │       ├── _submission.json.jbuilder
│       │   │   │       ├── _topics.json.jbuilder
│       │   │   │       ├── create_live_feedback_chat.json.jbuilder
│       │   │   │       ├── edit.json.jbuilder
│       │   │   │       ├── fetch_live_feedback_chat.json.jbuilder
│       │   │   │       ├── fetch_live_feedback_status.json.jbuilder
│       │   │   │       └── index.json.jbuilder
│       │   │   ├── submission_question/
│       │   │   │   └── submission_questions/
│       │   │   │       └── all_answers.json.jbuilder
│       │   │   └── submissions/
│       │   │       ├── _filter.json.jbuilder
│       │   │       ├── _submissions_list_data.json.jbuilder
│       │   │       ├── _tabs.json.jbuilder
│       │   │       ├── index.json.jbuilder
│       │   │       └── pending.json.jbuilder
│       │   ├── condition/
│       │   │   ├── _condition_data.json.jbuilder
│       │   │   ├── _condition_list_data.json.jbuilder
│       │   │   ├── _conditions.json.jbuilder
│       │   │   ├── _enabled_conditions.json.jbuilder
│       │   │   ├── achievements/
│       │   │   │   └── _achievement.json.jbuilder
│       │   │   ├── assessments/
│       │   │   │   ├── _assessment.json.jbuilder
│       │   │   │   ├── _assessment_condition.json.jbuilder
│       │   │   │   └── available_assessments.json.jbuilder
│       │   │   ├── levels/
│       │   │   │   └── _level.json.jbuilder
│       │   │   ├── scholaistic_assessments/
│       │   │   │   ├── _scholaistic_assessment.json.jbuilder
│       │   │   │   └── available_scholaistic_assessments.json.jbuilder
│       │   │   └── surveys/
│       │   │       ├── _survey.json.jbuilder
│       │   │       └── available_surveys.json.jbuilder
│       │   ├── courses/
│       │   │   ├── _course_data.json.jbuilder
│       │   │   ├── _course_list_data.json.jbuilder
│       │   │   ├── _course_user_progress.json.jbuilder
│       │   │   ├── _sidebar_items.json.jbuilder
│       │   │   ├── index.json.jbuilder
│       │   │   ├── show.json.jbuilder
│       │   │   └── sidebar.json.jbuilder
│       │   ├── discussion/
│       │   │   ├── posts/
│       │   │   │   └── _post.json.jbuilder
│       │   │   └── topics/
│       │   │       ├── _discussion_topic_programming_file_annotation.jbuilder
│       │   │       ├── _discussion_topic_submission_question.json.jbuilder
│       │   │       ├── _discussion_topic_video.json.jbuilder
│       │   │       ├── _tabs.json.jbuilder
│       │   │       ├── _topic.json.jbuilder
│       │   │       ├── discussion_topic_list_data.jbuilder
│       │   │       └── index.json.jbuilder
│       │   ├── enrol_requests/
│       │   │   ├── _enrol_request_list_data.json.jbuilder
│       │   │   └── index.json.jbuilder
│       │   ├── experience_points/
│       │   │   ├── disbursement/
│       │   │   │   └── new.json.jbuilder
│       │   │   └── forum_disbursement/
│       │   │       └── new.json.jbuilder
│       │   ├── experience_points_records/
│       │   │   ├── _experience_points_record.json.jbuilder
│       │   │   ├── index.jbuilder
│       │   │   └── show.jbuilder
│       │   ├── forum/
│       │   │   ├── forums/
│       │   │   │   ├── _forum_list_data.json.jbuilder
│       │   │   │   ├── all_posts.json.jbuilder
│       │   │   │   ├── index.json.jbuilder
│       │   │   │   ├── search.json.jbuilder
│       │   │   │   └── show.json.jbuilder
│       │   │   ├── posts/
│       │   │   │   ├── _post_creator_data.json.jbuilder
│       │   │   │   ├── _post_list_data.json.jbuilder
│       │   │   │   ├── _post_publish_data.json.jbuilder
│       │   │   │   └── create.json.jbuilder
│       │   │   └── topics/
│       │   │       ├── _topic_list_data.json.jbuilder
│       │   │       └── show.json.jbuilder
│       │   ├── group/
│       │   │   ├── _group.json.jbuilder
│       │   │   ├── group_categories/
│       │   │   │   ├── create_groups.json.jbuilder
│       │   │   │   ├── index.json.jbuilder
│       │   │   │   ├── show_info.json.jbuilder
│       │   │   │   └── show_users.json.jbuilder
│       │   │   └── groups/
│       │   │       └── update.json.jbuilder
│       │   ├── leaderboards/
│       │   │   ├── _leaderboard_achievement_list_data.json.jbuilder
│       │   │   ├── _leaderboard_group_list_data.json.jbuilder
│       │   │   ├── _leaderboard_list_data.json.jbuilder
│       │   │   └── index.json.jbuilder
│       │   ├── learning_map/
│       │   │   └── index.json.jbuilder
│       │   ├── lesson_plan/
│       │   │   ├── events/
│       │   │   │   └── _event_lesson_plan_item.json.jbuilder
│       │   │   ├── items/
│       │   │   │   ├── _item.json.jbuilder
│       │   │   │   ├── _personal_or_ref_time.json.jbuilder
│       │   │   │   └── index.json.jbuilder
│       │   │   ├── milestones/
│       │   │   │   └── _milestone.json.jbuilder
│       │   │   └── todos/
│       │   │       └── _todo.json.jbuilder
│       │   ├── levels/
│       │   │   └── index.json.jbuilder
│       │   ├── mailer/
│       │   │   ├── assessment_closing_reminder_email.html.slim
│       │   │   ├── assessment_closing_reminder_email.text.erb
│       │   │   ├── assessment_closing_summary_email.html.slim
│       │   │   ├── assessment_closing_summary_email.text.erb
│       │   │   ├── course_duplicate_failed_email.html.slim
│       │   │   ├── course_duplicate_failed_email.text.erb
│       │   │   ├── course_duplicated_email.html.slim
│       │   │   ├── course_duplicated_email.text.erb
│       │   │   ├── course_user_deletion_failed_email.html.slim
│       │   │   ├── course_user_deletion_failed_email.text.erb
│       │   │   ├── submission_graded_email.html.slim
│       │   │   ├── submission_graded_email.text.erb
│       │   │   ├── survey_closing_reminder_email.html.slim
│       │   │   ├── survey_closing_reminder_email.text.erb
│       │   │   ├── survey_closing_summary_email.html.slim
│       │   │   ├── survey_closing_summary_email.text.erb
│       │   │   ├── user_added_email.html.slim
│       │   │   ├── user_added_email.text.erb
│       │   │   ├── user_enrol_request_received_email.html.slim
│       │   │   ├── user_enrol_request_received_email.text.erb
│       │   │   ├── user_enrol_requested_email.html.slim
│       │   │   ├── user_enrol_requested_email.text.erb
│       │   │   ├── user_invitation_email.html.slim
│       │   │   ├── user_invitation_email.text.erb
│       │   │   ├── user_rejected_email.html.slim
│       │   │   ├── user_rejected_email.text.erb
│       │   │   ├── user_suspended_email.html.slim
│       │   │   ├── user_suspended_email.text.erb
│       │   │   ├── user_unsuspended_email.html.slim
│       │   │   ├── user_unsuspended_email.text.erb
│       │   │   ├── video_closing_reminder_email.html.slim
│       │   │   └── video_closing_reminder_email.text.erb
│       │   ├── material/
│       │   │   ├── _material.json.jbuilder
│       │   │   └── folders/
│       │   │       ├── breadcrumbs.json.jbuilder
│       │   │       ├── show.json.jbuilder
│       │   │       └── upload_materials.json.jbuilder
│       │   ├── object_duplications/
│       │   │   ├── _course_duplication_data.json.jbuilder
│       │   │   └── new.json.jbuilder
│       │   ├── personal_times/
│       │   │   ├── _personal_time_list_data.json.jbuilder
│       │   │   └── index.json.jbuilder
│       │   ├── plagiarism/
│       │   │   └── assessments/
│       │   │       ├── _plagiarism_check.json.jbuilder
│       │   │       ├── _plagiarism_checks.json.jbuilder
│       │   │       ├── index.json.jbuilder
│       │   │       ├── linked_and_unlinked_assessments.json.jbuilder
│       │   │       └── plagiarism_data.json.jbuilder
│       │   ├── question_assessments/
│       │   │   └── _question_assessment.json.jbuilder
│       │   ├── reference_timelines/
│       │   │   ├── _reference_timeline.json.jbuilder
│       │   │   └── index.json.jbuilder
│       │   ├── rubrics/
│       │   │   ├── _answer_evaluation.json.jbuilder
│       │   │   ├── _mock_answer_evaluation.json.jbuilder
│       │   │   ├── _rubric.json.jbuilder
│       │   │   └── index.json.jbuilder
│       │   ├── scholaistic/
│       │   │   ├── assistants/
│       │   │   │   ├── index.json.jbuilder
│       │   │   │   └── show.json.jbuilder
│       │   │   ├── scholaistic_assessments/
│       │   │   │   ├── edit.json.jbuilder
│       │   │   │   ├── index.json.jbuilder
│       │   │   │   ├── new.json.jbuilder
│       │   │   │   └── show.json.jbuilder
│       │   │   └── submissions/
│       │   │       ├── index.json.jbuilder
│       │   │       └── show.json.jbuilder
│       │   ├── statistics/
│       │   │   ├── aggregate/
│       │   │   │   ├── activity_get_help.json.jbuilder
│       │   │   │   ├── all_assessments.json.jbuilder
│       │   │   │   ├── all_staff.json.jbuilder
│       │   │   │   ├── all_students.json.jbuilder
│       │   │   │   ├── course_performance.json.jbuilder
│       │   │   │   └── course_progression.json.jbuilder
│       │   │   ├── assessments/
│       │   │   │   ├── _answer.json.jbuilder
│       │   │   │   ├── _assessment.json.jbuilder
│       │   │   │   ├── _attempt_status.json.jbuilder
│       │   │   │   ├── _course_user.json.jbuilder
│       │   │   │   ├── _live_feedback_history_details.json.jbuilder
│       │   │   │   ├── _submission.json.jbuilder
│       │   │   │   ├── ancestor_info.json.jbuilder
│       │   │   │   ├── ancestor_statistics.json.jbuilder
│       │   │   │   ├── assessment_statistics.json.jbuilder
│       │   │   │   ├── live_feedback_history.json.jbuilder
│       │   │   │   ├── live_feedback_statistics.json.jbuilder
│       │   │   │   └── submission_statistics.json.jbuilder
│       │   │   ├── statistics/
│       │   │   │   └── index.json.jbuilder
│       │   │   └── users/
│       │   │       └── learning_rate_records.json.jbuilder
│       │   ├── survey/
│       │   │   ├── questions/
│       │   │   │   ├── _option.json.jbuilder
│       │   │   │   └── _question.json.jbuilder
│       │   │   ├── responses/
│       │   │   │   ├── _response.json.jbuilder
│       │   │   │   ├── _see_other.json.jbuilder
│       │   │   │   └── index.json.jbuilder
│       │   │   ├── sections/
│       │   │   │   └── _section.json.jbuilder
│       │   │   └── surveys/
│       │   │       ├── _survey.json.jbuilder
│       │   │       ├── _survey_with_questions.json.jbuilder
│       │   │       ├── index.json.jbuilder
│       │   │       └── results.json.jbuilder
│       │   ├── surveys/
│       │   │   └── _survey_lesson_plan_item.json.jbuilder
│       │   ├── user_email_subscriptions/
│       │   │   └── _subscription_setting.json.jbuilder
│       │   ├── user_invitations/
│       │   │   ├── _course_user_invitation_list.json.jbuilder
│       │   │   ├── _course_user_invitation_list_data.json.jbuilder
│       │   │   ├── _invitation_result_data.json.jbuilder
│       │   │   ├── index.json.jbuilder
│       │   │   └── new.json.jbuilder
│       │   ├── user_registrations/
│       │   │   └── _registration.json.jbuilder
│       │   ├── users/
│       │   │   ├── _permissions_data.json.jbuilder
│       │   │   ├── _tabs_data.json.jbuilder
│       │   │   ├── _upgrade_to_staff_results.json.jbuilder
│       │   │   ├── _user.json.jbuilder
│       │   │   ├── _user_data.json.jbuilder
│       │   │   ├── _user_list_data.json.jbuilder
│       │   │   ├── index.json.jbuilder
│       │   │   ├── show.json.jbuilder
│       │   │   ├── staff.json.jbuilder
│       │   │   └── students.json.jbuilder
│       │   ├── video/
│       │   │   ├── sessions/
│       │   │   │   └── _session.json.jbuilder
│       │   │   ├── submission/
│       │   │   │   ├── sessions/
│       │   │   │   │   └── create.json.jbuilder
│       │   │   │   └── submissions/
│       │   │   │       ├── _watch_next_video_url.json.jbuilder
│       │   │   │       ├── edit.json.jbuilder
│       │   │   │       ├── index.json.jbuilder
│       │   │   │       └── show.json.jbuilder
│       │   │   ├── topics/
│       │   │   │   ├── _post.json.jbuilder
│       │   │   │   ├── _posts.json.jbuilder
│       │   │   │   ├── _topic.json.jbuilder
│       │   │   │   ├── _topics.json.jbuilder
│       │   │   │   ├── create.json.jbuilder
│       │   │   │   ├── index.json.jbuilder
│       │   │   │   └── show.json.jbuilder
│       │   │   └── videos/
│       │   │       ├── _video.json.jbuilder
│       │   │       ├── _video_data.json.jbuilder
│       │   │       ├── _video_lesson_plan_item.json.jbuilder
│       │   │       ├── _video_list_data.json.jbuilder
│       │   │       ├── _video_statistics.json.jbuilder
│       │   │       ├── index.json.jbuilder
│       │   │       └── show.json.jbuilder
│       │   └── video_submissions/
│       │       └── index.json.jbuilder
│       ├── instance/
│       │   └── mailer/
│       │       ├── user_added_email.html.slim
│       │       ├── user_added_email.text.erb
│       │       ├── user_invitation_email.html.slim
│       │       └── user_invitation_email.text.erb
│       ├── instance_user_role_request_mailer/
│       │   ├── new_role_request.html.slim
│       │   ├── new_role_request.text.erb
│       │   ├── role_request_approved.html.slim
│       │   ├── role_request_approved.text.erb
│       │   ├── role_request_rejected.html.slim
│       │   └── role_request_rejected.text.erb
│       ├── instance_user_role_requests/
│       │   ├── _instance_user_role_request_list_data.json.jbuilder
│       │   └── index.json.jbuilder
│       ├── jobs/
│       │   ├── _completed.json.jbuilder
│       │   ├── _errored.json.jbuilder
│       │   ├── _submitted.json.jbuilder
│       │   └── show.json.jbuilder
│       ├── layouts/
│       │   ├── _manage_email_subscription.html.slim
│       │   ├── _manage_email_subscription.text.erb
│       │   ├── _materials.json.jbuilder
│       │   ├── mailer.html.slim
│       │   ├── mailer.text.erb
│       │   ├── no_greeting_mailer.html.slim
│       │   └── no_greeting_mailer.text.erb
│       ├── notifiers/
│       │   └── course/
│       │       ├── achievement_notifier/
│       │       │   └── gained/
│       │       │       ├── course_notifications/
│       │       │       │   └── _feed.json.jbuilder
│       │       │       └── user_notifications/
│       │       │           └── popup.json.jbuilder
│       │       ├── announcement_notifier/
│       │       │   └── new/
│       │       │       └── course_notifications/
│       │       │           └── email.html.slim
│       │       ├── assessment/
│       │       │   ├── answer/
│       │       │   │   └── comment_notifier/
│       │       │   │       └── annotated/
│       │       │   │           └── user_notifications/
│       │       │   │               └── email.html.slim
│       │       │   └── submission_question/
│       │       │       └── comment_notifier/
│       │       │           └── replied/
│       │       │               └── user_notifications/
│       │       │                   └── email.html.slim
│       │       ├── assessment_notifier/
│       │       │   ├── attempted/
│       │       │   │   └── course_notifications/
│       │       │   │       └── _feed.json.jbuilder
│       │       │   ├── opening/
│       │       │   │   └── course_notifications/
│       │       │   │       └── email.html.slim
│       │       │   └── submitted/
│       │       │       └── user_notifications/
│       │       │           └── email.html.slim
│       │       ├── consolidated_opening_reminder_notifier/
│       │       │   └── opening_reminder/
│       │       │       └── course_notifications/
│       │       │           ├── course/
│       │       │           │   ├── _assessment.html.slim
│       │       │           │   ├── _survey.html.slim
│       │       │           │   └── _video.html.slim
│       │       │           └── email.html.slim
│       │       ├── forum/
│       │       │   ├── post_notifier/
│       │       │   │   ├── replied/
│       │       │   │   │   ├── course_notifications/
│       │       │   │   │   │   └── _feed.json.jbuilder
│       │       │   │   │   └── user_notifications/
│       │       │   │   │       └── email.html.slim
│       │       │   │   └── voted/
│       │       │   │       └── course_notifications/
│       │       │   │           └── _feed.json.jbuilder
│       │       │   └── topic_notifier/
│       │       │       └── created/
│       │       │           ├── course_notifications/
│       │       │           │   └── _feed.json.jbuilder
│       │       │           └── user_notifications/
│       │       │               └── email.html.slim
│       │       ├── level_notifier/
│       │       │   └── reached/
│       │       │       ├── course_notifications/
│       │       │       │   └── _feed.json.jbuilder
│       │       │       └── user_notifications/
│       │       │           └── popup.json.jbuilder
│       │       └── video_notifier/
│       │           ├── attempted/
│       │           │   └── course_notifications/
│       │           │       └── _feed.json.jbuilder
│       │           ├── closing/
│       │           │   └── user_notifications/
│       │           │       └── email.html.slim
│       │           └── opening/
│       │               └── course_notifications/
│       │                   └── email.html.slim
│       ├── system/
│       │   └── admin/
│       │       ├── announcements/
│       │       │   └── index.json.jbuilder
│       │       ├── courses/
│       │       │   ├── _course_list_data.json.jbuilder
│       │       │   └── index.json.jbuilder
│       │       ├── get_help/
│       │       │   └── index.json.jbuilder
│       │       ├── instance/
│       │       │   ├── admin/
│       │       │   │   └── index.json.jbuilder
│       │       │   ├── announcements/
│       │       │   │   └── index.json.jbuilder
│       │       │   ├── components/
│       │       │   │   └── index.json.jbuilder
│       │       │   ├── courses/
│       │       │   │   └── index.json.jbuilder
│       │       │   ├── get_help/
│       │       │   │   └── index.json.jbuilder
│       │       │   ├── user_invitations/
│       │       │   │   ├── _instance_user_invitation_list_data.json.jbuilder
│       │       │   │   ├── _invitation_result_data.json.jbuilder
│       │       │   │   └── index.json.jbuilder
│       │       │   └── users/
│       │       │       ├── _user_list_data.json.jbuilder
│       │       │       └── index.json.jbuilder
│       │       ├── instances/
│       │       │   ├── _instance_list_data.json.jbuilder
│       │       │   └── index.json.jbuilder
│       │       └── users/
│       │           ├── _user_list_data.json.jbuilder
│       │           └── index.json.jbuilder
│       ├── user/
│       │   ├── emails/
│       │   │   ├── _email_list_data.json.jbuilder
│       │   │   └── index.json.jbuilder
│       │   ├── profiles/
│       │   │   ├── edit.json.jbuilder
│       │   │   └── show.json.jbuilder
│       │   └── registrations/
│       │       └── create.json.jbuilder
│       └── users/
│           ├── _course_list_data.json.jbuilder
│           ├── _instance_list_data.json.jbuilder
│           └── show.json.jbuilder
├── authentication/
│   ├── Dockerfile
│   ├── README.md
│   ├── docker-compose.yml
│   ├── env
│   ├── import/
│   │   └── coursemology_realm.json
│   ├── script/
│   │   └── cm_db_federation.sql
│   └── theme/
│       └── coursemology-keycloakify-keycloak-theme-6.1.7.jar
├── bin/
│   ├── bundle
│   ├── rails
│   ├── rake
│   ├── setup
│   ├── spring
│   └── update
├── client/
│   ├── .babelrc
│   ├── .eslintignore
│   ├── .eslintrc.js
│   ├── .prettierignore
│   ├── .prettierrc.js
│   ├── .yarn-integrity
│   ├── CONTRIBUTING.md
│   ├── README.md
│   ├── app/
│   │   ├── App.tsx
│   │   ├── __test__/
│   │   │   ├── mocks/
│   │   │   │   ├── ResizeObserver.js
│   │   │   │   ├── axiosMock.js
│   │   │   │   ├── fileMock.js
│   │   │   │   ├── matchMedia.js
│   │   │   │   ├── requestAnimationFrame.js
│   │   │   │   └── svgMock.js
│   │   │   ├── setup.js
│   │   │   └── utils/
│   │   │       ├── __test__/
│   │   │       │   └── shallowUntil.test.js
│   │   │       └── shallowUntil.js
│   │   ├── api/
│   │   │   ├── Announcements.ts
│   │   │   ├── Attachments.ts
│   │   │   ├── Base.ts
│   │   │   ├── ErrorHandling.ts
│   │   │   ├── Home.ts
│   │   │   ├── Jobs.ts
│   │   │   ├── Users.ts
│   │   │   ├── course/
│   │   │   │   ├── Achievements.ts
│   │   │   │   ├── Admin/
│   │   │   │   │   ├── Announcements.ts
│   │   │   │   │   ├── Assessments.ts
│   │   │   │   │   ├── Base.ts
│   │   │   │   │   ├── Codaveri.ts
│   │   │   │   │   ├── Comments.ts
│   │   │   │   │   ├── Components.ts
│   │   │   │   │   ├── Course.ts
│   │   │   │   │   ├── Forums.ts
│   │   │   │   │   ├── Leaderboard.ts
│   │   │   │   │   ├── LessonPlan.ts
│   │   │   │   │   ├── Materials.ts
│   │   │   │   │   ├── Notifications.ts
│   │   │   │   │   ├── RagWise.ts
│   │   │   │   │   ├── Scholaistic.ts
│   │   │   │   │   ├── Sidebar.ts
│   │   │   │   │   ├── Stories.ts
│   │   │   │   │   ├── Videos.ts
│   │   │   │   │   └── index.ts
│   │   │   │   ├── Announcements.ts
│   │   │   │   ├── Assessment/
│   │   │   │   │   ├── AllAnswers.ts
│   │   │   │   │   ├── Assessments.js
│   │   │   │   │   ├── Base.js
│   │   │   │   │   ├── Categories.js
│   │   │   │   │   ├── Question/
│   │   │   │   │   │   ├── ForumPostResponse.ts
│   │   │   │   │   │   ├── McqMrq.ts
│   │   │   │   │   │   ├── MockAnswers.ts
│   │   │   │   │   │   ├── Programming.ts
│   │   │   │   │   │   ├── Questions.ts
│   │   │   │   │   │   ├── RubricBasedResponse.ts
│   │   │   │   │   │   ├── Rubrics.ts
│   │   │   │   │   │   ├── Scribing.js
│   │   │   │   │   │   ├── TextResponse.ts
│   │   │   │   │   │   ├── VoiceResponse.ts
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── Sessions.ts
│   │   │   │   │   ├── Skills.ts
│   │   │   │   │   ├── Submission/
│   │   │   │   │   │   ├── Answer/
│   │   │   │   │   │   │   ├── Answer.ts
│   │   │   │   │   │   │   ├── ForumPostResponse.js
│   │   │   │   │   │   │   ├── Programming.js
│   │   │   │   │   │   │   ├── Scribing.js
│   │   │   │   │   │   │   ├── TextResponse.ts
│   │   │   │   │   │   │   └── index.js
│   │   │   │   │   │   └── Logs/
│   │   │   │   │   │       └── Logs.ts
│   │   │   │   │   ├── SubmissionQuestions.js
│   │   │   │   │   ├── Submissions/
│   │   │   │   │   │   └── Submissions.ts
│   │   │   │   │   ├── Submissions.js
│   │   │   │   │   └── index.ts
│   │   │   │   ├── Base.js
│   │   │   │   ├── Comments.ts
│   │   │   │   ├── Conditions.ts
│   │   │   │   ├── Courses.ts
│   │   │   │   ├── Disbursement.ts
│   │   │   │   ├── Duplication.js
│   │   │   │   ├── EnrolRequests.ts
│   │   │   │   ├── ExperiencePointsRecord.ts
│   │   │   │   ├── Forum/
│   │   │   │   │   ├── Forums.ts
│   │   │   │   │   ├── Posts.ts
│   │   │   │   │   ├── Topics.ts
│   │   │   │   │   └── index.ts
│   │   │   │   ├── Groups.js
│   │   │   │   ├── Leaderboard.ts
│   │   │   │   ├── LearningMap.js
│   │   │   │   ├── LessonPlan.js
│   │   │   │   ├── Level.ts
│   │   │   │   ├── Material/
│   │   │   │   │   └── Folders.ts
│   │   │   │   ├── MaterialFolders.js
│   │   │   │   ├── Materials.ts
│   │   │   │   ├── PersonalTimes.ts
│   │   │   │   ├── Plagiarism.ts
│   │   │   │   ├── Posts.js
│   │   │   │   ├── ReferenceTimelines.ts
│   │   │   │   ├── Rubrics.ts
│   │   │   │   ├── Scholaistic.ts
│   │   │   │   ├── Statistics/
│   │   │   │   │   ├── AnswerStatistics.ts
│   │   │   │   │   ├── AssessmentStatistics.ts
│   │   │   │   │   ├── CourseStatistics.ts
│   │   │   │   │   ├── UserStatistics.ts
│   │   │   │   │   └── index.ts
│   │   │   │   ├── Stories.ts
│   │   │   │   ├── Survey/
│   │   │   │   │   ├── Base.js
│   │   │   │   │   ├── Questions.js
│   │   │   │   │   ├── Responses.js
│   │   │   │   │   ├── Sections.js
│   │   │   │   │   ├── Surveys.js
│   │   │   │   │   └── index.js
│   │   │   │   ├── UserEmailSubscriptions.js
│   │   │   │   ├── UserInvitations.ts
│   │   │   │   ├── UserNotifications.ts
│   │   │   │   ├── Users.ts
│   │   │   │   ├── Video/
│   │   │   │   │   ├── Base.js
│   │   │   │   │   ├── Sessions.js
│   │   │   │   │   ├── Submissions.ts
│   │   │   │   │   ├── Topics.js
│   │   │   │   │   ├── Videos.ts
│   │   │   │   │   └── index.js
│   │   │   │   ├── VideoSubmissions.ts
│   │   │   │   └── index.js
│   │   │   ├── index.ts
│   │   │   ├── system/
│   │   │   │   ├── Admin.ts
│   │   │   │   ├── Base.ts
│   │   │   │   ├── InstanceAdmin.ts
│   │   │   │   └── index.js
│   │   │   └── types.ts
│   │   ├── assets/
│   │   │   └── templates/
│   │   │       └── course-user-invitation-template.csv
│   │   ├── bundles/
│   │   │   ├── announcements/
│   │   │   │   ├── GlobalAnnouncementIndex.tsx
│   │   │   │   ├── operations.ts
│   │   │   │   ├── selectors.ts
│   │   │   │   ├── store.ts
│   │   │   │   └── types.ts
│   │   │   ├── authentication/
│   │   │   │   └── pages/
│   │   │   │       └── AuthenticationRedirection/
│   │   │   │           └── index.tsx
│   │   │   ├── common/
│   │   │   │   ├── DashboardPage.tsx
│   │   │   │   ├── ErrorPage.tsx
│   │   │   │   ├── LandingPage.tsx
│   │   │   │   ├── PrivacyPolicyPage/
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   └── privacy-policy.md
│   │   │   │   ├── TermsOfServicePage/
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   └── terms-of-service.md
│   │   │   │   ├── components/
│   │   │   │   │   └── NewCourseButton.tsx
│   │   │   │   └── store.ts
│   │   │   ├── course/
│   │   │   │   ├── achievement/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── buttons/
│   │   │   │   │   │   │   ├── AchievementManagementButtons.tsx
│   │   │   │   │   │   │   └── AwardButton.tsx
│   │   │   │   │   │   ├── forms/
│   │   │   │   │   │   │   └── AchievementForm.tsx
│   │   │   │   │   │   ├── misc/
│   │   │   │   │   │   │   └── AchievementReordering.tsx
│   │   │   │   │   │   └── tables/
│   │   │   │   │   │       └── AchievementTable.tsx
│   │   │   │   │   ├── handles.ts
│   │   │   │   │   ├── operations.ts
│   │   │   │   │   ├── pages/
│   │   │   │   │   │   ├── AchievementAward/
│   │   │   │   │   │   │   ├── AchievementAwardManager.tsx
│   │   │   │   │   │   │   ├── AchievementAwardSummary.tsx
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── AchievementEdit/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── AchievementNew/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── AchievementShow/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   └── AchievementsIndex/
│   │   │   │   │   │       └── index.tsx
│   │   │   │   │   ├── selectors.ts
│   │   │   │   │   ├── store.ts
│   │   │   │   │   └── types.ts
│   │   │   │   ├── admin/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   └── SettingsNavigation.tsx
│   │   │   │   │   ├── pages/
│   │   │   │   │   │   ├── AnnouncementsSettings/
│   │   │   │   │   │   │   ├── AnnouncementsSettingsForm.tsx
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   │   └── translations.ts
│   │   │   │   │   │   ├── AssessmentSettings/
│   │   │   │   │   │   │   ├── AssessmentCategoriesManager/
│   │   │   │   │   │   │   │   ├── Category.tsx
│   │   │   │   │   │   │   │   ├── MoveAssessmentsMenu.tsx
│   │   │   │   │   │   │   │   ├── MoveTabsMenu.tsx
│   │   │   │   │   │   │   │   ├── Tab.tsx
│   │   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   │   └── utils.ts
│   │   │   │   │   │   │   ├── AssessmentSettingsContext.ts
│   │   │   │   │   │   │   ├── AssessmentSettingsForm.tsx
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   │   └── translations.ts
│   │   │   │   │   │   ├── CodaveriSettings/
│   │   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   │   ├── AssessmentCategory.tsx
│   │   │   │   │   │   │   │   ├── AssessmentList.tsx
│   │   │   │   │   │   │   │   ├── AssessmentListItem.tsx
│   │   │   │   │   │   │   │   ├── AssessmentProgrammingQnList.tsx
│   │   │   │   │   │   │   │   ├── AssessmentTab.tsx
│   │   │   │   │   │   │   │   ├── CodaveriSettingsChip.tsx
│   │   │   │   │   │   │   │   ├── buttons/
│   │   │   │   │   │   │   │   │   ├── CodaveriEvaluatorToggleButton.tsx
│   │   │   │   │   │   │   │   │   ├── CodaveriToggleButtons.tsx
│   │   │   │   │   │   │   │   │   ├── ExpandAllSwitch.tsx
│   │   │   │   │   │   │   │   │   └── LiveFeedbackToggleButton.tsx
│   │   │   │   │   │   │   │   ├── forms/
│   │   │   │   │   │   │   │   │   └── CodaveriSettingsForm.tsx
│   │   │   │   │   │   │   │   └── lists/
│   │   │   │   │   │   │   │       └── CollapsibleList.tsx
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   │   ├── selectors.ts
│   │   │   │   │   │   │   └── translations.ts
│   │   │   │   │   │   ├── CommentsSettings/
│   │   │   │   │   │   │   ├── CommentsSettingsForm.tsx
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   │   └── translations.ts
│   │   │   │   │   │   ├── ComponentSettings/
│   │   │   │   │   │   │   ├── ComponentSettingsForm.tsx
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   │   └── translations.ts
│   │   │   │   │   │   ├── CourseSettings/
│   │   │   │   │   │   │   ├── CourseSettingsForm.tsx
│   │   │   │   │   │   │   ├── DeleteCoursePrompt.tsx
│   │   │   │   │   │   │   ├── OffsetTimesPrompt.tsx
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   │   ├── translations.ts
│   │   │   │   │   │   │   └── validationSchema.ts
│   │   │   │   │   │   ├── ForumsSettings/
│   │   │   │   │   │   │   ├── ForumsSettingsForm.tsx
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   │   └── translations.ts
│   │   │   │   │   │   ├── LeaderboardSettings/
│   │   │   │   │   │   │   ├── LeaderboardSettingsForm.tsx
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   │   └── translations.ts
│   │   │   │   │   │   ├── LessonPlanSettings/
│   │   │   │   │   │   │   ├── MilestoneGroupSettings.jsx
│   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   └── index.test.tsx
│   │   │   │   │   │   │   ├── index.jsx
│   │   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   │   └── translations.intl.js
│   │   │   │   │   │   ├── MaterialsSettings/
│   │   │   │   │   │   │   ├── MaterialsSettingsForm.tsx
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   │   └── translations.ts
│   │   │   │   │   │   ├── NotificationSettings/
│   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   └── index.test.tsx
│   │   │   │   │   │   │   ├── index.jsx
│   │   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   │   └── translations.intl.js
│   │   │   │   │   │   ├── RagWiseSettings/
│   │   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   │   ├── CourseTab.tsx
│   │   │   │   │   │   │   │   ├── FolderTab.tsx
│   │   │   │   │   │   │   │   ├── ForumItem.tsx
│   │   │   │   │   │   │   │   ├── ForumList.tsx
│   │   │   │   │   │   │   │   ├── MaterialItem.tsx
│   │   │   │   │   │   │   │   ├── MaterialList.tsx
│   │   │   │   │   │   │   │   ├── buttons/
│   │   │   │   │   │   │   │   │   ├── ExpandAllSwitch.tsx
│   │   │   │   │   │   │   │   │   ├── ForumKnowledgeBaseSwitch.tsx
│   │   │   │   │   │   │   │   │   └── MaterialKnowledgeBaseSwitch.tsx
│   │   │   │   │   │   │   │   ├── forms/
│   │   │   │   │   │   │   │   │   └── RagWiseSettingsForm.tsx
│   │   │   │   │   │   │   │   └── lists/
│   │   │   │   │   │   │   │       └── CollapsibleList.tsx
│   │   │   │   │   │   │   ├── constants.ts
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   │   ├── selectors.ts
│   │   │   │   │   │   │   └── translations.ts
│   │   │   │   │   │   ├── ScholaisticSettings/
│   │   │   │   │   │   │   ├── PingResultAlert.tsx
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   ├── loader.ts
│   │   │   │   │   │   │   └── operations.ts
│   │   │   │   │   │   ├── SidebarSettings/
│   │   │   │   │   │   │   ├── SidebarSettingsForm.tsx
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   │   └── translations.ts
│   │   │   │   │   │   ├── StoriesSettings/
│   │   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   │   └── Introduction.tsx
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   └── operations.ts
│   │   │   │   │   │   └── VideosSettings/
│   │   │   │   │   │       ├── VideosSettingsForm.tsx
│   │   │   │   │   │       ├── VideosTabsManager/
│   │   │   │   │   │       │   ├── Tab.tsx
│   │   │   │   │   │       │   └── index.tsx
│   │   │   │   │   │       ├── index.tsx
│   │   │   │   │   │       ├── operations.ts
│   │   │   │   │   │       └── translations.ts
│   │   │   │   │   ├── reducers/
│   │   │   │   │   │   ├── codaveriSettings.ts
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   ├── lessonPlanSettings.ts
│   │   │   │   │   │   ├── notificationSettings.ts
│   │   │   │   │   │   └── ragWiseSettings.ts
│   │   │   │   │   └── translations.ts
│   │   │   │   ├── announcements/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── buttons/
│   │   │   │   │   │   │   └── NewAnnouncementButton.tsx
│   │   │   │   │   │   ├── forms/
│   │   │   │   │   │   │   └── AnnouncementForm.tsx
│   │   │   │   │   │   └── misc/
│   │   │   │   │   │       ├── AnnouncementCard.tsx
│   │   │   │   │   │       └── AnnouncementsDisplay.tsx
│   │   │   │   │   ├── handles.ts
│   │   │   │   │   ├── operations.ts
│   │   │   │   │   ├── pages/
│   │   │   │   │   │   ├── AnnouncementEdit/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── AnnouncementNew/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   └── AnnouncementsIndex/
│   │   │   │   │   │       └── index.tsx
│   │   │   │   │   ├── selectors.ts
│   │   │   │   │   ├── store.ts
│   │   │   │   │   └── types.ts
│   │   │   │   ├── assessment/
│   │   │   │   │   ├── attemptLoader.ts
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── AssessmentForm/
│   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   └── index.test.tsx
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   │   ├── translations.ts
│   │   │   │   │   │   │   ├── types.ts
│   │   │   │   │   │   │   └── useFormValidation.tsx
│   │   │   │   │   │   ├── ConvertMcqMrqButton/
│   │   │   │   │   │   │   ├── ConvertMcqMrqPrompt.tsx
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── FileManager/
│   │   │   │   │   │   │   ├── Toolbar.tsx
│   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   └── index.test.tsx
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   └── translations.intl.js
│   │   │   │   │   │   ├── Koditsu/
│   │   │   │   │   │   │   ├── KoditsuChip.tsx
│   │   │   │   │   │   │   └── KoditsuChipButton.tsx
│   │   │   │   │   │   └── monitoring/
│   │   │   │   │   │       ├── BlocksInvalidBrowserFormField.tsx
│   │   │   │   │   │       ├── BrowserAuthorizationMethodOptionsFormFields/
│   │   │   │   │   │       │   ├── SebConfigKeyOptionsFormFields.tsx
│   │   │   │   │   │       │   ├── UserAgentOptionsFormFields.tsx
│   │   │   │   │   │       │   ├── common.ts
│   │   │   │   │   │       │   └── index.tsx
│   │   │   │   │   │       ├── BrowserAuthorizationOptionsFormFields.tsx
│   │   │   │   │   │       ├── EnableMonitoringFormField.tsx
│   │   │   │   │   │       ├── MonitoringIntervalsFormFields.tsx
│   │   │   │   │   │       ├── MonitoringOptionsFormFields.tsx
│   │   │   │   │   │       └── translations.ts
│   │   │   │   │   ├── constants.js
│   │   │   │   │   ├── handles.ts
│   │   │   │   │   ├── operations/
│   │   │   │   │   │   ├── assessments.ts
│   │   │   │   │   │   ├── history.ts
│   │   │   │   │   │   ├── liveFeedback.ts
│   │   │   │   │   │   ├── monitoring.ts
│   │   │   │   │   │   ├── plagiarism.ts
│   │   │   │   │   │   ├── questions.ts
│   │   │   │   │   │   └── statistics.ts
│   │   │   │   │   ├── pages/
│   │   │   │   │   │   ├── AssessmentAuthenticate/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── AssessmentBlockedByMonitorPage.tsx
│   │   │   │   │   │   ├── AssessmentEdit/
│   │   │   │   │   │   │   ├── AssessmentEditPage.jsx
│   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   └── index.test.tsx
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── AssessmentGenerate/
│   │   │   │   │   │   │   ├── GenerateTabs.tsx
│   │   │   │   │   │   │   ├── LockableSection.tsx
│   │   │   │   │   │   │   ├── MultipleResponse/
│   │   │   │   │   │   │   │   ├── GenerateMcqMrqConversation.tsx
│   │   │   │   │   │   │   │   ├── GenerateMcqMrqExportDialog.tsx
│   │   │   │   │   │   │   │   ├── GenerateMcqMrqPrototypeForm.tsx
│   │   │   │   │   │   │   │   └── GenerateMcqMrqQuestionPage.tsx
│   │   │   │   │   │   │   ├── Programming/
│   │   │   │   │   │   │   │   ├── GenerateProgrammingConversation.tsx
│   │   │   │   │   │   │   │   ├── GenerateProgrammingExportDialog.tsx
│   │   │   │   │   │   │   │   ├── GenerateProgrammingPrototypeForm.tsx
│   │   │   │   │   │   │   │   ├── GenerateProgrammingQuestionPage.tsx
│   │   │   │   │   │   │   │   └── TestCasesManager.tsx
│   │   │   │   │   │   │   ├── constants.ts
│   │   │   │   │   │   │   ├── selectors.ts
│   │   │   │   │   │   │   ├── types.ts
│   │   │   │   │   │   │   └── utils.ts
│   │   │   │   │   │   ├── AssessmentMonitoring/
│   │   │   │   │   │   │   ├── PulseGrid.tsx
│   │   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   │   ├── ActiveSessionBlob.tsx
│   │   │   │   │   │   │   │   ├── ActivityCenter.tsx
│   │   │   │   │   │   │   │   ├── ConnectionStatus.tsx
│   │   │   │   │   │   │   │   ├── FilterAutocomplete.tsx
│   │   │   │   │   │   │   │   ├── HeartbeatDetailCard.tsx
│   │   │   │   │   │   │   │   ├── HeartbeatsTimeline.tsx
│   │   │   │   │   │   │   │   ├── HeartbeatsTimelineChart.tsx
│   │   │   │   │   │   │   │   ├── SebPayloadDetail.tsx
│   │   │   │   │   │   │   │   ├── Session.tsx
│   │   │   │   │   │   │   │   ├── SessionBlob.tsx
│   │   │   │   │   │   │   │   ├── SessionBlobLegend.tsx
│   │   │   │   │   │   │   │   ├── SessionDetailsPopup.tsx
│   │   │   │   │   │   │   │   ├── SessionsGrid.tsx
│   │   │   │   │   │   │   │   ├── UserAgentDetail.tsx
│   │   │   │   │   │   │   │   └── ValidChip.tsx
│   │   │   │   │   │   │   ├── hooks/
│   │   │   │   │   │   │   │   ├── liveMonitoringChannel.ts
│   │   │   │   │   │   │   │   ├── useLiveMonitoringChannel.ts
│   │   │   │   │   │   │   │   ├── useMonitoring.ts
│   │   │   │   │   │   │   │   └── usePresence.ts
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   ├── selectors.ts
│   │   │   │   │   │   │   ├── types.ts
│   │   │   │   │   │   │   └── utils.ts
│   │   │   │   │   │   ├── AssessmentPlagiarism/
│   │   │   │   │   │   │   ├── AssessmentPlagiarismPage.tsx
│   │   │   │   │   │   │   ├── PlagiarismCheckStatus.tsx
│   │   │   │   │   │   │   ├── PlagiarismResultsTable.tsx
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   └── selectors.ts
│   │   │   │   │   │   ├── AssessmentShow/
│   │   │   │   │   │   │   ├── AssessmentDetails.tsx
│   │   │   │   │   │   │   ├── AssessmentShowHeader.tsx
│   │   │   │   │   │   │   ├── AssessmentShowPage.tsx
│   │   │   │   │   │   │   ├── GenerateQuestionMenu.tsx
│   │   │   │   │   │   │   ├── McqWidget.tsx
│   │   │   │   │   │   │   ├── NewQuestionMenu.tsx
│   │   │   │   │   │   │   ├── Question.tsx
│   │   │   │   │   │   │   ├── QuestionsManager.tsx
│   │   │   │   │   │   │   ├── UnavailableAlert.tsx
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   └── prompts/
│   │   │   │   │   │   │       ├── DeleteQuestionButtonPrompt.tsx
│   │   │   │   │   │   │       └── DuplicationPrompt.tsx
│   │   │   │   │   │   ├── AssessmentStatistics/
│   │   │   │   │   │   │   ├── AncestorOptions.tsx
│   │   │   │   │   │   │   ├── AncestorStatistics.tsx
│   │   │   │   │   │   │   ├── AnswerDisplay/
│   │   │   │   │   │   │   │   └── LastAttempt.tsx
│   │   │   │   │   │   │   ├── AssessmentStatisticsPage.tsx
│   │   │   │   │   │   │   ├── DuplicationHistoryStatistics.tsx
│   │   │   │   │   │   │   ├── GradeDistribution/
│   │   │   │   │   │   │   │   ├── AncestorGradesChart.tsx
│   │   │   │   │   │   │   │   ├── GradesChart.tsx
│   │   │   │   │   │   │   │   └── MainGradesChart.tsx
│   │   │   │   │   │   │   ├── LiveFeedbackHistory/
│   │   │   │   │   │   │   │   ├── GetHelpSlider.tsx
│   │   │   │   │   │   │   │   ├── LiveFeedbackConversation.tsx
│   │   │   │   │   │   │   │   ├── LiveFeedbackDetails.tsx
│   │   │   │   │   │   │   │   ├── LiveFeedbackFiles.tsx
│   │   │   │   │   │   │   │   ├── LiveFeedbackHistoryTimelineView.tsx
│   │   │   │   │   │   │   │   ├── LiveFeedbackMessageHistory.tsx
│   │   │   │   │   │   │   │   ├── LiveFeedbackMessageOptionHistory.tsx
│   │   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   │   ├── LiveFeedbackStatistics.tsx
│   │   │   │   │   │   │   ├── LiveFeedbackStatisticsTable.tsx
│   │   │   │   │   │   │   ├── StatisticsCharts.tsx
│   │   │   │   │   │   │   ├── StudentAttemptCountTable.tsx
│   │   │   │   │   │   │   ├── StudentGradesPerQuestionTable.tsx
│   │   │   │   │   │   │   ├── SubmissionStatus/
│   │   │   │   │   │   │   │   ├── AncestorSubmissionChart.tsx
│   │   │   │   │   │   │   │   ├── MainSubmissionChart.tsx
│   │   │   │   │   │   │   │   └── SubmissionStatusChart.tsx
│   │   │   │   │   │   │   ├── SubmissionTimeAndGradeStatistics/
│   │   │   │   │   │   │   │   ├── AncestorSubmissionTimeAndGradeStatistics.tsx
│   │   │   │   │   │   │   │   ├── MainSubmissionTimeAndGradeStatistics.tsx
│   │   │   │   │   │   │   │   └── SubmissionTimeAndGradeChart.tsx
│   │   │   │   │   │   │   ├── classNameUtils.ts
│   │   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   │   └── LiveFeedbackMetricsSelector.tsx
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   ├── selectors.ts
│   │   │   │   │   │   │   ├── translations.ts
│   │   │   │   │   │   │   └── utils.js
│   │   │   │   │   │   └── AssessmentsIndex/
│   │   │   │   │   │       ├── ActionButtons.tsx
│   │   │   │   │   │       ├── AssessmentsTable.tsx
│   │   │   │   │   │       ├── NewAssessmentFormButton.jsx
│   │   │   │   │   │       ├── StatusBadges.tsx
│   │   │   │   │   │       ├── UnavailableMessage.tsx
│   │   │   │   │   │       ├── __test__/
│   │   │   │   │   │       │   └── index.test.jsx
│   │   │   │   │   │       └── index.tsx
│   │   │   │   │   ├── question/
│   │   │   │   │   │   ├── commons/
│   │   │   │   │   │   │   ├── useDirty.ts
│   │   │   │   │   │   │   └── utils.ts
│   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   ├── AIGradingPlaygroundAlert.tsx
│   │   │   │   │   │   │   ├── CommonQuestionFields.tsx
│   │   │   │   │   │   │   ├── QuestionFormOutlet.tsx
│   │   │   │   │   │   │   └── SkillsAutocomplete.tsx
│   │   │   │   │   │   ├── forum-post-responses/
│   │   │   │   │   │   │   ├── EditForumPostResponsePage.tsx
│   │   │   │   │   │   │   ├── NewForumPostResponsePage.tsx
│   │   │   │   │   │   │   ├── commons/
│   │   │   │   │   │   │   │   └── validations.ts
│   │   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   │   └── ForumPostResponseForm.tsx
│   │   │   │   │   │   │   └── operation.ts
│   │   │   │   │   │   ├── multiple-responses/
│   │   │   │   │   │   │   ├── EditMcqMrqPage.tsx
│   │   │   │   │   │   │   ├── NewMcqMrqPage.tsx
│   │   │   │   │   │   │   ├── commons/
│   │   │   │   │   │   │   │   ├── translationAdapter.tsx
│   │   │   │   │   │   │   │   └── validations.ts
│   │   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   │   ├── AdaptedForm.tsx
│   │   │   │   │   │   │   │   ├── ConvertMcqMrqIllustration/
│   │   │   │   │   │   │   │   │   ├── McqIllustration.tsx
│   │   │   │   │   │   │   │   │   ├── MrqIllustration.tsx
│   │   │   │   │   │   │   │   │   ├── OptionSkeleton.tsx
│   │   │   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   │   │   ├── McqMrqForm.tsx
│   │   │   │   │   │   │   │   ├── Option.tsx
│   │   │   │   │   │   │   │   └── OptionsManager.tsx
│   │   │   │   │   │   │   └── operations.ts
│   │   │   │   │   │   ├── programming/
│   │   │   │   │   │   │   ├── EditProgrammingQuestionPage.tsx
│   │   │   │   │   │   │   ├── NewProgrammingQuestionPage.tsx
│   │   │   │   │   │   │   ├── ProgrammingForm.tsx
│   │   │   │   │   │   │   ├── commons/
│   │   │   │   │   │   │   │   ├── builder.ts
│   │   │   │   │   │   │   │   └── validation.ts
│   │   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   │   ├── ReorderableTestCasesManager.tsx
│   │   │   │   │   │   │   │   ├── common/
│   │   │   │   │   │   │   │   │   ├── ControlledEditor.tsx
│   │   │   │   │   │   │   │   │   ├── DataFileRow.tsx
│   │   │   │   │   │   │   │   │   ├── DataFilesAccordion.tsx
│   │   │   │   │   │   │   │   │   ├── DataFilesManager.tsx
│   │   │   │   │   │   │   │   │   ├── EditorAccordion.tsx
│   │   │   │   │   │   │   │   │   ├── ExpressionField.tsx
│   │   │   │   │   │   │   │   │   ├── ImportResult.tsx
│   │   │   │   │   │   │   │   │   ├── InstalledDependenciesPrompt.tsx
│   │   │   │   │   │   │   │   │   ├── InstalledDependenciesTable.tsx
│   │   │   │   │   │   │   │   │   ├── PackageInfo.tsx
│   │   │   │   │   │   │   │   │   ├── PackageUploader.tsx
│   │   │   │   │   │   │   │   │   ├── ReorderableJavaTestCase.tsx
│   │   │   │   │   │   │   │   │   ├── ReorderableTestCase.tsx
│   │   │   │   │   │   │   │   │   ├── ReorderableTestCases.tsx
│   │   │   │   │   │   │   │   │   ├── StaticTestCase.tsx
│   │   │   │   │   │   │   │   │   ├── StaticTestCases.tsx
│   │   │   │   │   │   │   │   │   ├── StaticTestCasesTable.tsx
│   │   │   │   │   │   │   │   │   ├── TestCaseCell.tsx
│   │   │   │   │   │   │   │   │   └── TestCaseRow.tsx
│   │   │   │   │   │   │   │   ├── package/
│   │   │   │   │   │   │   │   │   ├── BasicPackageEditor.tsx
│   │   │   │   │   │   │   │   │   ├── CppPackageEditor.tsx
│   │   │   │   │   │   │   │   │   ├── CsharpPackageEditor.tsx
│   │   │   │   │   │   │   │   │   ├── GoPackageEditor.tsx
│   │   │   │   │   │   │   │   │   ├── JavaPackageEditor.tsx
│   │   │   │   │   │   │   │   │   ├── JavascriptPackageEditor.tsx
│   │   │   │   │   │   │   │   │   ├── PackageDetails.tsx
│   │   │   │   │   │   │   │   │   ├── PackageEditor.tsx
│   │   │   │   │   │   │   │   │   ├── PolyglotEditor.tsx
│   │   │   │   │   │   │   │   │   ├── PythonPackageEditor.tsx
│   │   │   │   │   │   │   │   │   ├── RPackageEditor.tsx
│   │   │   │   │   │   │   │   │   ├── RustPackageEditor.tsx
│   │   │   │   │   │   │   │   │   └── TypescriptPackageEditor.tsx
│   │   │   │   │   │   │   │   └── sections/
│   │   │   │   │   │   │   │       ├── BuildLog.tsx
│   │   │   │   │   │   │   │       ├── EvaluatorFields.tsx
│   │   │   │   │   │   │   │       ├── FeedbackFields.tsx
│   │   │   │   │   │   │   │       ├── LanguageFields.tsx
│   │   │   │   │   │   │   │       ├── PackageFields.tsx
│   │   │   │   │   │   │   │       ├── QuestionFields.tsx
│   │   │   │   │   │   │   │       └── SubmitWarningDialog.tsx
│   │   │   │   │   │   │   ├── hooks/
│   │   │   │   │   │   │   │   ├── ProgrammingFormDataContext.tsx
│   │   │   │   │   │   │   │   └── useLanguageMode.tsx
│   │   │   │   │   │   │   └── operations.ts
│   │   │   │   │   │   ├── reducers/
│   │   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   │   └── rubrics.ts
│   │   │   │   │   │   ├── rubric-based-responses/
│   │   │   │   │   │   │   ├── EditRubricBasedResponsePage.tsx
│   │   │   │   │   │   │   ├── NewRubricBasedResponsePage.tsx
│   │   │   │   │   │   │   ├── commons/
│   │   │   │   │   │   │   │   └── validation.ts
│   │   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   │   ├── AIGradingFields.tsx
│   │   │   │   │   │   │   │   ├── CategoryManager.tsx
│   │   │   │   │   │   │   │   ├── QuestionFields.tsx
│   │   │   │   │   │   │   │   └── RubricBasedResponseForm.tsx
│   │   │   │   │   │   │   ├── hooks/
│   │   │   │   │   │   │   │   └── RubricBasedResponseFormDataContext.tsx
│   │   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   │   └── utils.ts
│   │   │   │   │   │   ├── rubric-playground/
│   │   │   │   │   │   │   ├── AddAnswersPrompt.tsx
│   │   │   │   │   │   │   ├── AnswerEvaluationsTable/
│   │   │   │   │   │   │   │   ├── CategoryGradeCell.tsx
│   │   │   │   │   │   │   │   ├── PopoverContentCell.tsx
│   │   │   │   │   │   │   │   ├── TotalGradeCell.tsx
│   │   │   │   │   │   │   │   ├── UnevaluatedCell.tsx
│   │   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   │   ├── types.ts
│   │   │   │   │   │   │   │   └── utils.ts
│   │   │   │   │   │   │   ├── AnswerEvaluationsTableHeader.tsx
│   │   │   │   │   │   │   ├── RubricEditForm/
│   │   │   │   │   │   │   │   ├── PlaygroundCategoryManager.tsx
│   │   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   │   ├── RubricHeader/
│   │   │   │   │   │   │   │   ├── HeaderButton.tsx
│   │   │   │   │   │   │   │   ├── VersionSlider.tsx
│   │   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   │   ├── RubricPlaygroundPage.tsx
│   │   │   │   │   │   │   ├── operations/
│   │   │   │   │   │   │   │   ├── answers.ts
│   │   │   │   │   │   │   │   ├── mockAnswers.ts
│   │   │   │   │   │   │   │   ├── rowEvaluation.ts
│   │   │   │   │   │   │   │   └── rubric.ts
│   │   │   │   │   │   │   ├── translations.ts
│   │   │   │   │   │   │   ├── types.ts
│   │   │   │   │   │   │   └── utils.ts
│   │   │   │   │   │   ├── scribing/
│   │   │   │   │   │   │   ├── ScribingQuestion.tsx
│   │   │   │   │   │   │   ├── ScribingQuestionForm/
│   │   │   │   │   │   │   │   ├── ScribingQuestionForm.scss
│   │   │   │   │   │   │   │   ├── index.jsx
│   │   │   │   │   │   │   │   └── translations.ts
│   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   ├── index.test.tsx
│   │   │   │   │   │   │   │   └── responses.test.ts
│   │   │   │   │   │   │   ├── constants.js
│   │   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   │   ├── propTypes.js
│   │   │   │   │   │   │   ├── store.ts
│   │   │   │   │   │   │   ├── types.ts
│   │   │   │   │   │   │   └── utils.js
│   │   │   │   │   │   ├── selectors/
│   │   │   │   │   │   │   └── rubrics.ts
│   │   │   │   │   │   ├── text-responses/
│   │   │   │   │   │   │   ├── EditTextResponsePage.tsx
│   │   │   │   │   │   │   ├── NewTextResponsePage.tsx
│   │   │   │   │   │   │   ├── commons/
│   │   │   │   │   │   │   │   └── validations.ts
│   │   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   │   ├── FileUploadManager.tsx
│   │   │   │   │   │   │   │   ├── Solution.tsx
│   │   │   │   │   │   │   │   ├── SolutionsManager.tsx
│   │   │   │   │   │   │   │   └── TextResponseForm.tsx
│   │   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   │   └── utils.tsx
│   │   │   │   │   │   └── voice-responses/
│   │   │   │   │   │       ├── EditVoicePage.tsx
│   │   │   │   │   │       ├── NewVoicePage.tsx
│   │   │   │   │   │       ├── components/
│   │   │   │   │   │       │   └── VoiceForm.tsx
│   │   │   │   │   │       └── operations.ts
│   │   │   │   │   ├── reducers/
│   │   │   │   │   │   ├── editPage.js
│   │   │   │   │   │   ├── formDialog.js
│   │   │   │   │   │   ├── generation.ts
│   │   │   │   │   │   ├── liveFeedback.ts
│   │   │   │   │   │   ├── monitoring.ts
│   │   │   │   │   │   ├── plagiarism.ts
│   │   │   │   │   │   └── statistics.ts
│   │   │   │   │   ├── sessions/
│   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   └── pages/
│   │   │   │   │   │       └── AssessmentSessionNew/
│   │   │   │   │   │           └── index.tsx
│   │   │   │   │   ├── skills/
│   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   ├── buttons/
│   │   │   │   │   │   │   │   └── SkillManagementButtons.tsx
│   │   │   │   │   │   │   ├── dialogs/
│   │   │   │   │   │   │   │   └── SkillDialog.tsx
│   │   │   │   │   │   │   ├── forms/
│   │   │   │   │   │   │   │   └── SkillForm.tsx
│   │   │   │   │   │   │   └── tables/
│   │   │   │   │   │   │       └── SkillsTable.tsx
│   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   ├── pages/
│   │   │   │   │   │   │   └── SkillsIndex/
│   │   │   │   │   │   │       └── index.tsx
│   │   │   │   │   │   ├── selectors.ts
│   │   │   │   │   │   ├── store.ts
│   │   │   │   │   │   └── types.ts
│   │   │   │   │   ├── store.ts
│   │   │   │   │   ├── submission/
│   │   │   │   │   │   ├── actions/
│   │   │   │   │   │   │   ├── annotations.js
│   │   │   │   │   │   │   ├── answers/
│   │   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   │   └── scribing.test.ts
│   │   │   │   │   │   │   │   ├── index.js
│   │   │   │   │   │   │   │   ├── programming.js
│   │   │   │   │   │   │   │   ├── scribing.ts
│   │   │   │   │   │   │   │   ├── textResponse.js
│   │   │   │   │   │   │   │   └── voiceResponse.js
│   │   │   │   │   │   │   ├── comments.js
│   │   │   │   │   │   │   ├── index.js
│   │   │   │   │   │   │   ├── live_feedback.ts
│   │   │   │   │   │   │   ├── logs.ts
│   │   │   │   │   │   │   ├── submissions.js
│   │   │   │   │   │   │   └── utils.js
│   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   ├── AllAttempts/
│   │   │   │   │   │   │   │   ├── AllAttemptsQuestion.tsx
│   │   │   │   │   │   │   │   ├── AllAttemptsSequenceView.tsx
│   │   │   │   │   │   │   │   ├── AllAttemptsTimelineView.tsx
│   │   │   │   │   │   │   │   ├── Comment.tsx
│   │   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   │   ├── AnswerDetails/
│   │   │   │   │   │   │   │   ├── AnswerDetails.tsx
│   │   │   │   │   │   │   │   ├── AttachmentDetails.tsx
│   │   │   │   │   │   │   │   ├── FileUploadDetails.tsx
│   │   │   │   │   │   │   │   ├── ForumPostResponseComponent/
│   │   │   │   │   │   │   │   │   ├── ParentPostPack.tsx
│   │   │   │   │   │   │   │   │   ├── PostContent.tsx
│   │   │   │   │   │   │   │   │   └── PostPack.tsx
│   │   │   │   │   │   │   │   ├── ForumPostResponseDetails.tsx
│   │   │   │   │   │   │   │   ├── MultipleChoiceDetails.tsx
│   │   │   │   │   │   │   │   ├── MultipleResponseDetails.tsx
│   │   │   │   │   │   │   │   ├── ProgrammingAnswerDetails.tsx
│   │   │   │   │   │   │   │   ├── ProgrammingComponent/
│   │   │   │   │   │   │   │   │   ├── CodaveriFeedbackStatus.tsx
│   │   │   │   │   │   │   │   │   ├── FileContent.tsx
│   │   │   │   │   │   │   │   │   ├── TestCaseRow.tsx
│   │   │   │   │   │   │   │   │   └── TestCases.tsx
│   │   │   │   │   │   │   │   ├── RubricBasedResponseDetails.tsx
│   │   │   │   │   │   │   │   └── TextResponseDetails.tsx
│   │   │   │   │   │   │   ├── DropzoneErrorComponent.tsx
│   │   │   │   │   │   │   ├── Editor.jsx
│   │   │   │   │   │   │   ├── EvaluatorErrorPanel.tsx
│   │   │   │   │   │   │   ├── FileInput.jsx
│   │   │   │   │   │   │   ├── GetHelpChatPage/
│   │   │   │   │   │   │   │   ├── ChatInputArea.tsx
│   │   │   │   │   │   │   │   ├── ChipButton.tsx
│   │   │   │   │   │   │   │   ├── ConversationArea.tsx
│   │   │   │   │   │   │   │   ├── Header.tsx
│   │   │   │   │   │   │   │   ├── SuggestionChips.tsx
│   │   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   │   └── utils.ts
│   │   │   │   │   │   │   ├── MarkdownText.tsx
│   │   │   │   │   │   │   ├── ProgressPanel.tsx
│   │   │   │   │   │   │   ├── ReadOnlyEditor/
│   │   │   │   │   │   │   │   ├── AddCommentIcon.jsx
│   │   │   │   │   │   │   │   ├── Checkbox.jsx
│   │   │   │   │   │   │   │   ├── NarrowEditor.jsx
│   │   │   │   │   │   │   │   ├── WideComments.jsx
│   │   │   │   │   │   │   │   ├── WideEditor.jsx
│   │   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   │   ├── ScribingView/
│   │   │   │   │   │   │   │   ├── LayersComponent.tsx
│   │   │   │   │   │   │   │   ├── ScribingCanvas.tsx
│   │   │   │   │   │   │   │   ├── ScribingToolbar.tsx
│   │   │   │   │   │   │   │   ├── ScribingView.scss
│   │   │   │   │   │   │   │   ├── ToolDropdown.jsx
│   │   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   │   ├── ScribingToolbar.test.tsx
│   │   │   │   │   │   │   │   │   └── index.test.tsx
│   │   │   │   │   │   │   │   ├── fields/
│   │   │   │   │   │   │   │   │   ├── ColorPickerField.jsx
│   │   │   │   │   │   │   │   │   ├── FontFamilyField.jsx
│   │   │   │   │   │   │   │   │   ├── FontSizeField.jsx
│   │   │   │   │   │   │   │   │   ├── LineStyleField.jsx
│   │   │   │   │   │   │   │   │   ├── LineThicknessField.jsx
│   │   │   │   │   │   │   │   │   ├── ShapeField.tsx
│   │   │   │   │   │   │   │   │   └── __test__/
│   │   │   │   │   │   │   │   │       └── ColorPickerField.test.js
│   │   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   │   └── popovers/
│   │   │   │   │   │   │   │       ├── DrawPopover.jsx
│   │   │   │   │   │   │   │       ├── LinePopover.jsx
│   │   │   │   │   │   │   │       ├── ShapePopover.jsx
│   │   │   │   │   │   │   │       └── TypePopover.jsx
│   │   │   │   │   │   │   ├── SubmissionWorkflowState.tsx
│   │   │   │   │   │   │   ├── TextResponseSolutions.jsx
│   │   │   │   │   │   │   ├── WarningDialog.tsx
│   │   │   │   │   │   │   ├── answers/
│   │   │   │   │   │   │   │   ├── Answer.tsx
│   │   │   │   │   │   │   │   ├── AnswerHeader.tsx
│   │   │   │   │   │   │   │   ├── AnswerNotImplemented.tsx
│   │   │   │   │   │   │   │   ├── FileUpload/
│   │   │   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   │   │   ├── ForumPostResponse/
│   │   │   │   │   │   │   │   │   ├── CardTitle.jsx
│   │   │   │   │   │   │   │   │   ├── Error.jsx
│   │   │   │   │   │   │   │   │   ├── ForumCard.jsx
│   │   │   │   │   │   │   │   │   ├── ForumPost.jsx
│   │   │   │   │   │   │   │   │   ├── ForumPostOption.jsx
│   │   │   │   │   │   │   │   │   ├── ForumPostSelect.jsx
│   │   │   │   │   │   │   │   │   ├── ForumPostSelectDialog.jsx
│   │   │   │   │   │   │   │   │   ├── Labels.jsx
│   │   │   │   │   │   │   │   │   ├── ParentPost.jsx
│   │   │   │   │   │   │   │   │   ├── SelectedPostCard.jsx
│   │   │   │   │   │   │   │   │   ├── TopicCard.jsx
│   │   │   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   │   │   ├── MultipleChoice/
│   │   │   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   │   │   ├── MultipleResponse/
│   │   │   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   │   │   ├── Programming/
│   │   │   │   │   │   │   │   │   ├── ProgrammingFile.tsx
│   │   │   │   │   │   │   │   │   ├── ProgrammingFileDownloadChip.tsx
│   │   │   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   │   │   └── ProgrammingFile.test.tsx
│   │   │   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   │   │   ├── RubricBasedResponse/
│   │   │   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   │   │   ├── TextResponse/
│   │   │   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   │   │   ├── adapters/
│   │   │   │   │   │   │   │   │   ├── FileUploadAdapter.tsx
│   │   │   │   │   │   │   │   │   ├── ForumPostResponseAdapter.tsx
│   │   │   │   │   │   │   │   │   ├── MultipleChoiceAdapter.tsx
│   │   │   │   │   │   │   │   │   ├── MultipleResponseAdapter.tsx
│   │   │   │   │   │   │   │   │   ├── ProgrammingAdapter.tsx
│   │   │   │   │   │   │   │   │   ├── RubricBasedResponseAdapter.tsx
│   │   │   │   │   │   │   │   │   ├── ScribingAdapter.tsx
│   │   │   │   │   │   │   │   │   ├── TextResponseAdapter.tsx
│   │   │   │   │   │   │   │   │   └── VoiceResponseAdapter.tsx
│   │   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   │   ├── types.ts
│   │   │   │   │   │   │   │   └── utils.tsx
│   │   │   │   │   │   │   └── comment/
│   │   │   │   │   │   │       ├── CodaveriCommentCard.jsx
│   │   │   │   │   │   │       ├── CommentCard.jsx
│   │   │   │   │   │   │       └── CommentField.jsx
│   │   │   │   │   │   ├── constants.ts
│   │   │   │   │   │   ├── containers/
│   │   │   │   │   │   │   ├── Annotations.jsx
│   │   │   │   │   │   │   ├── CodaveriFeedbackStatus.jsx
│   │   │   │   │   │   │   ├── Comments.jsx
│   │   │   │   │   │   │   ├── GradingPanel.jsx
│   │   │   │   │   │   │   ├── PostPreview.tsx
│   │   │   │   │   │   │   ├── ProgrammingImport/
│   │   │   │   │   │   │   │   ├── ImportedFileView.jsx
│   │   │   │   │   │   │   │   ├── ProgrammingImportEditor.jsx
│   │   │   │   │   │   │   │   └── ProgrammingImportHistoryView.jsx
│   │   │   │   │   │   │   ├── QuestionGrade.tsx
│   │   │   │   │   │   │   ├── ReadOnlyEditor.jsx
│   │   │   │   │   │   │   ├── RubricExplanation.tsx
│   │   │   │   │   │   │   ├── RubricGrade.tsx
│   │   │   │   │   │   │   ├── RubricPanel.tsx
│   │   │   │   │   │   │   ├── RubricPanelRow.tsx
│   │   │   │   │   │   │   ├── ScribingView.jsx
│   │   │   │   │   │   │   ├── TestCaseView/
│   │   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   │   └── index.test.js
│   │   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   │   ├── UploadedFileView.jsx
│   │   │   │   │   │   │   └── VoiceResponseAnswer.jsx
│   │   │   │   │   │   ├── localStorage/
│   │   │   │   │   │   │   └── liveFeedbackChat/
│   │   │   │   │   │   │       └── operations.ts
│   │   │   │   │   │   ├── pages/
│   │   │   │   │   │   │   ├── LogsIndex/
│   │   │   │   │   │   │   │   ├── LogsContent.tsx
│   │   │   │   │   │   │   │   ├── LogsHead.tsx
│   │   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   │   └── translations.ts
│   │   │   │   │   │   │   ├── SubmissionEditIndex/
│   │   │   │   │   │   │   │   ├── BlockedSubmission.tsx
│   │   │   │   │   │   │   │   ├── ErrorHelper.tsx
│   │   │   │   │   │   │   │   ├── SubmissionEmptyForm.tsx
│   │   │   │   │   │   │   │   ├── SubmissionForm.tsx
│   │   │   │   │   │   │   │   ├── TimeLimitBanner.tsx
│   │   │   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   │   │   ├── ActionButtonsRow.tsx
│   │   │   │   │   │   │   │   │   ├── AutogradingErrorPanel.tsx
│   │   │   │   │   │   │   │   │   ├── ErrorMessages.tsx
│   │   │   │   │   │   │   │   │   ├── ExplanationPanel.tsx
│   │   │   │   │   │   │   │   │   ├── QuestionContent.tsx
│   │   │   │   │   │   │   │   │   ├── SinglePageQuestions.tsx
│   │   │   │   │   │   │   │   │   ├── TabbedViewQuestions.tsx
│   │   │   │   │   │   │   │   │   └── button/
│   │   │   │   │   │   │   │   │       ├── AutogradeSubmissionButton.tsx
│   │   │   │   │   │   │   │   │       ├── ContinueButton.tsx
│   │   │   │   │   │   │   │   │       ├── FinaliseButton.tsx
│   │   │   │   │   │   │   │   │       ├── LiveFeedbackButton.tsx
│   │   │   │   │   │   │   │   │       ├── MarkButton.tsx
│   │   │   │   │   │   │   │   │       ├── PublishButton.tsx
│   │   │   │   │   │   │   │   │       ├── ReevaluateButton.tsx
│   │   │   │   │   │   │   │   │       ├── ResetAnswerButton.tsx
│   │   │   │   │   │   │   │   │       ├── SaveDraftButton.tsx
│   │   │   │   │   │   │   │   │       ├── SaveGradeButton.tsx
│   │   │   │   │   │   │   │   │       ├── StepperButton.tsx
│   │   │   │   │   │   │   │   │       ├── SubmitButton.tsx
│   │   │   │   │   │   │   │   │       ├── SubmitEmptyFormButton.tsx
│   │   │   │   │   │   │   │   │       ├── UnmarkButton.tsx
│   │   │   │   │   │   │   │   │       └── UnsubmitButton.tsx
│   │   │   │   │   │   │   │   ├── index.jsx
│   │   │   │   │   │   │   │   ├── useErrorTranslation.ts
│   │   │   │   │   │   │   │   └── validations/
│   │   │   │   │   │   │   │       ├── AllValidation.tsx
│   │   │   │   │   │   │   │       ├── AttachmentValidation.tsx
│   │   │   │   │   │   │   │       └── types.ts
│   │   │   │   │   │   │   └── SubmissionsIndex/
│   │   │   │   │   │   │       ├── SubmissionsTable.jsx
│   │   │   │   │   │   │       ├── SubmissionsTableRow.jsx
│   │   │   │   │   │   │       ├── __test__/
│   │   │   │   │   │   │       │   └── submissionsTable.test.jsx
│   │   │   │   │   │   │       ├── index.tsx
│   │   │   │   │   │   │       └── translations.js
│   │   │   │   │   │   ├── propTypes.js
│   │   │   │   │   │   ├── reducers/
│   │   │   │   │   │   │   ├── annotations.js
│   │   │   │   │   │   │   ├── answerFlags/
│   │   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   │   ├── answers.js
│   │   │   │   │   │   │   ├── assessment.js
│   │   │   │   │   │   │   ├── attachments.js
│   │   │   │   │   │   │   ├── codaveriFeedbackStatus.js
│   │   │   │   │   │   │   ├── commentForms.js
│   │   │   │   │   │   │   ├── explanations.js
│   │   │   │   │   │   │   ├── grading/
│   │   │   │   │   │   │   │   ├── index.js
│   │   │   │   │   │   │   │   └── types.ts
│   │   │   │   │   │   │   ├── history/
│   │   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   │   ├── index.js
│   │   │   │   │   │   │   ├── liveFeedbackChats/
│   │   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   │   ├── posts.js
│   │   │   │   │   │   │   ├── questions.js
│   │   │   │   │   │   │   ├── questionsFlags.js
│   │   │   │   │   │   │   ├── recorder.js
│   │   │   │   │   │   │   ├── scribing/
│   │   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   │   ├── submission.js
│   │   │   │   │   │   │   ├── submissionFlags.js
│   │   │   │   │   │   │   ├── submissions.js
│   │   │   │   │   │   │   ├── testCases.js
│   │   │   │   │   │   │   └── topics.js
│   │   │   │   │   │   ├── selectors/
│   │   │   │   │   │   │   ├── answerFlags.ts
│   │   │   │   │   │   │   ├── answers.ts
│   │   │   │   │   │   │   ├── assessments.ts
│   │   │   │   │   │   │   ├── attachments.ts
│   │   │   │   │   │   │   ├── codaveriFeedbackStatus.ts
│   │   │   │   │   │   │   ├── comments.ts
│   │   │   │   │   │   │   ├── explanations.ts
│   │   │   │   │   │   │   ├── grading.ts
│   │   │   │   │   │   │   ├── history.ts
│   │   │   │   │   │   │   ├── liveFeedbackChats.ts
│   │   │   │   │   │   │   ├── questionFlags.ts
│   │   │   │   │   │   │   ├── questions.ts
│   │   │   │   │   │   │   ├── submissionFlags.ts
│   │   │   │   │   │   │   ├── submissions.ts
│   │   │   │   │   │   │   └── topics.ts
│   │   │   │   │   │   ├── suggestionTranslations.ts
│   │   │   │   │   │   ├── translations.ts
│   │   │   │   │   │   ├── types.ts
│   │   │   │   │   │   └── utils/
│   │   │   │   │   │       ├── answers.ts
│   │   │   │   │   │       ├── rubrics.ts
│   │   │   │   │   │       └── timer.ts
│   │   │   │   │   ├── submissions/
│   │   │   │   │   │   ├── SubmissionsIndex.tsx
│   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   ├── buttons/
│   │   │   │   │   │   │   │   └── SubmissionsTableButton.tsx
│   │   │   │   │   │   │   ├── misc/
│   │   │   │   │   │   │   │   ├── SubmissionFilter.tsx
│   │   │   │   │   │   │   │   └── SubmissionTabs.tsx
│   │   │   │   │   │   │   └── tables/
│   │   │   │   │   │   │       └── SubmissionsTable.tsx
│   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   ├── selectors.ts
│   │   │   │   │   │   ├── store.ts
│   │   │   │   │   │   └── types.ts
│   │   │   │   │   ├── translations.ts
│   │   │   │   │   └── utils/
│   │   │   │   │       ├── __test__/
│   │   │   │   │       │   └── index.test.js
│   │   │   │   │       ├── index.js
│   │   │   │   │       └── recorderHelper.js
│   │   │   │   ├── container/
│   │   │   │   │   ├── Breadcrumbs/
│   │   │   │   │   │   ├── Breadcrumbs.tsx
│   │   │   │   │   │   ├── Crumb.tsx
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   └── sliders.tsx
│   │   │   │   │   ├── CourseContainer.tsx
│   │   │   │   │   ├── CourseLoader.ts
│   │   │   │   │   ├── Sidebar/
│   │   │   │   │   │   ├── CourseItem.tsx
│   │   │   │   │   │   ├── CourseUserItem.tsx
│   │   │   │   │   │   ├── CourseUserProgress.tsx
│   │   │   │   │   │   ├── LevelRing.tsx
│   │   │   │   │   │   ├── PinSidebarButton.tsx
│   │   │   │   │   │   ├── Sidebar.tsx
│   │   │   │   │   │   ├── SidebarAccordion.tsx
│   │   │   │   │   │   ├── SidebarContainer.tsx
│   │   │   │   │   │   ├── SidebarItem.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   └── unread.ts
│   │   │   │   ├── courses/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── buttons/
│   │   │   │   │   │   │   ├── TodoAccessButton.tsx
│   │   │   │   │   │   │   └── TodoIgnoreButton.tsx
│   │   │   │   │   │   ├── forms/
│   │   │   │   │   │   │   ├── CourseInvitationCodeForm.tsx
│   │   │   │   │   │   │   └── NewCourseForm.tsx
│   │   │   │   │   │   ├── misc/
│   │   │   │   │   │   │   ├── CourseAnnouncements.tsx
│   │   │   │   │   │   │   ├── CourseDisplay.tsx
│   │   │   │   │   │   │   ├── CourseEnrolOptions.tsx
│   │   │   │   │   │   │   ├── CourseInfoBox.tsx
│   │   │   │   │   │   │   ├── CourseNotifications.tsx
│   │   │   │   │   │   │   ├── CourseSuspendedAlert.tsx
│   │   │   │   │   │   │   └── NotificationCard.tsx
│   │   │   │   │   │   └── tables/
│   │   │   │   │   │       └── PendingTodosTable.tsx
│   │   │   │   │   ├── operations.ts
│   │   │   │   │   ├── pages/
│   │   │   │   │   │   ├── CourseShow/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── CoursesIndex/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   └── CoursesNew/
│   │   │   │   │   │       └── index.tsx
│   │   │   │   │   ├── selectors.ts
│   │   │   │   │   ├── store.ts
│   │   │   │   │   └── types.ts
│   │   │   │   ├── discussion/
│   │   │   │   │   └── topics/
│   │   │   │   │       ├── components/
│   │   │   │   │       │   ├── cards/
│   │   │   │   │       │   │   ├── CodaveriCommentCard.tsx
│   │   │   │   │       │   │   ├── CommentCard.tsx
│   │   │   │   │       │   │   └── TopicCard.tsx
│   │   │   │   │       │   ├── fields/
│   │   │   │   │       │   │   └── CommentField.tsx
│   │   │   │   │       │   └── lists/
│   │   │   │   │       │       └── TopicList.tsx
│   │   │   │   │       ├── handles.ts
│   │   │   │   │       ├── operations.ts
│   │   │   │   │       ├── pages/
│   │   │   │   │       │   └── CommentIndex/
│   │   │   │   │       │       └── index.tsx
│   │   │   │   │       ├── selectors.ts
│   │   │   │   │       ├── store.ts
│   │   │   │   │       └── types.ts
│   │   │   │   ├── duplication/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── BulkSelectors.jsx
│   │   │   │   │   │   ├── CourseDropdownMenu.jsx
│   │   │   │   │   │   ├── IndentedCheckbox.jsx
│   │   │   │   │   │   ├── TypeBadge/
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   └── UnpublishedIcon.jsx
│   │   │   │   │   ├── constants.js
│   │   │   │   │   ├── operations.js
│   │   │   │   │   ├── pages/
│   │   │   │   │   │   └── Duplication/
│   │   │   │   │   │       ├── DestinationCourseSelector/
│   │   │   │   │   │       │   ├── InstanceDropdown.tsx
│   │   │   │   │   │       │   ├── NewCourseForm.jsx
│   │   │   │   │   │       │   └── index.jsx
│   │   │   │   │   │       ├── DuplicateAllButton.jsx
│   │   │   │   │   │       ├── DuplicateButton.jsx
│   │   │   │   │   │       ├── DuplicateItemsConfirmation/
│   │   │   │   │   │       │   ├── AchievementsListing.jsx
│   │   │   │   │   │       │   ├── AssessmentsListing.jsx
│   │   │   │   │   │       │   ├── MaterialsListing.jsx
│   │   │   │   │   │       │   ├── SurveyListing.jsx
│   │   │   │   │   │       │   ├── VideosListing.jsx
│   │   │   │   │   │       │   └── index.jsx
│   │   │   │   │   │       ├── ItemsSelector/
│   │   │   │   │   │       │   ├── AchievementsSelector.jsx
│   │   │   │   │   │       │   ├── AssessmentsSelector.jsx
│   │   │   │   │   │       │   ├── MaterialsSelector.jsx
│   │   │   │   │   │       │   ├── SurveysSelector.jsx
│   │   │   │   │   │       │   ├── VideosSelector.jsx
│   │   │   │   │   │       │   └── index.jsx
│   │   │   │   │   │       ├── ItemsSelectorMenu/
│   │   │   │   │   │       │   └── index.jsx
│   │   │   │   │   │       ├── __test__/
│   │   │   │   │   │       │   ├── DuplicateButton.test.tsx
│   │   │   │   │   │       │   └── ObjectDuplication.test.jsx
│   │   │   │   │   │       └── index.jsx
│   │   │   │   │   ├── propTypes.js
│   │   │   │   │   ├── selectors/
│   │   │   │   │   │   ├── destinationCourse.js
│   │   │   │   │   │   └── destinationInstance.ts
│   │   │   │   │   ├── store.js
│   │   │   │   │   └── utils.js
│   │   │   │   ├── enrol-requests/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── buttons/
│   │   │   │   │   │   │   └── PendingEnrolRequestsButtons.tsx
│   │   │   │   │   │   └── tables/
│   │   │   │   │   │       └── EnrolRequestsTable.tsx
│   │   │   │   │   ├── operations.ts
│   │   │   │   │   ├── pages/
│   │   │   │   │   │   └── UserRequests/
│   │   │   │   │   │       └── index.tsx
│   │   │   │   │   ├── selectors.ts
│   │   │   │   │   ├── store.ts
│   │   │   │   │   └── types.ts
│   │   │   │   ├── experience-points/
│   │   │   │   │   ├── ExperiencePointsDetails.tsx
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── ExperiencePointsDownload.tsx
│   │   │   │   │   │   ├── ExperiencePointsFiltering.tsx
│   │   │   │   │   │   ├── ExperiencePointsNumberField.tsx
│   │   │   │   │   │   ├── ExperiencePointsReasonField.tsx
│   │   │   │   │   │   ├── ExperiencePointsTable.tsx
│   │   │   │   │   │   └── ExperiencePointsTableRow.tsx
│   │   │   │   │   ├── disbursement/
│   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   ├── buttons/
│   │   │   │   │   │   │   │   ├── DuplicateButton.tsx
│   │   │   │   │   │   │   │   └── RemoveAllButton.tsx
│   │   │   │   │   │   │   ├── fields/
│   │   │   │   │   │   │   │   └── PointField.tsx
│   │   │   │   │   │   │   ├── forms/
│   │   │   │   │   │   │   │   ├── DisbursementForm.tsx
│   │   │   │   │   │   │   │   ├── FilterForm.tsx
│   │   │   │   │   │   │   │   └── ForumDisbursementForm.tsx
│   │   │   │   │   │   │   └── tables/
│   │   │   │   │   │   │       ├── DisbursementTable.tsx
│   │   │   │   │   │   │       ├── ForumDisbursementTable.tsx
│   │   │   │   │   │   │       └── ForumPostTable.tsx
│   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   ├── pages/
│   │   │   │   │   │   │   ├── ForumDisbursement/
│   │   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   │   └── GeneralDisbursement/
│   │   │   │   │   │   │       └── index.tsx
│   │   │   │   │   │   ├── selectors.ts
│   │   │   │   │   │   ├── store.ts
│   │   │   │   │   │   └── types.ts
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   ├── operations.ts
│   │   │   │   │   ├── selectors.ts
│   │   │   │   │   └── store.ts
│   │   │   │   ├── forum/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── buttons/
│   │   │   │   │   │   │   ├── ForumManagementButtons.tsx
│   │   │   │   │   │   │   ├── ForumTopicManagementButtons.tsx
│   │   │   │   │   │   │   ├── ForumTopicPostEditActionButtons.tsx
│   │   │   │   │   │   │   ├── ForumTopicPostManagementButtons.tsx
│   │   │   │   │   │   │   ├── GenerateReplyButton.tsx
│   │   │   │   │   │   │   ├── HideButton.tsx
│   │   │   │   │   │   │   ├── LockButton.tsx
│   │   │   │   │   │   │   ├── MarkAllAsReadButton.tsx
│   │   │   │   │   │   │   ├── MarkAnswerAndPublishButton.tsx
│   │   │   │   │   │   │   ├── MarkAnswerButton.tsx
│   │   │   │   │   │   │   ├── NextUnreadButton.tsx
│   │   │   │   │   │   │   ├── ReplyButton.tsx
│   │   │   │   │   │   │   ├── SubscribeButton.tsx
│   │   │   │   │   │   │   └── VotePostButton.tsx
│   │   │   │   │   │   ├── cards/
│   │   │   │   │   │   │   ├── PostCard.tsx
│   │   │   │   │   │   │   └── ReplyCard.tsx
│   │   │   │   │   │   ├── forms/
│   │   │   │   │   │   │   ├── ForumForm.tsx
│   │   │   │   │   │   │   ├── ForumTopicForm.tsx
│   │   │   │   │   │   │   └── ForumTopicPostForm.tsx
│   │   │   │   │   │   ├── misc/
│   │   │   │   │   │   │   └── PostCreatorObject.tsx
│   │   │   │   │   │   └── tables/
│   │   │   │   │   │       ├── ForumTable.tsx
│   │   │   │   │   │       └── ForumTopicTable.tsx
│   │   │   │   │   ├── handles.ts
│   │   │   │   │   ├── operations.ts
│   │   │   │   │   ├── pages/
│   │   │   │   │   │   ├── ForumEdit/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── ForumNew/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── ForumShow/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── ForumTopicEdit/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── ForumTopicNew/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── ForumTopicPostNew/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── ForumTopicShow/
│   │   │   │   │   │   │   ├── TopicPostTrees.tsx
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   └── ForumsIndex/
│   │   │   │   │   │       └── index.tsx
│   │   │   │   │   ├── selectors.ts
│   │   │   │   │   ├── store.ts
│   │   │   │   │   ├── translations.ts
│   │   │   │   │   └── types.ts
│   │   │   │   ├── group/
│   │   │   │   │   ├── actions/
│   │   │   │   │   │   ├── categories.js
│   │   │   │   │   │   ├── general.js
│   │   │   │   │   │   ├── groups.js
│   │   │   │   │   │   └── index.js
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── GroupCard.tsx
│   │   │   │   │   │   └── GroupRoleChip.tsx
│   │   │   │   │   ├── constants.js
│   │   │   │   │   ├── forms/
│   │   │   │   │   │   ├── GroupCreationForm.jsx
│   │   │   │   │   │   ├── GroupFormDialog.jsx
│   │   │   │   │   │   └── NameDescriptionForm.jsx
│   │   │   │   │   ├── pages/
│   │   │   │   │   │   ├── GroupIndex/
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── GroupNew/
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   └── GroupShow/
│   │   │   │   │   │       ├── CategoryCard.tsx
│   │   │   │   │   │       ├── GroupManager/
│   │   │   │   │   │       │   ├── ChangeSummaryTable.jsx
│   │   │   │   │   │       │   ├── GroupManager.jsx
│   │   │   │   │   │       │   ├── GroupUserManager.jsx
│   │   │   │   │   │       │   ├── GroupUserManagerList.jsx
│   │   │   │   │   │       │   └── index.js
│   │   │   │   │   │       ├── GroupTableCard.tsx
│   │   │   │   │   │       └── index.jsx
│   │   │   │   │   ├── propTypes.js
│   │   │   │   │   ├── reducers/
│   │   │   │   │   │   ├── groupsDialog.js
│   │   │   │   │   │   ├── groupsFetch.js
│   │   │   │   │   │   └── groupsManage.js
│   │   │   │   │   ├── store.ts
│   │   │   │   │   ├── types.ts
│   │   │   │   │   └── utils/
│   │   │   │   │       ├── groups.js
│   │   │   │   │       └── sort.js
│   │   │   │   ├── helper/
│   │   │   │   │   ├── achievements.ts
│   │   │   │   │   └── index.ts
│   │   │   │   ├── leaderboard/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   └── tables/
│   │   │   │   │   │       └── LeaderboardTable.tsx
│   │   │   │   │   ├── handles.ts
│   │   │   │   │   ├── operations.ts
│   │   │   │   │   ├── pages/
│   │   │   │   │   │   └── LeaderboardIndex/
│   │   │   │   │   │       └── index.tsx
│   │   │   │   │   ├── selectors.ts
│   │   │   │   │   ├── store.ts
│   │   │   │   │   └── types.ts
│   │   │   │   ├── learning-map/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── ConnectionPoint/
│   │   │   │   │   │   │   ├── ConnectionPoint.scss
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── Gate/
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── Node/
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── NodeMenu/
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── UnlockRateDisplay/
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   └── ZoomActionElements/
│   │   │   │   │   │       └── index.jsx
│   │   │   │   │   ├── constants.js
│   │   │   │   │   ├── containers/
│   │   │   │   │   │   ├── ArrowOverlay/
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── Canvas/
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── Dashboard/
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── GateToNodeArrows/
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── LearningMap/
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── Levels/
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   └── NodeToGateArrows/
│   │   │   │   │   │       └── index.jsx
│   │   │   │   │   ├── operations.ts
│   │   │   │   │   ├── propTypes.js
│   │   │   │   │   ├── store.ts
│   │   │   │   │   ├── translations.ts
│   │   │   │   │   └── types.ts
│   │   │   │   ├── lesson-plan/
│   │   │   │   │   ├── constants.js
│   │   │   │   │   ├── containers/
│   │   │   │   │   │   ├── ColumnVisibilityDropdown/
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── EventFormDialog/
│   │   │   │   │   │   │   ├── EventForm.jsx
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── LessonPlanFilter/
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── LessonPlanLayout/
│   │   │   │   │   │   │   ├── EnterEditModeButton.jsx
│   │   │   │   │   │   │   ├── NewEventButton.jsx
│   │   │   │   │   │   │   ├── NewMilestoneButton.jsx
│   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   ├── NewEventButton.test.jsx
│   │   │   │   │   │   │   │   ├── NewMilestoneButton.test.jsx
│   │   │   │   │   │   │   │   └── index.test.jsx
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── LessonPlanNav/
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── MilestoneFormDialog/
│   │   │   │   │   │   │   ├── MilestoneForm.jsx
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   └── TranslatedItemType.tsx
│   │   │   │   │   ├── operations.ts
│   │   │   │   │   ├── pages/
│   │   │   │   │   │   ├── LessonPlanEdit/
│   │   │   │   │   │   │   ├── ItemRow/
│   │   │   │   │   │   │   │   ├── DateCell.jsx
│   │   │   │   │   │   │   │   ├── PublishedCell.jsx
│   │   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   │   ├── MilestoneRow.jsx
│   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   ├── ItemRow.test.jsx
│   │   │   │   │   │   │   │   ├── MilestoneRow.test.jsx
│   │   │   │   │   │   │   │   └── index.test.jsx
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   └── LessonPlanShow/
│   │   │   │   │   │       ├── LessonPlanGroup.jsx
│   │   │   │   │   │       ├── LessonPlanItem/
│   │   │   │   │   │       │   ├── AdminTools.jsx
│   │   │   │   │   │       │   ├── Details/
│   │   │   │   │   │       │   │   ├── Chips.jsx
│   │   │   │   │   │       │   │   └── index.jsx
│   │   │   │   │   │       │   ├── Material.jsx
│   │   │   │   │   │       │   ├── __test__/
│   │   │   │   │   │       │   │   └── AdminTools.test.jsx
│   │   │   │   │   │       │   └── index.jsx
│   │   │   │   │   │       ├── MilestoneAdminTools.jsx
│   │   │   │   │   │       ├── __test__/
│   │   │   │   │   │       │   ├── LessonPlanShow.test.jsx
│   │   │   │   │   │       │   └── MilestoneAdminTools.test.jsx
│   │   │   │   │   │       └── index.jsx
│   │   │   │   │   ├── reducers/
│   │   │   │   │   │   ├── eventForm.js
│   │   │   │   │   │   ├── flags.js
│   │   │   │   │   │   ├── lessonPlan.js
│   │   │   │   │   │   ├── milestoneForm.js
│   │   │   │   │   │   └── utils.js
│   │   │   │   │   ├── store.ts
│   │   │   │   │   └── translations.ts
│   │   │   │   ├── level/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── LevelsTable.tsx
│   │   │   │   │   │   └── LevelsTableRow.tsx
│   │   │   │   │   ├── operations.ts
│   │   │   │   │   ├── pages/
│   │   │   │   │   │   └── LevelsIndex/
│   │   │   │   │   │       ├── LevelsManager.tsx
│   │   │   │   │   │       └── index.tsx
│   │   │   │   │   ├── selector.ts
│   │   │   │   │   ├── store.ts
│   │   │   │   │   └── types.ts
│   │   │   │   ├── material/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   └── MaterialStatusPage.tsx
│   │   │   │   │   ├── files/
│   │   │   │   │   │   ├── DownloadingFilePage.tsx
│   │   │   │   │   │   └── ErrorRetrievingFilePage.tsx
│   │   │   │   │   ├── folders/
│   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   ├── buttons/
│   │   │   │   │   │   │   │   ├── DownloadFolderButton.tsx
│   │   │   │   │   │   │   │   ├── KnowledgeBaseSwitch.tsx
│   │   │   │   │   │   │   │   ├── NewSubfolderButton.tsx
│   │   │   │   │   │   │   │   ├── UploadFilesButton.tsx
│   │   │   │   │   │   │   │   └── WorkbinTableButtons.tsx
│   │   │   │   │   │   │   ├── forms/
│   │   │   │   │   │   │   │   ├── FolderForm.tsx
│   │   │   │   │   │   │   │   ├── MaterialForm.tsx
│   │   │   │   │   │   │   │   └── MaterialUploadForm.tsx
│   │   │   │   │   │   │   ├── misc/
│   │   │   │   │   │   │   │   ├── MaterialEdit.tsx
│   │   │   │   │   │   │   │   ├── MaterialUpload.tsx
│   │   │   │   │   │   │   │   └── MultipleFileInput.tsx
│   │   │   │   │   │   │   └── tables/
│   │   │   │   │   │   │       ├── TableMaterialRow.tsx
│   │   │   │   │   │   │       ├── TableSubfolderRow.tsx
│   │   │   │   │   │   │       └── WorkbinTable.tsx
│   │   │   │   │   │   ├── handles.ts
│   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   ├── pages/
│   │   │   │   │   │   │   ├── ErrorRetrievingFolderPage.tsx
│   │   │   │   │   │   │   ├── FolderEdit/
│   │   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   │   ├── FolderNew/
│   │   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   │   └── FolderShow/
│   │   │   │   │   │   │       └── index.tsx
│   │   │   │   │   │   ├── selectors.ts
│   │   │   │   │   │   ├── store.ts
│   │   │   │   │   │   └── types.ts
│   │   │   │   │   └── materialLoader.ts
│   │   │   │   ├── plagiarism/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── AssessmentLinkDialog.tsx
│   │   │   │   │   │   └── AssessmentLinkList.tsx
│   │   │   │   │   ├── constants.ts
│   │   │   │   │   ├── operations.ts
│   │   │   │   │   ├── pages/
│   │   │   │   │   │   └── PlagiarismIndex/
│   │   │   │   │   │       ├── assessments/
│   │   │   │   │   │       │   └── AssessmentsPlagiarismTable.tsx
│   │   │   │   │   │       └── index.tsx
│   │   │   │   │   ├── reducers/
│   │   │   │   │   │   └── assessments.ts
│   │   │   │   │   ├── selectors.ts
│   │   │   │   │   └── store.ts
│   │   │   │   ├── reference-timelines/
│   │   │   │   │   ├── TimelineDesigner.tsx
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── CreateRenameTimelinePrompt.tsx
│   │   │   │   │   │   ├── DayCalendar/
│   │   │   │   │   │   │   ├── DayCalendar.tsx
│   │   │   │   │   │   │   ├── DayColumn.tsx
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   ├── DeleteTimelinePrompt.tsx
│   │   │   │   │   │   ├── HorizontallyDraggable.tsx
│   │   │   │   │   │   ├── HorizontallyResizable.tsx
│   │   │   │   │   │   ├── SeriouslyAnchoredPopup.tsx
│   │   │   │   │   │   ├── SubmitIndicator.tsx
│   │   │   │   │   │   ├── TimeBar/
│   │   │   │   │   │   │   ├── DurationBar.tsx
│   │   │   │   │   │   │   ├── TimeBar.tsx
│   │   │   │   │   │   │   ├── TimeBarHandle.tsx
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   ├── TimePopup/
│   │   │   │   │   │   │   ├── TimePopup.tsx
│   │   │   │   │   │   │   ├── TimePopupForm.tsx
│   │   │   │   │   │   │   ├── TimePopupTopBar.tsx
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   ├── TimelinesOverview/
│   │   │   │   │   │   │   ├── TimelinesOverview.tsx
│   │   │   │   │   │   │   ├── TimelinesOverviewItem.tsx
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   └── TimelinesStack/
│   │   │   │   │   │       ├── AssignableTimeline.tsx
│   │   │   │   │   │       ├── AssignedTimeline.tsx
│   │   │   │   │   │       ├── Timeline.tsx
│   │   │   │   │   │       ├── TimelinesStack.tsx
│   │   │   │   │   │       └── index.ts
│   │   │   │   │   ├── contexts/
│   │   │   │   │   │   ├── LastSavedContext.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── operations.ts
│   │   │   │   │   ├── selectors.ts
│   │   │   │   │   ├── store.ts
│   │   │   │   │   ├── translations.ts
│   │   │   │   │   ├── types.ts
│   │   │   │   │   ├── utils.ts
│   │   │   │   │   └── views/
│   │   │   │   │       └── DayView/
│   │   │   │   │           ├── DayView.tsx
│   │   │   │   │           ├── ItemsSidebar.tsx
│   │   │   │   │           ├── TimelineSidebarItem.tsx
│   │   │   │   │           └── index.ts
│   │   │   │   ├── scholaistic/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── ScholaisticAsyncContainer.tsx
│   │   │   │   │   │   ├── ScholaisticErrorPage.tsx
│   │   │   │   │   │   └── ScholaisticFramePage.tsx
│   │   │   │   │   ├── handles.ts
│   │   │   │   │   └── pages/
│   │   │   │   │       ├── ScholaisticAssessmentEdit/
│   │   │   │   │       │   ├── index.tsx
│   │   │   │   │       │   ├── loader.ts
│   │   │   │   │       │   └── operations.ts
│   │   │   │   │       ├── ScholaisticAssessmentNew/
│   │   │   │   │       │   ├── index.tsx
│   │   │   │   │       │   └── loader.ts
│   │   │   │   │       ├── ScholaisticAssessmentSubmissionEdit/
│   │   │   │   │       │   ├── index.tsx
│   │   │   │   │       │   └── loader.ts
│   │   │   │   │       ├── ScholaisticAssessmentSubmissionsIndex/
│   │   │   │   │       │   ├── index.tsx
│   │   │   │   │       │   └── loader.ts
│   │   │   │   │       ├── ScholaisticAssessmentView/
│   │   │   │   │       │   ├── index.tsx
│   │   │   │   │       │   └── loader.ts
│   │   │   │   │       ├── ScholaisticAssessmentsIndex/
│   │   │   │   │       │   ├── ActionButtons.tsx
│   │   │   │   │       │   ├── index.tsx
│   │   │   │   │       │   └── loader.ts
│   │   │   │   │       ├── ScholaisticAssistantEdit/
│   │   │   │   │       │   ├── index.tsx
│   │   │   │   │       │   └── loader.ts
│   │   │   │   │       └── ScholaisticAssistantsIndex/
│   │   │   │   │           ├── index.tsx
│   │   │   │   │           └── loader.ts
│   │   │   │   ├── statistics/
│   │   │   │   │   ├── handles.ts
│   │   │   │   │   ├── operations.ts
│   │   │   │   │   ├── pages/
│   │   │   │   │   │   └── StatisticsIndex/
│   │   │   │   │   │       ├── assessments/
│   │   │   │   │   │       │   ├── AssessmentsScoreSummaryDownload.tsx
│   │   │   │   │   │       │   ├── AssessmentsStatistics.tsx
│   │   │   │   │   │       │   └── AssessmentsStatisticsTable.tsx
│   │   │   │   │   │       ├── course/
│   │   │   │   │   │       │   ├── CourseStatistics.tsx
│   │   │   │   │   │       │   ├── StudentPerformanceTable.tsx
│   │   │   │   │   │       │   ├── StudentProgressionChart.tsx
│   │   │   │   │   │       │   └── utils.js
│   │   │   │   │   │       ├── get_help/
│   │   │   │   │   │       │   ├── CourseGetHelpFilter.tsx
│   │   │   │   │   │       │   ├── CourseGetHelpStatistics.tsx
│   │   │   │   │   │       │   └── CourseGetHelpStatisticsTable.tsx
│   │   │   │   │   │       ├── index.tsx
│   │   │   │   │   │       ├── staff/
│   │   │   │   │   │       │   ├── StaffStatistics.tsx
│   │   │   │   │   │       │   └── StaffStatisticsTable.tsx
│   │   │   │   │   │       └── students/
│   │   │   │   │   │           ├── StudentStatisticsTable.tsx
│   │   │   │   │   │           └── StudentsStatistics.tsx
│   │   │   │   │   ├── types.ts
│   │   │   │   │   └── utils/
│   │   │   │   │       ├── parseCourseResponse.js
│   │   │   │   │       ├── parseStaffResponse.js
│   │   │   │   │       └── parseStudentsResponse.js
│   │   │   │   ├── stories/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── CikgoChatsPage.tsx
│   │   │   │   │   │   ├── CikgoErrorPage.tsx
│   │   │   │   │   │   ├── CikgoFramePage.tsx
│   │   │   │   │   │   ├── CikgoSidebarItems.tsx
│   │   │   │   │   │   └── LearnRedirect.tsx
│   │   │   │   │   └── pages/
│   │   │   │   │       ├── LearnPage.tsx
│   │   │   │   │       └── MissionControlPage.tsx
│   │   │   │   ├── survey/
│   │   │   │   │   ├── __test__/
│   │   │   │   │   │   └── index.test.tsx
│   │   │   │   │   ├── actions/
│   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   └── responses.test.ts
│   │   │   │   │   │   ├── questions.js
│   │   │   │   │   │   ├── responses.js
│   │   │   │   │   │   ├── sections.js
│   │   │   │   │   │   └── surveys.js
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── Dialogs.jsx
│   │   │   │   │   │   └── OptionsListItem.jsx
│   │   │   │   │   ├── constants.js
│   │   │   │   │   ├── containers/
│   │   │   │   │   │   ├── QuestionFormDialogue/
│   │   │   │   │   │   │   ├── QuestionForm.jsx
│   │   │   │   │   │   │   ├── QuestionFormDeletedOptions.jsx
│   │   │   │   │   │   │   ├── QuestionFormOption.jsx
│   │   │   │   │   │   │   ├── QuestionFormOptions.jsx
│   │   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   │   └── ImageField.jsx
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── RespondButton/
│   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   └── index.test.jsx
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── ResponseForm/
│   │   │   │   │   │   │   ├── ResponseAnswer.jsx
│   │   │   │   │   │   │   ├── ResponseSection.jsx
│   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   └── index.test.jsx
│   │   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   │   ├── MultipleChoiceOptionsField.jsx
│   │   │   │   │   │   │   │   └── MultipleResponseOptionsField.jsx
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── SectionFormDialogue/
│   │   │   │   │   │   │   ├── SectionForm.jsx
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── SurveyFormDialogue/
│   │   │   │   │   │   │   ├── SurveyForm.jsx
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── SurveyLayout/
│   │   │   │   │   │   │   ├── AdminMenu.jsx
│   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   ├── AdminMenu.test.jsx
│   │   │   │   │   │   │   │   └── index.test.jsx
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   └── UnsubmitButton.jsx
│   │   │   │   │   ├── handles.ts
│   │   │   │   │   ├── pages/
│   │   │   │   │   │   ├── ResponseEdit/
│   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   └── index.test.jsx
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── ResponseIndex/
│   │   │   │   │   │   │   ├── RemindButton.jsx
│   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   ├── RemindButton.test.tsx
│   │   │   │   │   │   │   │   └── index.test.jsx
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   └── translations.js
│   │   │   │   │   │   ├── ResponseShow/
│   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   └── index.test.jsx
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── SurveyIndex/
│   │   │   │   │   │   │   ├── NewSurveyButton.jsx
│   │   │   │   │   │   │   ├── SurveyBadges.jsx
│   │   │   │   │   │   │   ├── SurveysTable.jsx
│   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   └── NewSurveyButton.test.jsx
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── SurveyResults/
│   │   │   │   │   │   │   ├── OptionsQuestionResults.jsx
│   │   │   │   │   │   │   ├── ResultsQuestion.jsx
│   │   │   │   │   │   │   ├── ResultsSection.jsx
│   │   │   │   │   │   │   ├── TextResponseResults.jsx
│   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   ├── ResultsQuestion.test.tsx
│   │   │   │   │   │   │   │   └── index.test.jsx
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   └── SurveyShow/
│   │   │   │   │   │       ├── DownloadResponsesButton.jsx
│   │   │   │   │   │       ├── NewSectionButton.jsx
│   │   │   │   │   │       ├── Section/
│   │   │   │   │   │       │   ├── DeleteSectionButton.jsx
│   │   │   │   │   │       │   ├── EditSectionButton.jsx
│   │   │   │   │   │       │   ├── MoveDownButton.jsx
│   │   │   │   │   │       │   ├── MoveUpButton.jsx
│   │   │   │   │   │       │   ├── NewQuestionButton.jsx
│   │   │   │   │   │       │   ├── Question.jsx
│   │   │   │   │   │       │   ├── QuestionCard.jsx
│   │   │   │   │   │       │   ├── __test__/
│   │   │   │   │   │       │   │   ├── DeleteSectionButton.test.tsx
│   │   │   │   │   │       │   │   ├── EditSectionButton.test.jsx
│   │   │   │   │   │       │   │   ├── MoveDownButton.test.tsx
│   │   │   │   │   │       │   │   ├── MoveUpButton.test.jsx
│   │   │   │   │   │       │   │   └── NewQuestionButton.test.jsx
│   │   │   │   │   │       │   └── index.jsx
│   │   │   │   │   │       ├── SurveyDetails.jsx
│   │   │   │   │   │       ├── __test__/
│   │   │   │   │   │       │   ├── DownloadResponsesButton.test.tsx
│   │   │   │   │   │       │   └── NewSectionButton.test.jsx
│   │   │   │   │   │       └── index.jsx
│   │   │   │   │   ├── propTypes.js
│   │   │   │   │   ├── reducers/
│   │   │   │   │   │   ├── questionForm.js
│   │   │   │   │   │   ├── responseForm.js
│   │   │   │   │   │   ├── responses.js
│   │   │   │   │   │   ├── results.js
│   │   │   │   │   │   ├── section.js
│   │   │   │   │   │   ├── sectionForm.js
│   │   │   │   │   │   ├── survey.js
│   │   │   │   │   │   ├── surveyForm.js
│   │   │   │   │   │   ├── surveys.js
│   │   │   │   │   │   └── surveysFlags.js
│   │   │   │   │   ├── store.ts
│   │   │   │   │   ├── translations.js
│   │   │   │   │   └── utils/
│   │   │   │   │       ├── __test__/
│   │   │   │   │       │   └── index.test.js
│   │   │   │   │       └── index.js
│   │   │   │   ├── translations.ts
│   │   │   │   ├── user-email-subscriptions/
│   │   │   │   │   ├── UserEmailSubscriptions.tsx
│   │   │   │   │   ├── UserEmailSubscriptionsTable.jsx
│   │   │   │   │   ├── __test__/
│   │   │   │   │   │   └── index.test.jsx
│   │   │   │   │   ├── constants.js
│   │   │   │   │   ├── operations.ts
│   │   │   │   │   ├── store.ts
│   │   │   │   │   ├── translations.ts
│   │   │   │   │   └── types.ts
│   │   │   │   ├── user-invitations/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── buttons/
│   │   │   │   │   │   │   ├── InvitationActionButtons.tsx
│   │   │   │   │   │   │   ├── RegistrationCodeButton.tsx
│   │   │   │   │   │   │   ├── ResendAllInvitationsButton.tsx
│   │   │   │   │   │   │   └── UploadFileButton.tsx
│   │   │   │   │   │   ├── forms/
│   │   │   │   │   │   │   ├── IndividualInvitation.tsx
│   │   │   │   │   │   │   ├── IndividualInvitations.tsx
│   │   │   │   │   │   │   ├── IndividualInviteForm.tsx
│   │   │   │   │   │   │   └── InviteUsersFileUploadForm.tsx
│   │   │   │   │   │   ├── misc/
│   │   │   │   │   │   │   ├── InvitationResultDialog.tsx
│   │   │   │   │   │   │   └── InvitationsBarChart.tsx
│   │   │   │   │   │   └── tables/
│   │   │   │   │   │       ├── InvitationResultInvitationsTable.tsx
│   │   │   │   │   │       ├── InvitationResultUsersTable.tsx
│   │   │   │   │   │       └── UserInvitationsTable.tsx
│   │   │   │   │   ├── operations.ts
│   │   │   │   │   ├── pages/
│   │   │   │   │   │   ├── InvitationsIndex/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── InviteUsers/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── InviteUsersFileUpload/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   └── InviteUsersRegistrationCode/
│   │   │   │   │   │       └── index.tsx
│   │   │   │   │   ├── selectors.ts
│   │   │   │   │   ├── store.ts
│   │   │   │   │   ├── translations.ts
│   │   │   │   │   └── types.ts
│   │   │   │   ├── user-notification/
│   │   │   │   │   ├── PopupNotifier.tsx
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── AchievementGainedPopup.tsx
│   │   │   │   │   │   ├── LevelReachedPopup.tsx
│   │   │   │   │   │   ├── PopupDialog.tsx
│   │   │   │   │   │   └── __test__/
│   │   │   │   │   │       └── LevelReachedPopup.test.tsx
│   │   │   │   │   ├── operations.ts
│   │   │   │   │   └── translations.ts
│   │   │   │   ├── users/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── buttons/
│   │   │   │   │   │   │   ├── PointManagementButtons.tsx
│   │   │   │   │   │   │   └── UserManagementButtons.tsx
│   │   │   │   │   │   ├── misc/
│   │   │   │   │   │   │   ├── PersonalTimeEditor.tsx
│   │   │   │   │   │   │   ├── SelectCourseUser.tsx
│   │   │   │   │   │   │   ├── UpgradeToStaff.tsx
│   │   │   │   │   │   │   ├── UserProfileAchievements.tsx
│   │   │   │   │   │   │   ├── UserProfileCard.scss
│   │   │   │   │   │   │   ├── UserProfileCard.tsx
│   │   │   │   │   │   │   ├── UserProfileCardStats.tsx
│   │   │   │   │   │   │   ├── UserProfileSkills.tsx
│   │   │   │   │   │   │   └── __test__/
│   │   │   │   │   │   │       └── UserProfileCard.test.tsx
│   │   │   │   │   │   ├── navigation/
│   │   │   │   │   │   │   └── UserManagementTabs.tsx
│   │   │   │   │   │   └── tables/
│   │   │   │   │   │       ├── ManageUsersTable/
│   │   │   │   │   │       │   ├── ActiveTableToolbar.tsx
│   │   │   │   │   │       │   ├── AlgorithmMenu.tsx
│   │   │   │   │   │       │   ├── BulkActionsButton.tsx
│   │   │   │   │   │       │   ├── BulkAssignTimelineMenu.tsx
│   │   │   │   │   │       │   ├── PhantomSwitch.tsx
│   │   │   │   │   │       │   ├── RoleMenu.tsx
│   │   │   │   │   │       │   ├── TimelineMenu.tsx
│   │   │   │   │   │       │   ├── UserNameField.tsx
│   │   │   │   │   │       │   └── index.tsx
│   │   │   │   │   │       └── PersonalTimesTable.tsx
│   │   │   │   │   ├── handles.ts
│   │   │   │   │   ├── operations.ts
│   │   │   │   │   ├── pages/
│   │   │   │   │   │   ├── ExperiencePointsRecords/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── ManageStaff/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── ManageStudents/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── PersonalTimes/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── PersonalTimesShow/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── UserShow/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── UserStatistics/
│   │   │   │   │   │   │   ├── LearningRateRecords/
│   │   │   │   │   │   │   │   ├── LearningRateRecordsChart.tsx
│   │   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   └── UsersIndex/
│   │   │   │   │   │       └── index.tsx
│   │   │   │   │   ├── selectors.ts
│   │   │   │   │   ├── store.ts
│   │   │   │   │   ├── translations.ts
│   │   │   │   │   └── types.ts
│   │   │   │   ├── video/
│   │   │   │   │   ├── attemptLoader.ts
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── buttons/
│   │   │   │   │   │   │   ├── VideoManagementButtons.tsx
│   │   │   │   │   │   │   └── WatchVideoButton.tsx
│   │   │   │   │   │   ├── forms/
│   │   │   │   │   │   │   └── VideoForm.tsx
│   │   │   │   │   │   ├── misc/
│   │   │   │   │   │   │   ├── VideoBadges.tsx
│   │   │   │   │   │   │   └── VideoTabs.tsx
│   │   │   │   │   │   └── tables/
│   │   │   │   │   │       └── VideoTable.tsx
│   │   │   │   │   ├── handles.ts
│   │   │   │   │   ├── operations.ts
│   │   │   │   │   ├── pages/
│   │   │   │   │   │   ├── VideoEdit/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── VideoNew/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── VideoShow/
│   │   │   │   │   │   │   ├── VideoDetails.tsx
│   │   │   │   │   │   │   ├── VideoPlayerWithStore.jsx
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   └── VideosIndex/
│   │   │   │   │   │       └── index.tsx
│   │   │   │   │   ├── selectors.ts
│   │   │   │   │   ├── store.ts
│   │   │   │   │   ├── submission/
│   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   └── store.test.js
│   │   │   │   │   │   ├── actions/
│   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   └── video.test.js
│   │   │   │   │   │   │   ├── discussion.js
│   │   │   │   │   │   │   └── video.js
│   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   └── tables/
│   │   │   │   │   │   │       └── VideoSubmissionsTable.tsx
│   │   │   │   │   │   ├── containers/
│   │   │   │   │   │   │   ├── Charts/
│   │   │   │   │   │   │   │   ├── HeatMap.jsx
│   │   │   │   │   │   │   │   └── ProgressGraph.jsx
│   │   │   │   │   │   │   ├── Discussion.jsx
│   │   │   │   │   │   │   ├── Discussion.scss
│   │   │   │   │   │   │   ├── DiscussionElements/
│   │   │   │   │   │   │   │   ├── Controls.jsx
│   │   │   │   │   │   │   │   ├── EditPostContainer.jsx
│   │   │   │   │   │   │   │   ├── Editor.jsx
│   │   │   │   │   │   │   │   ├── NewPostContainer.jsx
│   │   │   │   │   │   │   │   ├── NewReplyContainer.jsx
│   │   │   │   │   │   │   │   ├── PostContainer.jsx
│   │   │   │   │   │   │   │   ├── PostMenu.jsx
│   │   │   │   │   │   │   │   ├── PostPresentation.jsx
│   │   │   │   │   │   │   │   ├── Reply.jsx
│   │   │   │   │   │   │   │   └── Topic.jsx
│   │   │   │   │   │   │   ├── Statistics.jsx
│   │   │   │   │   │   │   ├── Statistics.scss
│   │   │   │   │   │   │   ├── Submission.jsx
│   │   │   │   │   │   │   ├── VideoControls/
│   │   │   │   │   │   │   │   ├── CaptionsButton.jsx
│   │   │   │   │   │   │   │   ├── NextVideoButton.jsx
│   │   │   │   │   │   │   │   ├── PlayBackRateSelector.jsx
│   │   │   │   │   │   │   │   ├── PlayButton.jsx
│   │   │   │   │   │   │   │   ├── VideoPlayerSlider.jsx
│   │   │   │   │   │   │   │   ├── VideoTimestamp.jsx
│   │   │   │   │   │   │   │   ├── VolumeButton.jsx
│   │   │   │   │   │   │   │   ├── VolumeSlider.jsx
│   │   │   │   │   │   │   │   └── index.js
│   │   │   │   │   │   │   ├── VideoPlayer.jsx
│   │   │   │   │   │   │   └── VideoPlayer.scss
│   │   │   │   │   │   ├── pages/
│   │   │   │   │   │   │   ├── VideoSubmissionEdit/
│   │   │   │   │   │   │   │   ├── SubmissionEditWithStore.jsx
│   │   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   │   ├── VideoSubmissionShow/
│   │   │   │   │   │   │   │   ├── StatisticsWithStore.jsx
│   │   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   │   └── VideoSubmissionsIndex/
│   │   │   │   │   │   │       └── index.tsx
│   │   │   │   │   │   ├── reducers/
│   │   │   │   │   │   │   ├── discussion.js
│   │   │   │   │   │   │   ├── index.js
│   │   │   │   │   │   │   ├── oldSessions.js
│   │   │   │   │   │   │   └── video.js
│   │   │   │   │   │   ├── selectors/
│   │   │   │   │   │   │   └── discussion.js
│   │   │   │   │   │   ├── store.js
│   │   │   │   │   │   └── translations.js
│   │   │   │   │   └── types.ts
│   │   │   │   └── video-submissions/
│   │   │   │       ├── components/
│   │   │   │       │   └── tables/
│   │   │   │       │       └── UserVideoSubmissionTable.tsx
│   │   │   │       ├── operations.ts
│   │   │   │       └── pages/
│   │   │   │           └── UserVideoSubmissionsIndex/
│   │   │   │               └── index.tsx
│   │   │   ├── system/
│   │   │   │   └── admin/
│   │   │   │       ├── admin/
│   │   │   │       │   ├── AdminNavigator.tsx
│   │   │   │       │   ├── components/
│   │   │   │       │   │   ├── buttons/
│   │   │   │       │   │   │   ├── CoursesButtons.tsx
│   │   │   │       │   │   │   ├── InstancesButtons.tsx
│   │   │   │       │   │   │   └── UsersButtons.tsx
│   │   │   │       │   │   ├── forms/
│   │   │   │       │   │   │   └── InstanceForm.tsx
│   │   │   │       │   │   ├── misc/
│   │   │   │       │   │   │   └── SystemGetHelpFilter.tsx
│   │   │   │       │   │   └── tables/
│   │   │   │       │   │       ├── CoursesTable.tsx
│   │   │   │       │   │       ├── InstancesTable/
│   │   │   │       │   │       │   ├── InstanceField.tsx
│   │   │   │       │   │       │   └── index.tsx
│   │   │   │       │   │       ├── SystemGetHelpActivityTable.tsx
│   │   │   │       │   │       └── UsersTable.tsx
│   │   │   │       │   ├── operations.ts
│   │   │   │       │   ├── pages/
│   │   │   │       │   │   ├── AnnouncementsIndex.tsx
│   │   │   │       │   │   ├── CoursesIndex.tsx
│   │   │   │       │   │   ├── InstanceNew.tsx
│   │   │   │       │   │   ├── InstancesIndex.tsx
│   │   │   │       │   │   ├── SystemGetHelpActivityIndex.tsx
│   │   │   │       │   │   └── UsersIndex.tsx
│   │   │   │       │   ├── selectors.ts
│   │   │   │       │   ├── store.ts
│   │   │   │       │   └── types.ts
│   │   │   │       ├── components/
│   │   │   │       │   └── AdminNavigablePage.tsx
│   │   │   │       └── instance/
│   │   │   │           └── instance/
│   │   │   │               ├── InstanceAdminNavigator.tsx
│   │   │   │               ├── components/
│   │   │   │               │   ├── buttons/
│   │   │   │               │   │   ├── InvitationActionButtons.tsx
│   │   │   │               │   │   ├── PendingRoleRequestsButtons.tsx
│   │   │   │               │   │   ├── ResendAllInvitationsButton.tsx
│   │   │   │               │   │   └── UsersButtons.tsx
│   │   │   │               │   ├── forms/
│   │   │   │               │   │   ├── IndividualInvitation.tsx
│   │   │   │               │   │   ├── IndividualInvitations.tsx
│   │   │   │               │   │   ├── IndividualInviteForm.tsx
│   │   │   │               │   │   ├── InstanceUserRoleRequestForm.tsx
│   │   │   │               │   │   └── RejectWithMessageForm.tsx
│   │   │   │               │   ├── misc/
│   │   │   │               │   │   ├── InstanceGetHelpFilter.tsx
│   │   │   │               │   │   └── InvitationResultDialog.tsx
│   │   │   │               │   ├── navigation/
│   │   │   │               │   │   └── InstanceUsersTabs.tsx
│   │   │   │               │   └── tables/
│   │   │   │               │       ├── InstanceGetHelpActivityTable.tsx
│   │   │   │               │       ├── InstanceUserRoleRequestsTable.tsx
│   │   │   │               │       ├── InvitationResultInvitationsTable.tsx
│   │   │   │               │       ├── InvitationResultUsersTable.tsx
│   │   │   │               │       ├── UserInvitationsTable.tsx
│   │   │   │               │       ├── UsersTable.tsx
│   │   │   │               │       └── __test__/
│   │   │   │               │           └── InstanceUserRoleRequestsTable.test.tsx
│   │   │   │               ├── operations.ts
│   │   │   │               ├── pages/
│   │   │   │               │   ├── InstanceAnnouncementsIndex.tsx
│   │   │   │               │   ├── InstanceComponentsIndex.tsx
│   │   │   │               │   ├── InstanceCoursesIndex.tsx
│   │   │   │               │   ├── InstanceGetHelpActivityIndex.tsx
│   │   │   │               │   ├── InstanceUserRoleRequestsIndex.tsx
│   │   │   │               │   ├── InstanceUsersIndex.tsx
│   │   │   │               │   ├── InstanceUsersInvitations.tsx
│   │   │   │               │   └── InstanceUsersInvite.tsx
│   │   │   │               ├── selectors.ts
│   │   │   │               ├── store.ts
│   │   │   │               └── types.ts
│   │   │   ├── user/
│   │   │   │   ├── AccountSettings/
│   │   │   │   │   ├── AccountSettingsForm.tsx
│   │   │   │   │   └── index.tsx
│   │   │   │   ├── components/
│   │   │   │   │   ├── AddEmailSubsection.tsx
│   │   │   │   │   └── EmailsList.tsx
│   │   │   │   ├── operations.ts
│   │   │   │   └── translations.ts
│   │   │   └── users/
│   │   │       ├── components/
│   │   │       │   ├── Widget.tsx
│   │   │       │   └── tables/
│   │   │       │       ├── CoursesTable.tsx
│   │   │       │       ├── InstancesTable.tsx
│   │   │       │       └── __test__/
│   │   │       │           └── InstancesTable.test.tsx
│   │   │       ├── operations.ts
│   │   │       ├── pages/
│   │   │       │   ├── ConfirmEmailPage.tsx
│   │   │       │   ├── ForgotPasswordLandingPage.tsx
│   │   │       │   ├── ForgotPasswordPage.tsx
│   │   │       │   ├── ResendConfirmationEmailLandingPage.tsx
│   │   │       │   ├── ResendConfirmationEmailPage.tsx
│   │   │       │   ├── ResetPasswordPage.tsx
│   │   │       │   ├── SignUpLandingPage.tsx
│   │   │       │   ├── SignUpPage.tsx
│   │   │       │   ├── UserShow.tsx
│   │   │       │   └── __test__/
│   │   │       │       └── UserShow.test.tsx
│   │   │       ├── selectors.ts
│   │   │       ├── store.ts
│   │   │       ├── translations.ts
│   │   │       ├── types.ts
│   │   │       └── validations.ts
│   │   ├── declaration.d.ts
│   │   ├── index.tsx
│   │   ├── lib/
│   │   │   ├── actions/
│   │   │   │   └── index.js
│   │   │   ├── components/
│   │   │   │   ├── core/
│   │   │   │   │   ├── AvatarSelector.tsx
│   │   │   │   │   ├── AvatarWithLabel.tsx
│   │   │   │   │   ├── BarChart.jsx
│   │   │   │   │   ├── BetaChip.tsx
│   │   │   │   │   ├── CourseUserTypeFragment.tsx
│   │   │   │   │   ├── CourseUserTypeTabs.tsx
│   │   │   │   │   ├── CustomTooltip.tsx
│   │   │   │   │   ├── DescriptionCard.tsx
│   │   │   │   │   ├── ErrorText.jsx
│   │   │   │   │   ├── Expandable.tsx
│   │   │   │   │   ├── ExpandableCode.tsx
│   │   │   │   │   ├── ExperimentalChip.tsx
│   │   │   │   │   ├── Hint.tsx
│   │   │   │   │   ├── ImageCropper/
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   └── utils.ts
│   │   │   │   │   ├── InfoLabel.tsx
│   │   │   │   │   ├── LinearProgressWithLabel.tsx
│   │   │   │   │   ├── Link.tsx
│   │   │   │   │   ├── LoadingEllipsis.tsx
│   │   │   │   │   ├── LoadingIndicator.tsx
│   │   │   │   │   ├── LoadingOverlay.tsx
│   │   │   │   │   ├── Note.tsx
│   │   │   │   │   ├── NotificationBar.jsx
│   │   │   │   │   ├── PopupMenu.tsx
│   │   │   │   │   ├── Thumbnail.jsx
│   │   │   │   │   ├── UserHTMLText.tsx
│   │   │   │   │   ├── __test__/
│   │   │   │   │   │   ├── ErrorText.test.tsx
│   │   │   │   │   │   ├── LoadingIndicator.test.tsx
│   │   │   │   │   │   └── __snapshots__/
│   │   │   │   │   │       ├── ErrorText.test.tsx.snap
│   │   │   │   │   │       └── LoadingIndicator.test.tsx.snap
│   │   │   │   │   ├── buttons/
│   │   │   │   │   │   ├── AcceptButton.tsx
│   │   │   │   │   │   ├── AddButton.tsx
│   │   │   │   │   │   ├── Checkbox.tsx
│   │   │   │   │   │   ├── DeleteButton.tsx
│   │   │   │   │   │   ├── DownloadButton.tsx
│   │   │   │   │   │   ├── EditButton.tsx
│   │   │   │   │   │   ├── EmailButton.tsx
│   │   │   │   │   │   ├── IconRadio.tsx
│   │   │   │   │   │   ├── RadioButton.tsx
│   │   │   │   │   │   ├── SaveButton.tsx
│   │   │   │   │   │   └── __test__/
│   │   │   │   │   │       ├── DeleteButton.test.tsx
│   │   │   │   │   │       ├── EditButton.test.tsx
│   │   │   │   │   │       └── __snapshots__/
│   │   │   │   │   │           ├── DeleteButton.test.tsx.snap
│   │   │   │   │   │           └── EditButton.test.tsx.snap
│   │   │   │   │   ├── charts/
│   │   │   │   │   │   ├── GeneralChart.tsx
│   │   │   │   │   │   ├── LineChart.tsx
│   │   │   │   │   │   └── emptyChartPlugin.ts
│   │   │   │   │   ├── dialogs/
│   │   │   │   │   │   ├── ConfirmationDialog.jsx
│   │   │   │   │   │   ├── ImageCropDialog.tsx
│   │   │   │   │   │   ├── Prompt.tsx
│   │   │   │   │   │   └── RailsConfirmationDialog.jsx
│   │   │   │   │   ├── fields/
│   │   │   │   │   │   ├── AceEditor.css
│   │   │   │   │   │   ├── CAPTCHAField.tsx
│   │   │   │   │   │   ├── CKEditor.css
│   │   │   │   │   │   ├── CKEditorField.tsx
│   │   │   │   │   │   ├── CKEditorRichText.tsx
│   │   │   │   │   │   ├── DateTimePicker.jsx
│   │   │   │   │   │   ├── EditorField.tsx
│   │   │   │   │   │   ├── NumberTextField.tsx
│   │   │   │   │   │   ├── PasswordTextField.tsx
│   │   │   │   │   │   ├── SearchField.tsx
│   │   │   │   │   │   ├── SwitchableTextField.tsx
│   │   │   │   │   │   └── TextField.tsx
│   │   │   │   │   ├── indicators/
│   │   │   │   │   │   └── SavingIndicator/
│   │   │   │   │   │       └── index.tsx
│   │   │   │   │   └── layouts/
│   │   │   │   │       ├── Accordion.tsx
│   │   │   │   │       ├── BackendPagination.tsx
│   │   │   │   │       ├── Banner.tsx
│   │   │   │   │       ├── ContactableErrorAlert.tsx
│   │   │   │   │       ├── ContextualErrorPage.tsx
│   │   │   │   │       ├── DataTable.jsx
│   │   │   │   │       ├── Footer.tsx
│   │   │   │   │       ├── MarkdownPage.tsx
│   │   │   │   │       ├── Page.tsx
│   │   │   │   │       ├── Pagination.tsx
│   │   │   │   │       ├── Section.tsx
│   │   │   │   │       ├── Subsection.tsx
│   │   │   │   │       ├── SummaryCard.tsx
│   │   │   │   │       ├── TableContainer.tsx
│   │   │   │   │       └── layout.scss
│   │   │   │   ├── extensions/
│   │   │   │   │   ├── CustomBadge.tsx
│   │   │   │   │   ├── CustomSlider.tsx
│   │   │   │   │   ├── PersonalStartEndTime.tsx
│   │   │   │   │   ├── PersonalTimeBooleanIcon.tsx
│   │   │   │   │   ├── StackedBadges.tsx
│   │   │   │   │   └── conditions/
│   │   │   │   │       ├── AnyCondition.ts
│   │   │   │   │       ├── ConditionRow.tsx
│   │   │   │   │       ├── ConditionsManager.tsx
│   │   │   │   │       ├── conditions/
│   │   │   │   │       │   ├── AchievementCondition.tsx
│   │   │   │   │       │   ├── AssessmentCondition.tsx
│   │   │   │   │       │   ├── LevelCondition.tsx
│   │   │   │   │       │   ├── ScholaisticAssessmentCondition.tsx
│   │   │   │   │       │   └── SurveyCondition.tsx
│   │   │   │   │       ├── operations.ts
│   │   │   │   │       ├── specifiers.ts
│   │   │   │   │       └── translations.ts
│   │   │   │   ├── form/
│   │   │   │   │   ├── Form.tsx
│   │   │   │   │   ├── FormDialogue.jsx
│   │   │   │   │   ├── dialog/
│   │   │   │   │   │   └── FormDialog.tsx
│   │   │   │   │   └── fields/
│   │   │   │   │       ├── AutoCompleteField.jsx
│   │   │   │   │       ├── CheckboxField.tsx
│   │   │   │   │       ├── DataTableInlineEditable/
│   │   │   │   │       │   └── TextField.tsx
│   │   │   │   │       ├── DateTimePickerField.jsx
│   │   │   │   │       ├── EditorField.jsx
│   │   │   │   │       ├── MultiSelectField.jsx
│   │   │   │   │       ├── RichTextField.jsx
│   │   │   │   │       ├── SelectField.jsx
│   │   │   │   │       ├── SingleFileInput/
│   │   │   │   │       │   ├── BadgePreview.jsx
│   │   │   │   │       │   ├── DeleteButton.jsx
│   │   │   │   │       │   ├── FilePreview.jsx
│   │   │   │   │       │   ├── ImagePreview.jsx
│   │   │   │   │       │   ├── __test__/
│   │   │   │   │       │   │   ├── BadgePreview.test.js
│   │   │   │   │       │   │   ├── ImagePreview.test.js
│   │   │   │   │       │   │   └── index.test.js
│   │   │   │   │       │   ├── index.jsx
│   │   │   │   │       │   └── translations.js
│   │   │   │   │       ├── TextField.tsx
│   │   │   │   │       ├── ToggleField.jsx
│   │   │   │   │       └── utils/
│   │   │   │   │           ├── mapError.js
│   │   │   │   │           └── propsAreEqual.js
│   │   │   │   ├── icons/
│   │   │   │   │   ├── GhostIcon.tsx
│   │   │   │   │   └── PointerIcon.tsx
│   │   │   │   ├── navigation/
│   │   │   │   │   ├── AdminPopupMenuList.tsx
│   │   │   │   │   ├── BrandingHead.tsx
│   │   │   │   │   ├── CourseSwitcherPopupMenu.tsx
│   │   │   │   │   ├── UserPopupMenuList.tsx
│   │   │   │   │   └── withRouter.jsx
│   │   │   │   ├── table/
│   │   │   │   │   ├── MuiTableAdapter/
│   │   │   │   │   │   ├── MuiFilterMenu.tsx
│   │   │   │   │   │   ├── MuiFilterMenuItem.tsx
│   │   │   │   │   │   ├── MuiTable.tsx
│   │   │   │   │   │   ├── MuiTableBody.tsx
│   │   │   │   │   │   ├── MuiTableHeader.tsx
│   │   │   │   │   │   ├── MuiTablePagination.tsx
│   │   │   │   │   │   ├── MuiTableRow.tsx
│   │   │   │   │   │   ├── MuiTableRowSelector.tsx
│   │   │   │   │   │   ├── MuiTableToolbar.tsx
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   └── translations.ts
│   │   │   │   │   ├── Table.tsx
│   │   │   │   │   ├── TanStackTableBuilder/
│   │   │   │   │   │   ├── columnsBuilder.ts
│   │   │   │   │   │   ├── csvGenerator.ts
│   │   │   │   │   │   ├── customFlexRender.ts
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   └── useTanStackTableBuilder.tsx
│   │   │   │   │   ├── adapters/
│   │   │   │   │   │   ├── Body.ts
│   │   │   │   │   │   ├── Filter.ts
│   │   │   │   │   │   ├── Handlers.ts
│   │   │   │   │   │   ├── Header.ts
│   │   │   │   │   │   ├── Pagination.ts
│   │   │   │   │   │   ├── RowSelector.ts
│   │   │   │   │   │   ├── Sort.ts
│   │   │   │   │   │   ├── Table.ts
│   │   │   │   │   │   ├── Toolbar.ts
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── builder/
│   │   │   │   │   │   ├── ColumnTemplate.ts
│   │   │   │   │   │   ├── TableTemplate.ts
│   │   │   │   │   │   ├── buildColumns.ts
│   │   │   │   │   │   ├── featureTemplates.ts
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   └── utils.ts
│   │   │   │   └── wrappers/
│   │   │   │       ├── AttributionsProvider.tsx
│   │   │   │       ├── AuthProvider.tsx
│   │   │   │       ├── ErrorBoundary.tsx
│   │   │   │       ├── FooterProvider.tsx
│   │   │   │       ├── I18nProvider.tsx
│   │   │   │       ├── Preload.tsx
│   │   │   │       ├── Providers.tsx
│   │   │   │       ├── RollbarWrapper.tsx
│   │   │   │       ├── StoreProvider.tsx
│   │   │   │       ├── ThemeProvider.tsx
│   │   │   │       └── ToastProvider.tsx
│   │   │   ├── constants/
│   │   │   │   ├── icons.ts
│   │   │   │   ├── index.js
│   │   │   │   ├── sharedConstants.ts
│   │   │   │   └── videoConstants.js
│   │   │   ├── containers/
│   │   │   │   ├── AppContainer/
│   │   │   │   │   ├── AppContainer.tsx
│   │   │   │   │   ├── AppLoader.ts
│   │   │   │   │   ├── GlobalAnnouncements.tsx
│   │   │   │   │   ├── ServerUnreachableBanner.tsx
│   │   │   │   │   └── index.ts
│   │   │   │   ├── AuthPagesContainer.tsx
│   │   │   │   ├── CourselessContainer.tsx
│   │   │   │   ├── DeleteConfirmation/
│   │   │   │   │   └── index.jsx
│   │   │   │   ├── NotificationPopup/
│   │   │   │   │   └── index.jsx
│   │   │   │   └── TableLegends.tsx
│   │   │   ├── helpers/
│   │   │   │   ├── __test__/
│   │   │   │   │   └── htmlFormatHelpers.test.js
│   │   │   │   ├── htmlFormatHelpers.js
│   │   │   │   ├── jobHelpers.ts
│   │   │   │   ├── mui-datatables-helpers.ts
│   │   │   │   ├── react-hook-form-helper.js
│   │   │   │   ├── reducer-helpers.js
│   │   │   │   ├── url-builders.js
│   │   │   │   ├── url-helpers.ts
│   │   │   │   └── videoHelpers.js
│   │   │   ├── history.js
│   │   │   ├── hooks/
│   │   │   │   ├── items/
│   │   │   │   │   ├── useItems.ts
│   │   │   │   │   ├── usePaginate.ts
│   │   │   │   │   ├── useSearch.ts
│   │   │   │   │   └── useSort.ts
│   │   │   │   ├── router/
│   │   │   │   │   ├── dynamicNest.ts
│   │   │   │   │   ├── redirect.tsx
│   │   │   │   │   └── usePrompt.tsx
│   │   │   │   ├── session.ts
│   │   │   │   ├── store.ts
│   │   │   │   ├── toast/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── loadingToast.ts
│   │   │   │   │   └── toast.tsx
│   │   │   │   ├── unread.ts
│   │   │   │   ├── useDebounce.ts
│   │   │   │   ├── useEffectOnce.ts
│   │   │   │   ├── useMedia.ts
│   │   │   │   └── useTranslation.ts
│   │   │   ├── moment.ts
│   │   │   ├── reducers/
│   │   │   │   ├── deleteConfirmation.js
│   │   │   │   └── notificationPopup.js
│   │   │   ├── translations/
│   │   │   │   ├── course/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── users/
│   │   │   │   │       ├── index.ts
│   │   │   │   │       └── roles.ts
│   │   │   │   ├── form.ts
│   │   │   │   ├── getHelp.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── messages.ts
│   │   │   │   └── table.ts
│   │   │   └── types.js
│   │   ├── routers/
│   │   │   ├── AuthenticatableApp.tsx
│   │   │   ├── AuthenticatedApp.tsx
│   │   │   ├── UnauthenticatedApp.tsx
│   │   │   ├── course/
│   │   │   │   ├── achievements.tsx
│   │   │   │   ├── admin.tsx
│   │   │   │   ├── assessments/
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   ├── questions.tsx
│   │   │   │   │   └── submissions.tsx
│   │   │   │   ├── forums.tsx
│   │   │   │   ├── groups.tsx
│   │   │   │   ├── index.tsx
│   │   │   │   ├── lessonPlan.tsx
│   │   │   │   ├── materials.tsx
│   │   │   │   ├── plagiarism.tsx
│   │   │   │   ├── scholaistic.tsx
│   │   │   │   ├── statistics.tsx
│   │   │   │   ├── surveys.tsx
│   │   │   │   ├── users.tsx
│   │   │   │   └── videos.tsx
│   │   │   ├── courseless/
│   │   │   │   ├── index.tsx
│   │   │   │   ├── instanceAdmin.tsx
│   │   │   │   ├── systemAdmin.tsx
│   │   │   │   └── users.tsx
│   │   │   ├── index.ts
│   │   │   ├── redirects.tsx
│   │   │   └── router.tsx
│   │   ├── store.ts
│   │   ├── theme/
│   │   │   ├── bouncing-dot.css
│   │   │   ├── colors.js
│   │   │   ├── github.css
│   │   │   ├── index.css
│   │   │   ├── mui-style.ts
│   │   │   ├── palette.js
│   │   │   ├── sidebar.css
│   │   │   └── syntax-highlighting.css
│   │   ├── types/
│   │   │   ├── channels/
│   │   │   │   ├── heartbeat.ts
│   │   │   │   └── liveMonitoring.ts
│   │   │   ├── components/
│   │   │   │   └── DataTable.ts
│   │   │   ├── course/
│   │   │   │   ├── achievements.ts
│   │   │   │   ├── admin/
│   │   │   │   │   ├── announcements.ts
│   │   │   │   │   ├── assessments.ts
│   │   │   │   │   ├── codaveri.ts
│   │   │   │   │   ├── comments.ts
│   │   │   │   │   ├── components.ts
│   │   │   │   │   ├── course.ts
│   │   │   │   │   ├── forums.ts
│   │   │   │   │   ├── leaderboard.ts
│   │   │   │   │   ├── lessonPlan.ts
│   │   │   │   │   ├── materials.ts
│   │   │   │   │   ├── notifications.ts
│   │   │   │   │   ├── ragWise.ts
│   │   │   │   │   ├── scholaistic.ts
│   │   │   │   │   ├── sidebar.ts
│   │   │   │   │   ├── stories.ts
│   │   │   │   │   └── videos.ts
│   │   │   │   ├── announcements.ts
│   │   │   │   ├── assessment/
│   │   │   │   │   ├── assessments.ts
│   │   │   │   │   ├── monitoring.ts
│   │   │   │   │   ├── question/
│   │   │   │   │   │   ├── forum-post-responses.ts
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   ├── multiple-responses.ts
│   │   │   │   │   │   ├── programming.ts
│   │   │   │   │   │   ├── rubric-based-responses.ts
│   │   │   │   │   │   ├── scribing.ts
│   │   │   │   │   │   ├── text-responses.ts
│   │   │   │   │   │   └── voice-responses.ts
│   │   │   │   │   ├── question-generation.ts
│   │   │   │   │   ├── questions.ts
│   │   │   │   │   ├── sessions.ts
│   │   │   │   │   ├── skills/
│   │   │   │   │   │   ├── skills.ts
│   │   │   │   │   │   └── userSkills.ts
│   │   │   │   │   ├── submission/
│   │   │   │   │   │   ├── annotations.ts
│   │   │   │   │   │   ├── answer/
│   │   │   │   │   │   │   ├── answer.ts
│   │   │   │   │   │   │   ├── forumPostResponse.ts
│   │   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   │   ├── multipleResponse.ts
│   │   │   │   │   │   │   ├── programming.ts
│   │   │   │   │   │   │   ├── rubricBasedResponse.ts
│   │   │   │   │   │   │   ├── scribing.ts
│   │   │   │   │   │   │   ├── textResponse.ts
│   │   │   │   │   │   │   └── voiceResponse.ts
│   │   │   │   │   │   ├── liveFeedback.ts
│   │   │   │   │   │   ├── logs.ts
│   │   │   │   │   │   ├── question/
│   │   │   │   │   │   │   └── types.ts
│   │   │   │   │   │   ├── submission-question.ts
│   │   │   │   │   │   └── submission.ts
│   │   │   │   │   └── submissions.ts
│   │   │   │   ├── comments.ts
│   │   │   │   ├── conditions.ts
│   │   │   │   ├── courseUsers.ts
│   │   │   │   ├── courses.ts
│   │   │   │   ├── disbursement.ts
│   │   │   │   ├── duplication.ts
│   │   │   │   ├── enrolRequests.ts
│   │   │   │   ├── experiencePointsRecords.ts
│   │   │   │   ├── forums.ts
│   │   │   │   ├── leaderboard.ts
│   │   │   │   ├── learn.ts
│   │   │   │   ├── lesson-plan/
│   │   │   │   │   └── todos.ts
│   │   │   │   ├── material/
│   │   │   │   │   ├── files.ts
│   │   │   │   │   └── folders.ts
│   │   │   │   ├── notifications.ts
│   │   │   │   ├── personalTimes.ts
│   │   │   │   ├── plagiarism.ts
│   │   │   │   ├── referenceTimelines.ts
│   │   │   │   ├── rubrics.ts
│   │   │   │   ├── scholaistic.ts
│   │   │   │   ├── statistics/
│   │   │   │   │   ├── answer.ts
│   │   │   │   │   └── assessmentStatistics.ts
│   │   │   │   ├── subscriptions.ts
│   │   │   │   ├── userInvitations.ts
│   │   │   │   ├── userNotifications.ts
│   │   │   │   ├── video/
│   │   │   │   │   └── submissions.ts
│   │   │   │   ├── videoSubmissions.ts
│   │   │   │   └── videos.ts
│   │   │   ├── home.ts
│   │   │   ├── index.ts
│   │   │   ├── jobs.ts
│   │   │   ├── store.ts
│   │   │   ├── system/
│   │   │   │   ├── courses.ts
│   │   │   │   ├── instance/
│   │   │   │   │   ├── components.ts
│   │   │   │   │   ├── invitations.ts
│   │   │   │   │   ├── roleRequests.ts
│   │   │   │   │   └── users.ts
│   │   │   │   └── instances.ts
│   │   │   └── users.ts
│   │   ├── utilities/
│   │   │   ├── ResizeObserver.ts
│   │   │   ├── TestApp.tsx
│   │   │   ├── array.ts
│   │   │   ├── authentication.ts
│   │   │   ├── downloadFile.ts
│   │   │   ├── index.ts
│   │   │   ├── mirrorCreator.ts
│   │   │   ├── socket.ts
│   │   │   ├── store.ts
│   │   │   └── test-utils.tsx
│   │   └── workers/
│   │       ├── constructors.ts
│   │       ├── heartbeat.sharedworker.ts
│   │       ├── heartbeat.worker.ts
│   │       ├── heartbeatChannel.ts
│   │       ├── listeners.ts
│   │       ├── monitoringDatabase.ts
│   │       ├── types.ts
│   │       └── withHeartbeatWorker.tsx
│   ├── css-includes.json
│   ├── env
│   ├── env.test
│   ├── jest.config.js
│   ├── locales/
│   │   ├── en.json
│   │   ├── ko.json
│   │   └── zh.json
│   ├── package.json
│   ├── postcss.config.js
│   ├── public/
│   │   └── index.html
│   ├── tailwind.config.ts
│   ├── tsconfig.eslint.json
│   ├── tsconfig.json
│   ├── webpack.common.js
│   ├── webpack.dev.js
│   ├── webpack.prod.js
│   └── webpack.profile.js
├── config/
│   ├── application.rb
│   ├── boot.rb
│   ├── cable.yml
│   ├── credentials/
│   │   ├── README.md
│   │   ├── test.key
│   │   └── test.yml.enc
│   ├── database.yml
│   ├── environment.rb
│   ├── environments/
│   │   ├── development.rb
│   │   ├── production.rb
│   │   └── test.rb
│   ├── i18n-js.yml
│   ├── i18n-tasks.yml
│   ├── image_optim.yml
│   ├── initializers/
│   │   ├── action_cable_acts_as_tenant.rb
│   │   ├── acts_as_tenant.rb
│   │   ├── application_controller_renderer.rb
│   │   ├── argument_deserializer.rb
│   │   ├── aws.rb
│   │   ├── backtrace_silencers.rb
│   │   ├── bullet.rb
│   │   ├── carrier_wave.rb
│   │   ├── content_security_policy.rb
│   │   ├── cookies_serializer.rb
│   │   ├── coverage.rb
│   │   ├── devise.rb
│   │   ├── extensions.rb
│   │   ├── filter_parameter_logging.rb
│   │   ├── formats_filter.rb
│   │   ├── inflections.rb
│   │   ├── keycloak.rb
│   │   ├── llm_langchain.rb
│   │   ├── locale.rb
│   │   ├── lograge.rb
│   │   ├── mail_delivery_job.rb
│   │   ├── mime_types.rb
│   │   ├── oembed.rb
│   │   ├── rack_mini_profiler.rb
│   │   ├── recaptcha.rb
│   │   ├── redis.rb
│   │   ├── send_file.rb
│   │   ├── session_store.rb
│   │   ├── sidekiq.rb
│   │   ├── userstamp.rb
│   │   ├── worker_http_listener.rb
│   │   └── wrap_parameters.rb
│   ├── locales/
│   │   ├── en/
│   │   │   ├── activemodel/
│   │   │   │   └── course/
│   │   │   │       └── experience_points/
│   │   │   │           └── forum_disbursement.yml
│   │   │   ├── activerecord/
│   │   │   │   ├── attributes.yml
│   │   │   │   └── errors.yml
│   │   │   ├── course/
│   │   │   │   └── assessment/
│   │   │   │       ├── answer/
│   │   │   │       │   └── text_response_comprehension_auto_grading.yml
│   │   │   │       ├── assessments.yml
│   │   │   │       ├── question/
│   │   │   │       │   ├── forum_post_response.yml
│   │   │   │       │   ├── multiple_responses.yml
│   │   │   │       │   ├── programming.yml
│   │   │   │       │   ├── scribing.yml
│   │   │   │       │   └── voice_responses.yml
│   │   │   │       └── question_bundle_assignments.yml
│   │   │   ├── csv.yml
│   │   │   ├── devise.yml
│   │   │   ├── errors.yml
│   │   │   ├── jobs.yml
│   │   │   ├── mailers.yml
│   │   │   └── time.yml
│   │   ├── ko/
│   │   │   ├── activemodel/
│   │   │   │   └── course/
│   │   │   │       └── experience_points/
│   │   │   │           └── forum_disbursement.yml
│   │   │   ├── activerecord/
│   │   │   │   ├── attributes.yml
│   │   │   │   └── errors.yml
│   │   │   ├── course/
│   │   │   │   └── assessment/
│   │   │   │       ├── answer/
│   │   │   │       │   └── text_response_comprehension_auto_grading.yml
│   │   │   │       ├── assessments.yml
│   │   │   │       ├── question/
│   │   │   │       │   ├── forum_post_response.yml
│   │   │   │       │   ├── multiple_responses.yml
│   │   │   │       │   ├── programming.yml
│   │   │   │       │   ├── scribing.yml
│   │   │   │       │   └── voice_responses.yml
│   │   │   │       └── question_bundle_assignments.yml
│   │   │   ├── csv.yml
│   │   │   ├── devise.yml
│   │   │   ├── errors.yml
│   │   │   ├── instance_user_role_request_mailer.yml
│   │   │   ├── jobs.yml
│   │   │   ├── mailers.yml
│   │   │   └── time.yml
│   │   └── zh/
│   │       ├── activemodel/
│   │       │   └── course/
│   │       │       └── experience_points/
│   │       │           └── forum_disbursement.yml
│   │       ├── activerecord/
│   │       │   ├── attributes.yml
│   │       │   └── errors.yml
│   │       ├── course/
│   │       │   └── assessment/
│   │       │       ├── answer/
│   │       │       │   └── text_response_comprehension_auto_grading.yml
│   │       │       ├── assessments.yml
│   │       │       ├── question/
│   │       │       │   ├── forum_post_response.yml
│   │       │       │   ├── multiple_responses.yml
│   │       │       │   ├── programming.yml
│   │       │       │   ├── scribing.yml
│   │       │       │   └── voice_responses.yml
│   │       │       └── question_bundle_assignments.yml
│   │       ├── csv.yml
│   │       ├── devise.yml
│   │       ├── errors.yml
│   │       ├── instance_user_role_request_mailer.yml
│   │       ├── jobs.yml
│   │       ├── mailers.yml
│   │       └── time.yml
│   ├── puma.rb
│   ├── routes.rb
│   ├── schedule.yml
│   ├── spring.rb
│   └── storage.yml
├── config.ru
├── db/
│   ├── migrate/
│   │   ├── .rubocop.yml
│   │   ├── 20141203044211_create_instances.rb
│   │   ├── 20141204122534_devise_create_users.rb
│   │   ├── 20141204122851_create_user_emails.rb
│   │   ├── 20141205065248_create_instance_users.rb
│   │   ├── 20141210044557_add_role_to_users_and_instance_users.rb
│   │   ├── 20141210105742_create_courses.rb
│   │   ├── 20141210133147_create_course_users.rb
│   │   ├── 20141222074908_add_userstamps_to_courses.rb
│   │   ├── 20150106073750_add_name_to_instances.rb
│   │   ├── 20150114024350_create_course_announcements.rb
│   │   ├── 20150114025131_create_instance_announcements.rb
│   │   ├── 20150116102204_add_name_to_users.rb
│   │   ├── 20150126080047_add_sticky_to_course_announcements.rb
│   │   ├── 20150129040648_create_system_announcements.rb
│   │   ├── 20150204075501_create_course_achievements.rb
│   │   ├── 20150206020132_create_course_levels.rb
│   │   ├── 20150309030221_create_attachments.rb
│   │   ├── 20150314025251_add_logo_to_courses.rb
│   │   ├── 20150316080645_unread_migration.rb
│   │   ├── 20150411065243_create_course_lesson_plan_items.rb
│   │   ├── 20150413043822_add_settings_to_instances_and_courses.rb
│   │   ├── 20150415033008_create_course_experience_points_records.rb
│   │   ├── 20150422152756_create_course_condition_levels.rb
│   │   ├── 20150425030128_set_timestamps_nullity.rb
│   │   ├── 20150426062119_create_course_conditions.rb
│   │   ├── 20150426062133_create_course_conditions_achievements.rb
│   │   ├── 20150512014731_add_workflow_state_to_course_users.rb
│   │   ├── 20150512015621_add_userstamps_to_course_users.rb
│   │   ├── 20150513110737_create_course_groups.rb
│   │   ├── 20150513111716_create_course_group_users.rb
│   │   ├── 20150614024340_combine_instance_system_announcements.rb
│   │   ├── 20150615014716_create_course_invitations.rb
│   │   ├── 20150615073135_add_fields_to_course_lesson_plan_item.rb
│   │   ├── 20150615075515_create_course_events.rb
│   │   ├── 20150616120237_create_activities_and_notifications.rb
│   │   ├── 20150617021911_create_course_lesson_plan_milestones.rb
│   │   ├── 20150624230355_add_course_registration_key_to_course.rb
│   │   ├── 20150702122955_instance_users_change_user_id_unique.rb
│   │   ├── 20150713125423_create_assessments.rb
│   │   ├── 20150721051322_add_course_assessment_logic.rb
│   │   ├── 20150721055754_change_experience_points_record_points_null.rb
│   │   ├── 20150721070705_create_user_identities.rb
│   │   ├── 20150726062900_create_course_assessment_question_multiple_response.rb
│   │   ├── 20150726130555_set_achievement_condition_nullity.rb
│   │   ├── 20150726130922_set_conditional_nullity.rb
│   │   ├── 20150728020832_add_schema_nullity.rb
│   │   ├── 20150728022835_rename_published_to_draft.rb
│   │   ├── 20150729133128_rename_course_events_to_course_lesson_plan_events.rb
│   │   ├── 20150730074301_rename_start_end_time_to_start_end_at.rb
│   │   ├── 20150731010032_rename_valid_from_to_start_end_at.rb
│   │   ├── 20150803065430_change_multiple_response_question_option_option_explanation_column_type.rb
│   │   ├── 20150803065716_create_materials.rb
│   │   ├── 20150803080715_add_assessment_answer_workflow_state.rb
│   │   ├── 20150812024950_add_fields_to_course_material_folders.rb
│   │   ├── 20151011151130_create_course_user_achievements.rb
│   │   ├── 20151016094007_create_discussions_and_forums.rb
│   │   ├── 20151016094008_create_forums.rb
│   │   ├── 20151016151834_add_root_folder_to_courses.rb
│   │   ├── 20151018122902_add_grade_to_course_assessment_answer.rb
│   │   ├── 20151021014315_create_course_assessment_question_text_response.rb
│   │   ├── 20151022105653_add_unique_index_to_forum_and_topic.rb
│   │   ├── 20151027050627_add_submission_grading_statistics.rb
│   │   ├── 20151028151258_add_unique_index_to_materials.rb
│   │   ├── 20151030063045_add_unique_index_to_course_material_folders.rb
│   │   ├── 20151031044810_add_course_assessment_answer_auto_grading.rb
│   │   ├── 20151101050627_create_folder_for_categories_and_assessments.rb
│   │   ├── 20151114043545_create_jobs.rb
│   │   ├── 20151114093538_link_course_assessment_answer_auto_grading_to_jobs.rb
│   │   ├── 20151117141053_unread_polymorphic_reader_migration.rb
│   │   ├── 20151119020459_create_course_assessment_programming_questions.rb
│   │   ├── 20151121070719_create_polyglot_languages.rb
│   │   ├── 20151121082432_integrate_assessments_with_polyglot_framework.rb
│   │   ├── 20151122011709_create_course_assessment_programming_evaluations.rb
│   │   ├── 20151202030421_add_profile_photo_to_users.rb
│   │   ├── 20151210055839_create_course_condition_assessments.rb
│   │   ├── 20151212091754_normalise_programming_question_file_names.rb
│   │   ├── 20151212232827_add_token_authentication_to_user.rb
│   │   ├── 20151214080700_add_package_to_programming_evaluation.rb
│   │   ├── 20151214081508_add_unique_index_to_course_levels.rb
│   │   ├── 20151224034135_add_display_mode_to_assessments.rb
│   │   ├── 20151228030006_add_weight_to_questions.rb
│   │   ├── 20160119055307_add_correct_to_assessment_answers.rb
│   │   ├── 20160124054745_add_exit_code_to_programming_evaluation.rb
│   │   ├── 20160126094510_add_badge_to_course_achievements.rb
│   │   ├── 20160220081731_rename_assessment_tags_to_skills.rb
│   │   ├── 20160220092350_add_course_to_skill_and_skill_branch.rb
│   │   ├── 20160226013208_create_course_assessment_answer_programming_file_annotations.rb
│   │   ├── 20160229082515_create_attachment_references.rb
│   │   ├── 20160330031839_create_course_discussion_post_votes.rb
│   │   ├── 20160420005403_change_course_groups_from_user_to_course_user.rb
│   │   ├── 20160429135101_add_attributes_to_course_discussion_topics.rb
│   │   ├── 20160523093423_add_field_to_course_discussion_topics.rb
│   │   ├── 20160628052136_add_staff_only_comments_to_questions.rb
│   │   ├── 20160714053644_add_timestamps_to_course_assessment_answers.rb
│   │   ├── 20160716091234_add_autograded_to_course_assessments.rb
│   │   ├── 20160722020938_add_time_zone_to_users.rb
│   │   ├── 20160729022656_add_fields_to_course_assessment_question_programming_test_cases.rb
│   │   ├── 20160730044448_chang_attachment_references.rb
│   │   ├── 20160801084814_rename_question_type_to_grading_scheme.rb
│   │   ├── 20160808023535_change_course_assessment_questions_title_nullity.rb
│   │   ├── 20160811064336_change_test_cases_expected_type.rb
│   │   ├── 20160815141617_prevent_duplicate_submissions.rb
│   │   ├── 20160822092000_add_publisher_to_submissions.rb
│   │   ├── 20160823091240_add_unique_index_to_read_marks.rb
│   │   ├── 20160823094126_add_unique_index_to_multiple_response_answer_options.rb
│   │   ├── 20160830023835_alter_grade_type.rb
│   │   ├── 20160906091734_add_fields_to_course_assessment_answer_text_responses.rb
│   │   ├── 20160908100211_rename_programming_auto_grading_test_result_messages.rb
│   │   ├── 20160916101014_change_discussion_posts_title.rb
│   │   ├── 20160920101847_add_hide_text_to_course_assessment_question_text_responses.rb
│   │   ├── 20161003094742_create_lesson_plan_todos.rb
│   │   ├── 20161006063146_rename_assessments_display_mode.rb
│   │   ├── 20161007061116_add_fields_to_assessments.rb
│   │   ├── 20161013115452_migrate_graded_submissions_to_published.rb
│   │   ├── 20161020020353_add_todos_for_existing_lesson_plan_items.rb
│   │   ├── 20161027020646_add_package_type_to_course_assessment_question_programming.rb
│   │   ├── 20161027074807_add_session_id_to_submissions.rb
│   │   ├── 20161102022455_add_stdout_stderr_to_course_assessment_answer_programming_auto_grading.rb
│   │   ├── 20161107023238_add_attempt_limit_to_programming_questions.rb
│   │   ├── 20161108030759_add_gamified_to_courses.rb
│   │   ├── 20161116075305_add_tabbed_view_to_course_assessments.rb
│   │   ├── 20161202071856_add_skippable_to_assessments.rb
│   │   ├── 20161206101644_remove_mode_and_invert_draft.rb
│   │   ├── 20161207013914_create_course_survey_tables.rb
│   │   ├── 20161214050848_add_sent_at_to_course_user_invitations.rb
│   │   ├── 20161219105620_change_course_user_invitations.rb
│   │   ├── 20161223123359_create_course_enrol_requests.rb
│   │   ├── 20161227125455_remove_workflow_state_from_course_users.rb
│   │   ├── 20170102053335_create_course_video_tables.rb
│   │   ├── 20170103104020_create_course_lectures.rb
│   │   ├── 20170110022335_remove_extra_bonus_exp_from_lesson_plan.rb
│   │   ├── 20170115105609_add_delayed_grade_publication_to_course_assessments.rb
│   │   ├── 20170116103602_add_tokens_to_course_lesson_plan_items.rb
│   │   ├── 20170117145558_add_fields_to_courses.rb
│   │   ├── 20170117164747_add_awarded_at_and_draft_exp_to_course_experience_points_records.rb
│   │   ├── 20170120063357_change_default_value_of_assessment_questions_weight.rb
│   │   ├── 20170128041649_change_survey_tables.rb
│   │   ├── 20170203020915_add_weight_to_course_assessment_question_multiple_response_options.rb
│   │   ├── 20170210073247_add_selected_to_survey_answer_options.rb
│   │   ├── 20170214062036_add_index_for_survey_response_user.rb
│   │   ├── 20170217041431_add_survey_booleans.rb
│   │   ├── 20170220123952_remove_image_from_survey_question_option.rb
│   │   ├── 20170222101701_remove_default_from_groups.rb
│   │   ├── 20170302054635_add_submitted_at_to_submissions.rb
│   │   ├── 20170306051518_rename_lectures_to_virtual_classrooms.rb
│   │   ├── 20170307043218_add_instructor_id_to_virtual_classrooms.rb
│   │   ├── 20170307080839_add_timestamp_to_trackable_jobs.rb
│   │   ├── 20170307090147_add_time_limit_to_existing_programming_questions.rb
│   │   ├── 20170308044737_add_recorded_videos_to_virtual_classrooms.rb
│   │   ├── 20170308073855_create_course_assessment_submission_logs.rb
│   │   ├── 20170308074359_add_course_assessment_submission_question.rb
│   │   ├── 20170309094211_add_section_id_to_survey_questions.rb
│   │   ├── 20170407083553_add_reminded_at_and_allow_responsee_to_surveys.rb
│   │   ├── 20170420063829_remove_length_limit_of_expression.rb
│   │   ├── 20170426024809_remove_constraint_in_skills.rb
│   │   ├── 20170506010828_create_course_assessment_question_scribings.rb
│   │   ├── 20170510233359_remove_selected_from_survey_answer_options.rb
│   │   ├── 20170515061739_add_more_options_to_course_assessments.rb
│   │   ├── 20170522104534_regroup_course_settings.rb
│   │   ├── 20170528035408_create_course_asse

================================================
FILE CONTENTS
================================================

================================================
FILE: .circleci/config.yml
================================================
version: 2.1

orbs:
  codecov: codecov/codecov@5.4.3

executors:
  node:
    docker:
      - image: cimg/node:22.22.0

    working_directory: ~/repo
    resource_class: large

  ruby_with_postgres:
    parameters:
      collects_rails_coverage:
        type: boolean
        default: false

    docker:
      - image: cimg/ruby:3.3.5-browsers
        environment:
          PG_HOST: localhost
          PG_USER: ubuntu
          RAILS_ENV: test
          BUNDLE_APP_CONFIG: ~/repo/.bundle
          DATABASE_URL: 'postgres://ubuntu@localhost:5432/coursemology_test'
          COLLECT_COVERAGE: << parameters.collects_rails_coverage >>

      - image: pgvector/pgvector:pg16
        environment:
          POSTGRES_USER: ubuntu
          POSTGRES_DB: coursemology_test
          POSTGRES_PASSWORD: Testing1234

      - image: cimg/redis:7.2.3

    working_directory: ~/repo
    resource_class: large

commands:
  checkout_with_submodules:
    steps:
      - checkout

      - run:
          name: Checkout submodules
          command: git submodule update --init --recursive

  rehydrate_ruby_deps:
    steps:
      - restore_cache:
          name: Restore Ruby dependencies cache
          keys:
            - v3.3.5-ruby-{{ checksum "Gemfile.lock" }}
            - v3.3.5-ruby-

      - run:
          name: Install Bundler
          command: gem install bundler:2.5.9

      - run:
          name: Install Ruby dependencies
          command: bundle install --jobs=4 --retry=3 --path vendor/bundle --without development:production --deployment

      - save_cache:
          paths:
            - ./vendor/bundle
            - ./.bundle
          key: v3.3.5-ruby-{{ checksum "Gemfile.lock" }}

  rehydrate_node_deps:
    steps:
      - restore_cache:
          name: Restore client Yarn dependencies cache
          keys:
            - v22.22.0-node-{{ checksum "client/yarn.lock" }}-{{ checksum "client/vendor/recorderjs/package.json" }}
            - v22.22.0-node-

      - run:
          name: Install client Yarn dependencies
          working_directory: client
          command: yarn run clean-install

      - save_cache:
          paths:
            - ./client/node_modules
            - ./client/vendor/recorderjs/node_modules
          key: v22.22.0-node-{{ checksum "client/yarn.lock" }}-{{ checksum "client/vendor/recorderjs/package.json" }}

  restore_client_cache:
    steps:
      - restore_cache:
          name: Restore client cache
          keys:
            - v1-yarn-build-{{ .Revision }}

  build_and_cache_client:
    steps:
      - restore_client_cache

      - run:
          name: Add env file to client folder
          working_directory: client
          command: |
            touch .env.test
            echo GOOGLE_RECAPTCHA_SITE_KEY="${GOOGLE_RECAPTCHA_SITE_KEY}" >> .env.test
            echo ROLLBAR_POST_CLIENT_ITEM_KEY="${ROLLBAR_POST_CLIENT_ITEM_KEY}" >> .env.test
            echo SUPPORT_EMAIL="${SUPPORT_EMAIL}" >> .env.test
            echo DEFAULT_LOCALE="${DEFAULT_LOCALE}" >> .env.test
            echo DEFAULT_TIME_ZONE="${DEFAULT_TIME_ZONE}" >> .env.test
            echo OIDC_AUTHORITY="${OIDC_AUTHORITY}" >> .env.test
            echo OIDC_CLIENT_ID="${OIDC_CLIENT_ID}" >> .env.test
            echo OIDC_REDIRECT_URI="${OIDC_REDIRECT_URI}" >> .env.test

      - run:
          name: Build client
          working_directory: client
          command: yarn build:test
          environment:
            AVAILABLE_CPUS: 4

      - save_cache:
          paths:
            - ./client/build
          key: v1-yarn-build-{{ .Revision }}

  build_and_run_auth_server:
    steps:
      - run:
          name: Create coursemology_keycloak db
          command: |
            DB_CONTAINER_ID=$(docker ps -q --filter ancestor=pgvector/pgvector:pg16)
            docker exec $DB_CONTAINER_ID psql -c "CREATE DATABASE coursemology_keycloak OWNER ubuntu;" -U ubuntu -d postgres
            docker exec $DB_CONTAINER_ID psql -c "CREATE DATABASE coursemology OWNER ubuntu;" -U ubuntu -d postgres
      - run:
          name: Update docker compose file
          working_directory: authentication
          command: |
            sed -i '/ports:/,+1d' docker-compose.yml
      - run:
          name: Update realm config files
          working_directory: authentication/import
          command: |
            sed -i 's/host.docker.internal/localhost/g' coursemology_realm.json
            sed -i 's/\"postgres\"/\"ubuntu\"/g' coursemology_realm.json
      - run:
          name: Add env file to authentication folder
          working_directory: authentication
          command: |
            touch .env
            echo KC_NETWORK_MODE="container:$(docker ps -q --filter ancestor=pgvector/pgvector:pg16)" >> .env
            echo KC_DB="postgres" >> .env
            echo KC_DB_URL="jdbc:postgresql://localhost:5432/coursemology_keycloak" >> .env
            echo KC_DB_USERNAME="ubuntu" >> .env
            echo KC_DB_PASSWORD="" >> .env
            echo KC_HOSTNAME="localhost" >> .env
            echo KEYCLOAK_ADMIN="admin" >> .env
            echo KEYCLOAK_ADMIN_PASSWORD="password" >> .env
      - run:
          name: Build authentication image
          working_directory: authentication
          command: docker build -t coursemology_auth .
      - run:
          name: Run authentication server
          working_directory: authentication
          command: docker compose up
          background: true
      - run:
          name: Wait for Auth server
          command: |
            curl -s --retry 1000 --retry-delay 1 --retry-connrefused -4 http://localhost:8443

  setup_db:
    steps:
      - run:
          name: Set up test database
          command: bundle exec rake db:setup
          environment:
            COLLECT_COVERAGE: false

  serve_static_site:
    steps:
      - run:
          name: Download dirt-cheap-rocket
          command: curl https://github.com/Coursemology/dirt-cheap-rocket/releases/latest/download/dirt-cheap-rocket.cjs -o dirt-cheap-rocket.cjs -L
      - run:
          name: Serve static site
          command: node dirt-cheap-rocket.cjs
          background: true
          environment:
            DCR_CLIENT_PORT: 3200
            DCR_SERVER_PORT: 7979
            DCR_PUBLIC_PATH: /static
            DCR_ASSETS_DIR: client/build

  serve_rails_server:
    steps:
      - run:
          name: Add env file to main folder
          command: |
            touch .env
            echo RAILS_HOSTNAME="localhost:3000" >> .env
            echo KEYCLOAK_AUTH_SERVER_URL="http://localhost:8443/" >> .env
            echo KEYCLOAK_AUTH_JWKS_URL="http://localhost:8443/realms/coursemology_test/protocol/openid-connect/certs" >> .env
            echo KEYCLOAK_AUTH_INSTROPECTION_URL="http://localhost:8443/realms/coursemology_test/protocol/openid-connect/token/introspect" >> .env
            echo KEYCLOAK_ISS="http://localhost:8443/realms/coursemology_test" >> .env
            echo KEYCLOAK_AUD="account" >> .env
            echo KEYCLOAK_REALM="coursemology_test" >> .env

      - run:
          name: Serve Rails server
          command: bundle exec rails s -p 7979
          background: true

      - run:
          name: Wait for Rails server
          command: |
            curl -s --retry 1000 --retry-delay 1 --retry-connrefused -4 http://localhost:7979

  terminate_rails_and_wait_for_coverage_results:
    steps:
      - run:
          name: Terminate Rails server
          command: pkill -SIGINT -f puma

      - run:
          name: Wait for Rails coverage results
          no_output_timeout: 5m
          command: until [ -f coverage/coursemology.lcov ]; do sleep 1; done

  persist_coverage_reports:
    steps:
      - run:
          name: Assign unique coverage filename
          command: |
            mv coverage/coursemology.lcov coverage/cov-<< parameters.prefix >>-${CIRCLE_NODE_INDEX}.lcov

      - persist_to_workspace:
          root: coverage
          paths:
            - cov-*.lcov

    parameters:
      prefix:
        type: string

  setup_docker_layer_cache:
    steps:
      - setup_remote_docker:
          version: docker26
          docker_layer_caching: true

  # Install Ghostscript so `identify` in ImageMagick works with PDF files.
  # To remove PDF security policy for ImageMagick (Ubuntu 20.04), see https://stackoverflow.com/questions/52998331/imagemagick-security-policy-pdf-blocking-conversion
  # This is currently not used as CircleCI would fail to install occasionally.
  install_ghostscript_and_imagemagick:
    steps:
      - run:
          name: Install Ghostscript and ImageMagick
          command: |
            sudo apt update
            sudo apt install imagemagick
            sudo apt install ghostscript
            sudo sed -i '/disable ghostscript format types/,+6d' /etc/ImageMagick-6/policy.xml

jobs:
  build_client:
    executor: node

    steps:
      - checkout_with_submodules
      - rehydrate_node_deps
      - build_and_cache_client

  test_playwright:
    executor:
      name: ruby_with_postgres
      collects_rails_coverage: true

    parallelism: 10

    steps:
      - checkout_with_submodules
      - setup_docker_layer_cache

      - rehydrate_ruby_deps
      - restore_client_cache

      - setup_db
      - serve_static_site
      - serve_rails_server
      - build_and_run_auth_server

      # Replace both archive and security repositories 
      # https://support.circleci.com/hc/en-us/articles/37474192881179-Resolving-Unable-to-connect-to-archive-ubuntu-com-Error-in-CircleCI
      - run:
          name: Change Ubuntu archive mirrors
          command: |
            sudo sed -i 's|http://archive.ubuntu.com|http://mirrors.rit.edu|g' /etc/apt/sources.list
            sudo sed -i 's|http://security.ubuntu.com|http://mirrors.rit.edu|g' /etc/apt/sources.list

      - run:
          name: Install Playwright dependencies
          working_directory: tests
          command: |
            wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | sudo tee /etc/apt/trusted.gpg.d/google.asc >/dev/null
            yarn run clean-install
            yarn prepare

      - run:
          name: Run Playwright tests
          working_directory: tests
          command: |
            SHARD="$((${CIRCLE_NODE_INDEX}+1))"; npx playwright test --shard=${SHARD}/${CIRCLE_NODE_TOTAL} --reporter=junit
          environment:
            PLAYWRIGHT_JUNIT_OUTPUT_NAME: results.xml

      - run:
          name: Generate code coverage
          working_directory: tests
          command: yarn coverage

      - terminate_rails_and_wait_for_coverage_results
      - persist_coverage_reports:
          prefix: playwright-rails

      - store_test_results:
          path: ~/repo/tests/results.xml

      - run:
          name: Assign unique test results filename
          when: always
          working_directory: tests
          command: |
            mv test-results test-results-${CIRCLE_NODE_INDEX}

      - persist_to_workspace:
          root: tests
          paths:
            - test-results-*

  test_rspec:
    executor:
      name: ruby_with_postgres
      collects_rails_coverage: true

    parallelism: 30

    steps:
      - checkout_with_submodules
      - setup_docker_layer_cache

      - rehydrate_ruby_deps
      - restore_client_cache

      - setup_db
      - serve_static_site
      - build_and_run_auth_server

      - run:
          name: Run RSpec tests
          no_output_timeout: 10m
          command: |
            mkdir ~/rspec
            circleci tests glob "spec/**/*_spec.rb" | circleci tests run --command="xargs bundle exec rspec --format progress --format RspecJunitFormatter -o ~/rspec/rspec.xml" --verbose --split-by=timings

      - persist_coverage_reports:
          prefix: rspec-rails

      - store_test_results:
          path: ~/rspec

  process_test_results:
    docker:
      - image: cimg/base:2025.06
    steps:
      # Need the source code to be present in the workspace for codecov to accept the report
      - checkout
      - attach_workspace:
          at: workspace

      - run:
          name: Combine all lcov reports
          command: |
            sudo apt-get update
            sudo apt-get install lcov
            lcov $(printf -- '--add-tracefile %s ' workspace/cov-*.lcov) --output-file workspace/coverage-combined.lcov --branch-coverage --ignore-errors inconsistent

      - codecov/upload:
          upload_name: coverage-combined
          disable_search: true
          files: workspace/coverage-combined.lcov
          flags: backend

      - run:
          name: Zip all test results
          command: |
            zip -r test-results.zip workspace/*

      - store_artifacts:
          path: test-results.zip

  factorybot_lint:
    executor: ruby_with_postgres

    steps:
      - checkout
      - rehydrate_ruby_deps
      - setup_db

      - run:
          name: Run FactoryBot lint
          command: bundle exec rake factory_bot:lint

  jslint:
    executor: node

    steps:
      - checkout_with_submodules
      - rehydrate_node_deps

      - run:
          name: Run ESLint and Prettier checks
          working_directory: client
          command: yarn lint

  jstest:
    executor: node

    steps:
      - checkout_with_submodules
      - rehydrate_node_deps

      - run:
          name: Build translations
          working_directory: client
          command: yarn run build:translations

      - run:
          name: Run Jest tests
          working_directory: client
          command: yarn testci

  i18n_en:
    executor: ruby_with_postgres

    steps:
      - checkout
      - rehydrate_ruby_deps
      - setup_db

      - run:
          name: Check for unused translations (English)
          command: bundle exec i18n-tasks unused --locales en

      - run:
          name: Check for missing translations (English)
          command: bundle exec i18n-tasks missing --locales en

  i18n_zh:
    executor: ruby_with_postgres

    steps:
      - checkout
      - rehydrate_ruby_deps
      - setup_db

      - run:
          name: Check for unused translations (Mandarin)
          command: bundle exec i18n-tasks unused --locales zh

      - run:
          name: Check for missing translations (Mandarin)
          command: bundle exec i18n-tasks missing --locales zh

  i18n_ko:
    executor: ruby_with_postgres

    steps:
      - checkout
      - rehydrate_ruby_deps
      - setup_db

      - run:
          name: Check for unused translations (Korean)
          command: bundle exec i18n-tasks unused --locales ko

      - run:
          name: Check for missing translations (Korean)
          command: bundle exec i18n-tasks missing --locales ko

workflows:
  build_and_test_and_lint:
    jobs:
      - jslint
      - jstest
      - build_client
      - i18n_en
      - i18n_zh
      - i18n_ko
      - factorybot_lint
      - test_rspec:
          requires:
            - build_client
            - factorybot_lint
      - test_playwright:
          requires:
            - build_client
      - process_test_results:
          requires:
            - test_rspec
            - test_playwright


================================================
FILE: .codecov.yml
================================================
codecov:
  notify:
    require_ci_to_pass: no

flags:
  frontend:
    paths:
      - client/app/
  backend:
    paths:
      - app/
      - lib/

coverage:
  precision: 2
  round: up
  range: '70...100'
  status:
    project:
      default: off
      frontend:
        target: auto
        threshold: 0.1%
        flags:
          - frontend
      backend:
        target: auto
        threshold: 0.1%
        flags:
          - backend
    patch: yes
    changes: no

parsers:
  gcov:
    branch_detection:
      conditional: yes
      loop: yes
      method: no
      macro: no

comment: false


================================================
FILE: .github/ISSUE_TEMPLATE/1-bug-report.yml
================================================
name: 🐞 Bug Report
description: File a bug/issue
labels: ["Bug"]
assignees:
  - cysjonathan
  - adi-herwana-nus
body:
  - type: checkboxes
    attributes:
      label: Is there an existing issue for this?
      description: Please search to see if an issue already exists for the bug you encountered.
      options:
        - label: I have searched the existing issues
          required: true
  - type: textarea
    attributes:
      label: Current Behavior
      description: A concise description of what you're experiencing.
    validations:
      required: false
  - type: textarea
    attributes:
      label: Expected Behavior
      description: A concise description of what you expected to happen.
    validations:
      required: false
  - type: textarea
    attributes:
      label: Steps To Reproduce
      description: Steps to reproduce the behavior.
      placeholder: |
        1. In this environment...
        2. With this configuration...
        3. Run '...'
        4. See error...
    validations:
      required: false
  - type: textarea
    attributes:
      label: Anything else?
      description: |
        Links? References? Error Messages? Screenshots? Anything that will give us more context about the issue you are encountering!

        Tip: You can attach images or files by clicking this area to highlight it and then dragging files in.
    validations:
      required: false


================================================
FILE: .github/ISSUE_TEMPLATE/2-feature-request.yml
================================================
name: 💡 Feature Request
description: Suggest a new feature or enhancement
labels: ["Feature"]
assignees:
  - cysjonathan
  - adi-herwana-nus
body:
  - type: checkboxes
    attributes:
      label: Is there an existing issue for this?
      description: Please search to see if a feature request already exists for what you're proposing.
      options:
        - label: I have searched the existing issues
          required: true
  - type: textarea
    attributes:
      label: Problem Statement
      description: What problem would this feature solve? What is the current limitation?
      placeholder: "As a [user type], I want [goal] so that [reason]..."
    validations:
      required: false
  - type: textarea
    attributes:
      label: Proposed Solution
      description: Describe the feature you'd like to see implemented.
      placeholder: "I would like to see..."
    validations:
      required: false
  - type: textarea
    attributes:
      label: Alternative Solutions
      description: Have you considered any alternative solutions or workarounds?
    validations:
      required: false
  - type: textarea
    attributes:
      label: Anything else?
      description: |
        Mockups? Screenshots? Anything that will give us more context about the feature you are requesting!

        Tip: You can attach images or files by clicking this area to highlight it and then dragging files in.
    validations:
      required: false


================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: true
contact_links:
  - name: User Guide
    url: https://coursemology.github.io/coursemology-help/
    about: Please refer to the User Guide for help on using Coursemology
  - name: Developer Guide
    url: https://github.com/Coursemology/coursemology2/wiki
    about: Please refer to the Developer Guide for help on developing Coursemology


================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
  - package-ecosystem: bundler
    directory: '/'
    schedule:
      interval: daily
    open-pull-requests-limit: 10
    cooldown:
      default-days: 5
      semver-major-days: 30
      semver-minor-days: 7
      semver-patch-days: 3
    groups:
      dev-dependencies:
        dependency-type: development
      aws-dependencies:
        patterns:
          - 'aws-*'
          - 'fog-aws'

  - package-ecosystem: npm
    directory: '/client'
    schedule:
      interval: daily
    open-pull-requests-limit: 10
    cooldown:
      default-days: 5
      semver-major-days: 30
      semver-minor-days: 7
      semver-patch-days: 3

  - package-ecosystem: npm
    directory: '/tests'
    schedule:
      interval: daily
    open-pull-requests-limit: 10
    cooldown:
      default-days: 5
      semver-major-days: 30
      semver-minor-days: 7
      semver-patch-days: 3
    groups:
      all-dependencies:
        patterns:
          - '*'


================================================
FILE: .gitignore
================================================
# See https://help.github.com/articles/ignoring-files for more about ignoring files.
#
# If you find yourself ignoring temporary files generated by your text editor
# or operating system, you probably want to add a global ignore instead:
#   git config --global core.excludesfile '~/.gitignore_global'

# Ignore bundler config and gems.
/.bundle
/vendor/bundle

# Ignore user-specific Intellij project files
/.idea/*

# Ignore user-specific VSCode project files
.vscode

# Ignore credentials files which may contain sensitive information
/config/credentials/*.crt
/config/credentials/*.key
/config/credentials/*.yml.enc
!/config/credentials/test.key
!/config/credentials/test.yml.enc

# Ignore the default SQLite database.
/db/*.sqlite3
/db/*.sqlite3-journal

# Ignore all logfiles and tempfiles.
/log/*.log
/log/*.log.[0-9]*
/tmp

# Ignore ruby-version file
/.ruby-version

# Ignore byebug_history file
/.byebug_history

# Ignore generated documentation
/.yardoc/*
/doc/*

# Ignore generated code coverage information
/spec/coverage/*
/coverage/*
/client/coverage/*

# Ignore public download/upload folders
/public/downloads/*
/public/uploads/*

# Ignore installed node libraries and log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
node_modules

# Ignore generated js bundles
/public/webpack/*

# Ignore eslint cache
/client/.eslintcache

# Ignore build for client
/client/build
.DS_Store

# Ignore local node version
.node-version

# Ignore env files
.env
.env.*

# Ignore Playwright results
test-results/
playwright-report/
playwright/.cache/
.nyc_output
coverage/

dump.rdb

compiled-locales


================================================
FILE: .gitmodules
================================================
[submodule "vendor/assets/javascripts/recorderjs"]
	path = client/vendor/recorderjs
	url = https://github.com/mattdiamond/Recorderjs.git
	ignore = dirty
[submodule "authentication/singular-keycloak-database-federation"]
	path = authentication/singular-keycloak-database-federation
	url = https://github.com/Coursemology/singular-keycloak-database-federation.git


================================================
FILE: .hound.yml
================================================
fail_on_violations: true

rubocop:
  config_file: .rubocop.yml
  version: 1.22.1

javascript:
  enabled: false


================================================
FILE: .rspec
================================================
--color
--format progress
--format ParallelTests::RSpec::RuntimeLogger --out tmp/parallel_runtime_rspec.log


================================================
FILE: .rubocop.unhound.yml
================================================
Style/CollectionMethods:
  Enabled: true
  PreferredMethods:
    reduce:
    inject: 'reduce'
    find:
    detect: 'find'

Lint/AssignmentInCondition:
  Enabled: true

Lint/EachWithObjectArgument:
  Enabled: true

Lint/LiteralAsCondition:
  Description: Checks of literals used in conditions.
  Enabled: true

Lint/LiteralInInterpolation:
  Description: Checks for literals used in interpolation.
  Enabled: true

Lint/SuppressedException:
  Enabled: true

Metrics/AbcSize:
  Enabled: true

Metrics/ClassLength:
  Enabled: true

Metrics/CyclomaticComplexity:
  Enabled: true

Metrics/MethodLength:
  Enabled: true

Metrics/ModuleLength:
  Enabled: true

Metrics/ParameterLists:
  Enabled: true

Metrics/PerceivedComplexity:
  Enabled: true

Naming/AccessorMethodName:
  Enabled: true

Naming/FileName:
  Enabled: true

Style/Alias:
  Enabled: true
  EnforcedStyle: prefer_alias_method

Style/Documentation:
  Enabled: true

Style/DoubleNegation:
  Enabled: true

Style/EachWithObject:
  Enabled: true

Style/EmptyLiteral:
  Enabled: true

Style/GuardClause:
  Enabled: true

Style/IfUnlessModifier:
  Enabled: true

Style/ModuleFunction:
  Enabled: true

Style/OneLineConditional:
  Enabled: true

Style/PercentLiteralDelimiters:
  Enabled: true

Style/PerlBackrefs:
  Enabled: true

Style/SignalException:
  Enabled: true

Style/SingleLineBlockParams:
  Enabled: true

Style/SingleLineMethods:
  Enabled: true

Style/SpecialGlobalVars:
  Enabled: true

Style/TrailingCommaInArguments:
  Enabled: true

Style/TrailingCommaInArrayLiteral:
  Enabled: true

Style/TrailingCommaInHashLiteral:
  Enabled: true

Style/VariableInterpolation:
  Enabled: true

Style/WhenThen:
  Enabled: true


================================================
FILE: .rubocop.yml
================================================
inherit_from:
  - .rubocop.unhound.yml

AllCops:
  NewCops: enable
  Exclude:
    - 'bin/*'
    - 'db/seeds.rb'
    - 'db/schema.rb'
    - 'db/migrate/*'
    - 'vendor/bundle/**/*'
    - 'client/**/*'
  TargetRubyVersion: 3.0

Bundler/OrderedGems:
  Enabled: false

Layout/DotPosition:
  EnforcedStyle: trailing

Layout/EmptyLineAfterMagicComment:
  Enabled: false

Layout/FirstHashElementIndentation:
  EnforcedStyle: consistent

Layout/LineLength:
  Max: 120

Lint/ConstantDefinitionInBlock:
  Enabled: false

Metrics/AbcSize:
  Max: 20

Metrics/BlockLength:
  Enabled: false

Metrics/MethodLength:
  Max: 15
  CountAsOne: ['array', 'hash', 'heredoc']

Style/AsciiComments:
  AllowedChars: ['©', '├', '─', '└']

Style/ClassAndModuleChildren:
  EnforcedStyle: compact

Style/Documentation:
  Enabled: false

Style/EmptyMethod:
  Enabled: false

Style/HashAsLastArrayItem:
  EnforcedStyle: no_braces

Style/LambdaCall:
  Exclude:
    - '**/*.json.jbuilder'

Style/NumericPredicate:
  EnforcedStyle: comparison

Style/ParallelAssignment:
  Enabled: false

Style/RegexpLiteral:
  AllowInnerSlashes: true

Style/SignalException:
  EnforcedStyle: only_raise

Style/StringLiterals:
  EnforcedStyle: single_quotes

Style/SymbolArray:
  Enabled: false

Style/TernaryParentheses:
  EnforcedStyle: require_parentheses_when_complex

Style/WordArray:
  Enabled: false


================================================
FILE: .yardopts
================================================
--protected
--no-private
--embed-mixin ClassMethods
--markup markdown


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing

We have shifted our contributing guides to our [Wiki](https://github.com/Coursemology/coursemology2/wiki).
Please consult the guide before submitting a pull request to this repository.


================================================
FILE: Gemfile
================================================
# frozen_string_literal: true
source 'https://rubygems.org'

ruby '3.3.5'

# These gems are included in Ruby defaults for now,
# but they will have to be included separately in future versions.
gem 'ostruct'
gem 'csv'

# For Windows devs
gem 'tzinfo-data', platforms: [:mswin, :mswin64]

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 7.2.2'

# Use PostgreSQL for the backend
gem 'pg'

# Enables CORS configuration to allow sharing resources with client on another domain
gem 'rack-cors'

# Instance/Course settings
gem 'settings_on_rails', git: 'https://github.com/Coursemology/settings_on_rails'
# Manage read/unread status
gem 'unread', '~> 0.14.0'
# Extension for validating hostnames and domain names
gem 'validates_hostname'
# A Ruby state machine library
gem 'workflow'
gem 'workflow-activerecord', '>= 4.1', '< 7.0'
# Add creator_id and updater_id attributes to models
gem 'activerecord-userstamp', git: 'https://github.com/Coursemology/activerecord-userstamp.git'
# Allow actions to be deferred until after a record is committed.
gem 'after_commit_action'
# Allow declaring the calculated attributes of a record
gem 'calculated_attributes', git: 'https://github.com/Coursemology/calculated_attributes.git'
# For multiple table inheritance
# TODO: Figure out breaking changes in v2 as polymorphism is not working correctly.
gem 'active_record-acts_as', git: 'https://github.com/Coursemology/active_record-acts_as.git'
# Organise ActiveRecord model into a tree structure
gem 'edge'
# Upsert action for Postgres with validations
gem 'active_record_upsert', git: 'https://github.com/jesjos/active_record_upsert', ref: 'c3e07ae'
# Create pretty URLs and work with human-friendly strings
gem 'friendly_id'

# HTML Pipeline and dependencies
gem 'html-pipeline'
gem 'htmlentities'
gem 'sanitize', '>= 4.6.3'
gem 'rinku'
gem 'rouge', '~> 3'
gem 'ruby-oembed'

# to help obtaining app wide URI that uniquely identifies model instance
# (used in notify_identifier for NOTIFY/LISTEN to jobs)
gem 'globalid'

# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder'
# Slim as the templating language
gem 'slim-rails'
# Paginator for Rails
gem 'kaminari'
# Work with Docker
gem 'docker-api'

gem 'recaptcha'
gem 'rexml'
gem 'yajl-ruby', '~> 1.4'

# Page profiler
gem 'rack-mini-profiler'

gem 'redis-rails'

group :development do
  # Spring speeds up development by keeping your application running in the background.
  # Read more: https://github.com/rails/spring
  gem 'spring', platforms: [:ruby]
  gem 'listen'

  # Helps to prevent database slowdowns
  gem 'lol_dba', require: false

  # General cleanliness
  gem 'traceroute', require: false

  # bundle exec yardoc generates the API under doc/.
  # Use yard stats --list-undoc to find what needs documenting.
  gem 'yard', group: :doc
end

group :test do
  gem 'email_spec'
  gem 'rspec-html-matchers'
  gem 'should_not'
  gem 'shoulda-matchers'

  # Capybara for feature testing
  gem 'capybara'
  gem 'capybara-selenium'

  # Make screen shots in tests, helps with the debugging of JavaScript tests.
  gem 'capybara-screenshot'
end

group :development, :test do
  # Use RSpec for Behaviour testing
  gem 'rspec-rails', '~> 8'

  gem 'rubocop', '~> 1.86'

  # Factory Bot for factories
  # fix for https://github.com/thoughtbot/factory_bot/issues/1690
  gem 'factory_bot', '~> 6.6.0'
  gem 'factory_bot_rails'

  # Checks that all translations are used and defined
  gem 'i18n-tasks', require: false

  # Helps to prevent database consistency mistakes
  gem 'consistency_fail', require: false

  # Prevent N+1 queries.
  gem 'bullet', '>= 4.14.9'

  gem 'parallel_tests'

  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platform: :mri

  # Code coverage reporter and formatter
  gem 'simplecov'
  gem 'simplecov-lcov', '>= 0.8.0'

  gem 'dotenv-rails'
end

group :ci do
  gem 'rspec-retry'
  gem 'rspec_junit_formatter'
  gem 'rubocop-rails'
end

# This is used only when producing Production assets. Deals with things like minifying JavaScript
# source files/image assets.
group :assets do
  # Compress image assets
  gem 'image_optim_rails'
end

group :production, :test do
  # Puma will be our app server
  gem 'puma'
end

group :production, :test, :ci do
  gem 'aws-sdk-s3'
end

group :production do
  gem 'aws-sdk-cloudwatch'
  gem 'aws-sdk-core'

  # Use fog-aws as CarrierWave's storage provider
  gem 'fog-aws', '>= 3.19'
  gem 'flamegraph'
  gem 'stackprof'
  gem 'sidekiq', '~> 7.3.10'
  gem 'sidekiq-cron'
  gem 'rollbar', '>= 1.5.3'

  # better log format
  gem 'lograge'
  gem 'lograge-sql'
end

# Multitenancy
gem 'acts_as_tenant'

# Internationalization
gem 'http_accept_language'

# User authentication
gem 'devise', '4.9.4'
gem 'devise-multi_email'
gem 'keycloak'
gem 'jwt'

# Use cancancan for authorization
gem 'cancancan'

# Using CarrierWave for file uploads
gem 'carrierwave', '~> 3'
# Generate sequential filenames
gem 'filename'
# Required by CarrierWave, for image resizing
gem 'mini_magick'
# Library for reading and writing zip files
gem 'rubyzip', '~> 3.0', require: 'zip'
# Manipulating XML files, needed for programming evaluation test report parsing.
gem 'nokogiri', '>= 1.18.8'

# Polyglot support
gem 'coursemology-polyglot', git: 'https://github.com/Coursemology/polyglot'

# To assist with bulk inserts into database
gem 'activerecord-import', '>= 0.2.0'

gem 'record_tag_helper'
gem 'rails-controller-testing'

# WordNet corpus to obtain lemma form of words, for comprehension questions.
gem 'rwordnet', git: 'https://github.com/Coursemology/rwordnet'
gem 'loofah', '>= 2.2.1'
gem 'rails-html-sanitizer', '>= 1.0.4'

gem 'mimemagic', '0.4.3'
gem 'ffi', '>= 1.14.2'

# Retreival Augmented Generation (RAG) Support
gem 'pgvector'
gem 'neighbor'
gem 'langchainrb'
gem 'ruby-openai'
gem 'pdf-reader'
gem 'docx'


================================================
FILE: LICENSE
================================================
The MIT License (MIT)

http://opensource.org/licenses/MIT

Copyright (c) 2023 Coursemology.org

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


================================================
FILE: README.md
================================================
<!-- markdownlint-disable MD033 MD014 -->

# Coursemology [![CircleCI](https://circleci.com/gh/Coursemology/coursemology2.svg?style=svg)](https://circleci.com/gh/Coursemology/coursemology2)

[![Code Climate](https://codeclimate.com/github/Coursemology/coursemology2/badges/gpa.svg)](https://codeclimate.com/github/Coursemology/coursemology2)
[![codecov](https://codecov.io/gh/Coursemology/coursemology2/branch/master/graph/badge.svg)](https://codecov.io/gh/Coursemology/coursemology2)
[![Inline docs](http://inch-ci.org/github/Coursemology/coursemology2.svg?branch=master&style=flat-square)](http://inch-ci.org/github/Coursemology/coursemology2)
[![Slack](http://coursemology-slack.herokuapp.com/badge.svg)](http://coursemology-slack.herokuapp.com)

<a href="http://coursemology.org"><img src="https://raw.githubusercontent.com/Coursemology/coursemology.org/development/public/images/coursemology_logo_landscape_100.png" alt="Coursemology logo" title="Coursemology" align="right" /></a>

Coursemology is an open source gamified learning platform that enables educators to increase student engagement and make learning fun.

## Setting up Coursemology

### System Requirements

1. **Ruby** (= 3.3.5)
2. **Ruby on Rails** (= 7.2.3.1)
3. **PostgreSQL** (= 16) with **PGVector extension**
4. **ImageMagick** or **GraphicsMagick** (For [MiniMagick](https://github.com/minimagick/minimagick) - if PDF processing doesn't work for the import of scribing questions, download **Ghostscript**)
5. **Node.js** (v22 LTS)
6. **Yarn**
7. **Docker** (installed and running)
8. **Redis**

### Getting Started

We use Git submodules. Run the following command to initialize them before proceeding:

   ```sh
   $ git submodule update --init --recursive
   ```

Coursemology consists of three main components:
1. [Keycloak authentication provider](./authentication/README.md)
2. [Ruby on Rails application server](./app/README.md)
3. [React frontend client](./client/README.md)

Set up and run each component sequentially by following the linked documentation pages. As you proceed, open a new terminal window for each component after the previous component has been fully set up and started running.

Once each component has been set up and is running on their own terminals, you can access the app by visiting [http://localhost:8080](http://localhost:8080), and log in using the default user email and password:

email: `test@example.org`
password: `Coursemology!`

### Running using HTTPS locally

These commands should be run from the repository root directory, unless otherwise noted.

`lvh.me` is a public domain that resolves to `127.0.0.1`. It is used instead of `localhost` because browsers enforce stricter security policies on `localhost` that can break the OAuth redirect flow over HTTPS.

1. Generate a self-signed certificate and key for `lvh.me`:

   ```sh
   openssl req -x509 -newkey rsa:4096 -sha256 -days 365 -nodes \
     -keyout config/credentials/server.key \
     -out config/credentials/server.crt \
     -subj "/CN=lvh.me" \
     -addext "subjectAltName=DNS:lvh.me,DNS:*.lvh.me"
   ```

   Puma and the webpack dev server both use these files automatically on startup.

2. Update the Keycloak redirect URIs to use HTTPS:

   ```sh
   bundle exec rake "keycloak:push_redirect_uris[https://lvh.me:8080]"
   ```

3. Start the app server with the public hostname:

   ```sh
   RAILS_HOSTNAME=lvh.me:8080 RAILS_ENV=development bundle exec puma
   ```

4. Start the client in HTTPS mode (from the `client/` directory):

   ```sh
   yarn build:development-https
   ```

Access the app at `https://lvh.me:8080`. Your browser will show a certificate warning for the self-signed cert — ignore it or add a security exception.

#### Reverting to HTTP

1. Remove the certificate files so Puma falls back to HTTP:

   ```sh
   rm config/credentials/server.crt config/credentials/server.key
   ```

2. Restore the Keycloak redirect URIs:

   ```sh
   bundle exec rake "keycloak:push_redirect_uris"
   ```

3. Restart both the app server and client using the standard commands.


## Found Boogs?

Create an issue on the Github [issue tracker](https://github.com/Coursemology/coursemology2/issues) or come talk to us over at our [Slack channels](https://coursemology-slack.herokuapp.com/).

## Contributing

We welcome contributions to Coursemology! Check out the [issue tracker](https://github.com/coursemology/coursemology2/issues) and pick something you'll like to work on. Please read our [Contributor's Guide](https://github.com/Coursemology/coursemology2/blob/master/CONTRIBUTING.md) for guidance on our conventions.

If you are a student from NUS Computing looking for an FYP project, do check with [Prof Ben Leong](http://www.comp.nus.edu.sg/~bleong/).

## License

Copyright (c) 2015-2023 Coursemology.org. This software is licensed under the MIT License.

## Using Coursemology

You're more than welcome to use Coursemology for your own school or organization. If you need more help, [join](http://coursemology-slack.herokuapp.com/) our Slack channel to reach our core developers.

We are actively running [Coursemology](https://coursemology.org) and can provide free use of our infrastructure on a case by case basis. Please contact [Prof Ben Leong](http://www.comp.nus.edu.sg/~bleong/) if you would like to explore this option.

## Acknowledgments

The Coursemology.org Project was made possible by a number of teaching development grants from the National University of Singapore over the years. This project is currently supported by the [AI Centre for Educational Technologies](https://www.aicet.aisingapore.org/).


================================================
FILE: Rakefile
================================================
# frozen_string_literal: true
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.

require File.expand_path('config/application', __dir__)

# Development dependencies, may fail. See Gemfile.
begin
  require 'lol_dba'
  require 'traceroute'
rescue LoadError # rubocop:disable Lint/SuppressedException
end

Rails.application.load_tasks


================================================
FILE: app/README.md
================================================
# Coursemology App Server

Coursemology uses [Ruby on Rails](http://rubyonrails.org/) as its backend app server. This [guide](https://gorails.com/setup/) written by the awesome people at GoRails should help you to get started on Ruby on Rails (however, be careful about the Rails version you are going to install here, and make sure your system meets its requirements).

## Getting Started

These commands should be run with the repository root directory (one level up from where this README file is) as the working directory.

1. Download bundler to install dependencies

   ```sh
   gem install bundler:2.5.9
   ```

2. Install ruby dependencies

   ```sh
   bundle config set --local without 'ci:production'
   bundle install
   ```

3. Create and seed the database

   ```sh
   bundle exec rake db:setup
   ```

4. Initialize .env file

   ```sh
   cp env .env
   ```

   You may need to add specific API keys (such as the [GOOGLE_RECAPTCHA_SITE_KEY](https://developers.google.com/recaptcha/docs/faq#id-like-to-run-automated-tests-with-recaptcha.-what-should-i-do)) to the .env files for testing specific features.

5. To start the app server, run

   ```
   bundle exec rails s -p 3000
   ```

## Configuration

### Multi Tenancy

To make sure that multi tenancy works correctly for you, change the default host in `config/application.rb` before deploying:

```ruby
config.x.default_host = 'your_domain.com'
```

### Opening Reminder Emails

Email reminders for items which are about to start are sent via a cronjob which should be run once an hour. See [config/initializers/sidekiq.rb](../config/initializers/sidekiq.rb) and [config/schedule.yml](../config/schedule.yml) for sample configuration which assumes that the [Sidekiq](https://github.com/mperham/sidekiq) and [Sidekiq-Cron](https://github.com/ondrejbartas/sidekiq-cron) gems are used.

If you use a different job scheduler, edit those files so your favourite job scheduler invokes the `ConsolidatedItemEmailJob` job once an hour.

================================================
FILE: app/assets/config/manifest.js
================================================


================================================
FILE: app/channels/application_cable/channel.rb
================================================
# frozen_string_literal: true
class ApplicationCable::Channel < ActionCable::Channel::Base
  include ApplicationCableMultitenancyConcern

  protected

  def request
    ActionDispatch::Request.new(connection.env)
  end

  def session
    request.session
  end

  def ip_address_and_user_agent
    ip_address = request.remote_ip
    user_agent = request.headers['User-Agent']
    [ip_address, user_agent]
  end
end


================================================
FILE: app/channels/application_cable/connection.rb
================================================
# frozen_string_literal: true
class ApplicationCable::Connection < ActionCable::Connection::Base
  identified_by :current_user, :current_session_id

  include ApplicationCableAuthenticationConcern

  def connect
    self.current_user = current_user_from_token || reject_unauthorized_connection
    self.current_session_id = retrieve_current_session_id
  end
end


================================================
FILE: app/channels/concerns/application_cable_ability_concern.rb
================================================
# frozen_string_literal: true
module ApplicationCableAbilityConcern
  extend ActiveSupport::Concern

  included do
    before_subscribe :load_current_ability
  end

  def current_ability
    @current_ability ||= Ability.new(current_user, current_course, current_course_user, nil, current_session_id)
  end

  def can?(*args)
    current_ability.can?(*args)
  end

  def cannot?(*args)
    current_ability.cannot?(*args)
  end

  alias_method :load_current_ability, :current_ability
end


================================================
FILE: app/channels/concerns/application_cable_authentication_concern.rb
================================================
# frozen_string_literal: true
module ApplicationCableAuthenticationConcern
  def current_user_from_token
    token = authenticate_token
    User.joins(:emails).where('user_emails.email = ?', token[:email]).first if token
  end

  def retrieve_current_session_id
    @current_session_id ||= current_decoded_token&.[](:session_state)
  end

  def current_decoded_token
    @current_decoded_token ||= @decoded_token&.decoded_token
  end

  private

  def authenticate_token
    access_token = token_from_request

    @decoded_token ||= Authentication::AuthenticationService.validate_token(access_token, :local)

    return nil if @decoded_token.error

    @decoded_token.decoded_token
  end

  def token_from_request
    request.params['token']
  end
end


================================================
FILE: app/channels/concerns/application_cable_component_concern.rb
================================================
# frozen_string_literal: true
module ApplicationCableComponentConcern
  extend ActiveSupport::Concern

  included do
    before_subscribe :load_current_component_host
    before_subscribe :check_component
  end

  def current_component_host
    @current_component_host ||= Course::ControllerComponentHost.new(self)
  end

  private

  alias_method :load_current_component_host, :current_component_host

  def component
    raise ComponentNotFoundError
  end

  # TODO: Raise and use `rescue_from` in `included` once in Rails 6.1+
  def check_component
    reject unless component
  rescue ComponentNotFoundError
    reject
  end
end


================================================
FILE: app/channels/concerns/application_cable_course_concern.rb
================================================
# frozen_string_literal: true
module ApplicationCableCourseConcern
  extend ActiveSupport::Concern

  included do
    before_subscribe :find_course
  end

  def find_course
    course_id = params[:course_id]
    reject unless @course ||= Course.find(course_id)
  end

  def current_course
    @course
  end

  def current_course_user
    return nil unless current_course

    @current_course_user ||= current_course.course_users.find_by(user: current_user)
  end
end


================================================
FILE: app/channels/concerns/application_cable_multitenancy_concern.rb
================================================
# frozen_string_literal: true
module ApplicationCableMultitenancyConcern
  extend ActiveSupport::Concern
  include ApplicationMultitenancy

  included do
    set_current_tenant_through_filter
    before_subscribe :deduce_and_set_current_tenant
  end
end


================================================
FILE: app/channels/course/channel.rb
================================================
# frozen_string_literal: true
#
# The base channel for all `Course`-related channels. Subclasses of this channel
# must receive `course_id` as a parameter in the subscription request message.
#
# By default, it will expose, in chronological order:
# - `current_course`
# - `current_course_user`
# - `current_component_host`
# - `current_ability`
# - `can?` and `cannot?` from `CanCan::Ability`
#
# Note that the more inclusions are added, the more queries and operations are executed
# during subscriptions or actions, depending on the callbacks used in each included modules.
# These features are broken up into concerns so that future channels can opt in to only the
# capabilities they need.
class Course::Channel < ApplicationCable::Channel
  include ApplicationCableCourseConcern
  include ApplicationCableComponentConcern
  include ApplicationCableAbilityConcern
end


================================================
FILE: app/channels/course/monitoring/heartbeat_channel.rb
================================================
# frozen_string_literal: true
class Course::Monitoring::HeartbeatChannel < Course::Channel
  ACTIONS = { next: :next, terminate: :terminate, flushed: :flushed }.freeze

  def subscribed
    session_id = params[:session_id]
    @session = Course::Monitoring::Session.find(session_id)
    @monitor = @session.monitor
    reject unless @session.present? && can?(:read, @session) && listening?

    stream_for @session
  end

  def pulse(data)
    @monitor.reload && @session.reload

    unless can_pulse? && listening?
      # TODO: Use `stop_stream_from @session` once in Rails 6.1+
      # In particular, use `stop_stream_from @session unless can_pulse?`
      broadcast_terminate
      broadcast_terminate_to_live_monitoring
      return
    end

    ip_address, user_agent = ip_address_and_user_agent
    timestamp = data['timestamp']

    heartbeat = Course::Monitoring::Heartbeat.new(
      session: @session,
      user_agent: user_agent,
      ip_address: ip_address,
      generated_at: time_from(timestamp),
      seb_payload: data['sebPayload']
    )

    return unless heartbeat.save

    broadcast_next timestamp, rand(@monitor.min_interval_ms..@monitor.max_interval_ms)
    broadcast_pulse_to_live_monitoring heartbeat
  end

  def flush(data)
    ip_address, user_agent = ip_address_and_user_agent
    heartbeats_data = filter_and_sort_heartbeats(data['heartbeats'])

    heartbeats = heartbeats_data.map do |heartbeat_data|
      {
        session_id: @session.id,
        user_agent: user_agent,
        ip_address: ip_address,
        generated_at: time_from(heartbeat_data['timestamp']),
        stale: true,
        created_at: Time.zone.now,
        updated_at: Time.zone.now
      }
    end

    flushed = Course::Monitoring::Heartbeat.insert_all(heartbeats)
    broadcast_flushed heartbeats_data.first['timestamp'], heartbeats_data.last['timestamp'] if flushed
  end

  class << self
    def broadcast_terminate(session)
      broadcast_to session, { action: ACTIONS[:terminate] }
    end
  end

  private

  def listening?
    @monitor.enabled? && @session.listening?
  end

  def filter_and_sort_heartbeats(heartbeats)
    start_time = @session.created_at
    end_time = listening? ? @session.expiry : @session.heartbeats.last&.generated_at

    heartbeats.filter { |h| time_from(h['timestamp']).between?(start_time, end_time) }.sort_by { |h| h['timestamp'] }
  end

  def time_from(milliseconds)
    Time.zone.at(0, milliseconds, :millisecond)
  end

  def broadcast_pulse_to_live_monitoring(heartbeat)
    Course::Monitoring::LiveMonitoringChannel.broadcast_pulse_to @monitor, @session, {
      sessionId: @session.id,
      status: @session.status,
      misses: @session.misses,
      lastHeartbeatAt: heartbeat.generated_at,
      isValid: valid_heartbeat?(heartbeat)
    }.compact
  end

  def broadcast_terminate_to_live_monitoring
    Course::Monitoring::LiveMonitoringChannel.broadcast_terminate @monitor, @session
  end

  def broadcast_terminate
    Course::Monitoring::HeartbeatChannel.broadcast_terminate @session
  end

  def broadcast_flushed(first_timestamp, last_timestamp)
    Course::Monitoring::HeartbeatChannel.broadcast_to @session, {
      action: ACTIONS[:flushed],
      from: first_timestamp,
      to: last_timestamp
    }
  end

  def broadcast_next(received_timestamp, next_timeout)
    Course::Monitoring::HeartbeatChannel.broadcast_to @session, {
      action: ACTIONS[:next],
      nextTimeout: next_timeout,
      received: received_timestamp
    }
  end

  def component
    current_component_host[:course_monitoring_component]
  end

  def can_pulse?
    @can_pulse ||= can? :create, Course::Monitoring::Heartbeat.new(session: @session)
  end

  def assessment_id
    @assessment_id ||= @monitor.assessment.id
  end

  def valid_heartbeat?(heartbeat)
    heartbeat.valid_heartbeat? || Course::Assessment::MonitoringService.unblocked?(assessment_id, session)
  end
end


================================================
FILE: app/channels/course/monitoring/live_monitoring_channel.rb
================================================
# frozen_string_literal: true
class Course::Monitoring::LiveMonitoringChannel < Course::Channel
  include Course::UsersHelper

  DEFAULT_VIEW_HEARTBEATS_LIMIT = 10
  ACTIONS = { pulse: :pulse, terminate: :terminate, viewed: :viewed, watch: :watch }.freeze

  def subscribed
    monitor_id = params[:monitor_id]
    @monitor = Course::Monitoring::Monitor.find(monitor_id)
    reject unless @monitor.present? && can?(:read, @monitor)

    stream_for @monitor
  end

  class << self
    def broadcast_pulse_to(monitor, session, snapshot)
      broadcast_from monitor, :pulse, { userId: session.creator_id, snapshot: snapshot }
    end

    def broadcast_terminate(monitor, session)
      broadcast_from monitor, :terminate, session.creator_id
    end

    def broadcast_from(monitor, action, payload)
      broadcast_to monitor, { action: ACTIONS[action], payload: payload }.compact
    end
  end

  def watch
    active_snapshots = active_sessions_snapshots
    students = current_course.students.order(:phantom, :name)

    snapshots = students.to_h do |student|
      user_id = student.user_id
      [user_id, active_snapshots[user_id] || { userName: student.name }]
    end

    broadcast_watch students.map(&:user_id), snapshots, groups
  end

  def view(data)
    session_id, limit = data['session_id'], data['limit'] || DEFAULT_VIEW_HEARTBEATS_LIMIT
    return unless (session = @monitor.sessions.find(session_id))

    recent_heartbeats = (limit == -1 ? session.heartbeats : session.heartbeats.last(limit)).map do |heartbeat|
      {
        stale: heartbeat.stale,
        userAgent: heartbeat.user_agent,
        ipAddress: heartbeat.ip_address,
        generatedAt: heartbeat.generated_at,
        isValid: heartbeat.valid_heartbeat?,
        sebPayload: heartbeat.seb_payload
      }.compact
    end

    broadcast_viewed recent_heartbeats
  end

  private

  def active_sessions_snapshots
    @monitor.sessions.includes(:heartbeats, :creator).to_h do |session|
      last_heartbeat = session.heartbeats.last

      course_user = course_users_hash[session.creator_id]
      # This technically shouldn't happen, but can happen if someone is removed from
      # the course after they finish a monitored assessment.
      next [nil, nil] unless course_user

      snapshot = {
        sessionId: session.id,
        status: session.status,
        misses: session.misses,
        lastHeartbeatAt: last_heartbeat&.generated_at,
        isValid: last_heartbeat&.valid_heartbeat?,
        userName: course_user.name,
        submissionId: submission_ids_hash[session.creator_id],
        stale: last_heartbeat&.stale
      }.compact

      [session.creator_id, snapshot]
    end.compact
  end

  def groups
    current_course.groups.ordered_by_name.includes(:group_category, :course_users).map do |group|
      {
        id: group.id,
        name: group.name,
        category: group.group_category.name,
        userIds: group.course_users&.filter_map { |course_user| course_user.user_id if course_user.student? }
      }
    end
  end

  def broadcast(action, payload)
    Course::Monitoring::LiveMonitoringChannel.broadcast_from @monitor, action, payload
  end

  def broadcast_watch(users, snapshots, groups)
    broadcast :watch, {
      userIds: users,
      snapshots: snapshots,
      groups: groups,
      monitor: {
        maxIntervalMs: @monitor.max_interval_ms,
        offsetMs: @monitor.offset_ms,
        validates: @monitor.browser_authorization?,
        browserAuthorizationMethod: @monitor.browser_authorization_method
      }
    }
  end

  def broadcast_viewed(recent_heartbeats)
    broadcast :viewed, recent_heartbeats
  end

  def component
    current_component_host[:course_monitoring_component]
  end

  def course_users_hash
    @course_users_hash ||= preload_course_users_hash(current_course)
  end

  def submission_ids_hash
    @submission_ids_hash ||= @monitor.assessment.submissions.to_h do |submission|
      [submission.creator_id, submission.id]
    end
  end
end


================================================
FILE: app/controllers/announcements_controller.rb
================================================
# frozen_string_literal: true
class AnnouncementsController < ApplicationController
  load_resource :announcement, class: 'GenericAnnouncement', only: :mark_as_read, id_param: :announcement_id

  def index
    respond_to do |format|
      format.json do
        announcements = requesting_unread? ? unread_global_announcements : global_announcements
        @announcements = announcements.includes(:creator)
      end
    end
  end

  def mark_as_read
    if current_user
      @announcement.mark_as_read! for: current_user
      head :ok
    else
      head :no_content
    end
  end

  protected

  def publicly_accessible?
    requesting_unread? || action_name.to_sym == :mark_as_read
  end

  private

  def requesting_unread?
    params[:unread] == 'true'
  end
end


================================================
FILE: app/controllers/application_controller.rb
================================================
# frozen_string_literal: true

class ApplicationController < ActionController::Base
  # Prevent CSRF attacks by providing a null session when the token is missing from the request.
  protect_from_forgery(prepend: true, with: :exception)

  include ApplicationControllerMultitenancyConcern
  include ApplicationAuthenticationConcern
  include ApplicationComponentsConcern
  include ApplicationInternationalizationConcern
  include ApplicationUserConcern
  include ApplicationUserTimeZoneConcern
  include ApplicationInstanceUserConcern
  include ApplicationAbilityConcern
  include ApplicationAnnouncementsConcern
  include ApplicationPaginationConcern

  rescue_from AuthenticationError, with: :handle_authentication_error
  rescue_from IllegalStateError, with: :handle_illegal_state_error
  rescue_from ActionController::InvalidAuthenticityToken, with: :handle_csrf_error

  def index
  end

  protected

  # Runs the provided block with Bullet disabled.
  #
  # @note Bullet will not be enabled again after this block returns until the next Rack request.
  #   The block syntax is in anticipation of Bullet eventually supporting temporary disabling,
  #   which currently does not work. See flyerhzm/bullet#247.
  def without_bullet
    old_bullet_enable = Bullet.enable?
    Bullet.enable = false
    yield
  ensure
    Bullet.enable = old_bullet_enable
  end

  private

  def handle_illegal_state_error(exception)
    @exception = exception
    render json: { error: exception.message }, status: :unprocessable_entity
  end

  def handle_csrf_error(exception)
    @exception = exception
    render json: { error: "Can't verify CSRF token authenticity - #{exception.message}" }, status: :forbidden
  end

  def handle_authentication_error(exception)
    cookies.delete(:access_token)
    @exception = exception
    render json: { error: exception.message }, status: :unauthorized
  end

  # lograge
  def append_info_to_payload(payload)
    super
    payload[:level] = case payload[:status]
                      when 200
                        'INFO'
                      when 302
                        'WARN'
                      else
                        'ERROR'
                      end
    payload[:remote_ip] = request.ip
    payload[:current_user_id] = current_user.id if current_user.present?
  end
end


================================================
FILE: app/controllers/attachment_references_controller.rb
================================================
# frozen_string_literal: true
class AttachmentReferencesController < ApplicationController
  load_resource :attachment_reference

  def create
    attachment = Attachment.find_or_create_by(file: file_params[:file]) if file_params[:file]
    return unless attachment

    @attachment_reference = AttachmentReference.create(attachment: attachment, name: file_params[:name])
  end

  def show
    name = @attachment_reference.name
    uploader = @attachment_reference.attachment.file_upload

    # if case is only for local storage, since there is no S3 URL to redirect to. In prod, it always goes to else.
    if uploader.class.storage == CarrierWave::Storage::File # under Dev/test, config.storage = :file
      raise ActiveRecord::RecordNotFound, "File not found at path: #{uploader.path}" unless uploader.file&.exists?

      send_file uploader.path,
                filename: name,
                type: uploader.content_type
    else
      redirect_to @attachment_reference.url(filename: name), allow_other_host: true
    end
  end

  private

  def file_params
    params.permit(:file, :name)
  end
end


================================================
FILE: app/controllers/components/course/achievements_component.rb
================================================
# frozen_string_literal: true
class Course::AchievementsComponent < SimpleDelegator
  include Course::ControllerComponentHost::Component

  def self.gamified?
    true
  end

  def sidebar_items
    [
      {
        key: :achievements,
        icon: :achievement,
        weight: 4,
        path: course_achievements_path(current_course)
      }
    ]
  end
end


================================================
FILE: app/controllers/components/course/announcements_component.rb
================================================
# frozen_string_literal: true
class Course::AnnouncementsComponent < SimpleDelegator
  include Course::ControllerComponentHost::Component
  include Course::UnreadCountsConcern

  def sidebar_items
    main_sidebar_items + settings_sidebar_items
  end

  private

  def main_sidebar_items
    [
      {
        key: :announcements,
        icon: :announcement,
        title: settings.title,
        weight: 1,
        path: course_announcements_path(current_course),
        unread: unread_announcements_count
      }
    ]
  end

  def settings_sidebar_items
    [
      {
        key: self.class.key,
        title: settings.title,
        type: :settings,
        weight: 4,
        path: course_admin_announcements_path(current_course)
      }
    ]
  end
end


================================================
FILE: app/controllers/components/course/assessments_component.rb
================================================
# frozen_string_literal: true
class Course::AssessmentsComponent < SimpleDelegator
  include Course::ControllerComponentHost::Component
  include Course::UnreadCountsConcern

  def self.lesson_plan_item_actable_names
    [Course::Assessment.name]
  end

  def sidebar_items
    main_sidebar_items + admin_sidebar_items + admin_settings_items
  end

  private

  def main_sidebar_items
    assessment_categories + assessment_submissions
  end

  def assessment_categories
    current_course.assessment_categories.select(&:persisted?).map do |category|
      {
        key: "assessments_#{category.id}",
        icon: :assessment, # TODO: category.icon in db that user can select and set
        title: category.title,
        weight: 2,
        path: course_assessments_path(current_course, category: category)
      }
    end
  end

  def assessment_submissions
    [
      {
        key: :assessments_submissions,
        icon: :submission,
        weight: 3,
        path: course_submissions_path(current_course),
        unread: pending_assessment_submissions_count
      }
    ]
  end

  def admin_sidebar_items
    return [] unless can?(:read, Course::Assessment::Skill.new(course: current_course))

    [
      {
        key: :sidebar_assessments_skills,
        icon: :skills,
        type: :admin,
        weight: 8,
        path: course_assessments_skills_path(current_course)
      }
    ]
  end

  def admin_settings_items
    [
      {
        key: self.class.key,
        type: :settings,
        weight: 5,
        path: course_admin_assessments_path(current_course)
      }
    ]
  end
end


================================================
FILE: app/controllers/components/course/codaveri_component.rb
================================================
# frozen_string_literal: true
class Course::CodaveriComponent < SimpleDelegator
  include Course::ControllerComponentHost::Component

  def sidebar_items
    settings_sidebar_items
  end

  private

  def settings_sidebar_items
    [
      {
        key: self.class.key,
        type: :settings,
        weight: 6,
        path: course_admin_codaveri_path(current_course)
      }
    ]
  end
end


================================================
FILE: app/controllers/components/course/controller_component_host.rb
================================================
# frozen_string_literal: true
#
# The course component framework isolates features as components. The intent is to allow
# each feature to be enabled / disabled indepenedently within a course.
#
# When creating a component:
#
# - Your component class should `include Course::ControllerComponentHost::Component`.
# This injects the methods found in the {Course::ControllerComponentHost::Sidebar Sidebar}
# and {Course::ControllerComponentHost::Settings Settings} modules
# into the component. Override these methods to customise your component.
#
# - Your component class's initializer should take in the component host's context (a controller)
# as its only argument. You may do this by having your component inherit from `SimpleDelegator`.
# This allows you to call methods on the given context from your component, e.g. a call to
# {Course::Controller#current_course} will be delegated to the controller.
#
# - If your component has settings, you may define a settings model for it.
# (See {Course::ControllerComponentHost::Settings::ClassMethods#settings_class} for
# conventions to follow.)
#
# - You will also need to associate controllers for a component with the component class
# in order for it to be automatically enabled / disabled based on the course's settings
# (see {Course::ComponentController}).
#
class Course::ControllerComponentHost
  include Componentize

  module Sidebar
    extend ActiveSupport::Concern

    # Get the sidebar items and admin menu tab items from this component.
    #
    # @return [Array] An array of hashes containing the sidebar items exposed by this component.
    #   See {Course::ControllerComponentHost#sidebar_items} for the format.
    def sidebar_items
      []
    end
  end

  module Settings
    extend ActiveSupport::Concern

    delegate :enabled_by_default?, to: :class
    delegate :key, to: :class
    delegate :settings_class, to: :class

    module ClassMethods
      # @return [Boolean] the default enabled status of the component
      def enabled_by_default?
        true
      end

      # Unique key of the component, to serve as the key in settings and translations.
      #
      # @return [Symbol] the key
      def key
        name.underscore.tr('/', '_').to_sym
      end

      # Override this to customise the display name of the component.
      # The module name is the default display name.
      #
      # @return [String]
      def display_name
        name
      end

      # @return [Boolean] The gamfied status of the component. If true, the component will be
      #   disabled when the gamified flag in the course is false. Value is false by default.
      def gamified?
        false
      end

      # @return [Boolean] true if component can be disabled (or enabled) for individual courses.
      #   Otherwise, the component can only perhaps be disabled instance-wide.
      def can_be_disabled_for_course?
        true
      end

      # Returns a model which the current component can use to interface with its persisted
      # settings. The class initializer should take an instance of the component as its only
      # argument.
      #
      # Example:
      # If the component Course::FoobarComponent has settings, define a class
      # Course::Settings::FoobarComponent in the file
      # app/models/course/settings/foobar_component.rb.
      #
      # @return [Class] The settings interface class
      # @return [nil] if the class does not exist
      def settings_class
        @settings_class ||= "Course::Settings::#{name.demodulize}".safe_constantize
      end

      # Override in the component definition with the names of the actable types
      # if the component adds lesson plan items.
      # A component can specify multiple actable types for display on the lesson plan page.
      #
      # @return [Array<String>] actable types as an array of strings
      def lesson_plan_item_actable_names
        []
      end
    end

    # The settings interface instance for this component.
    #
    # @return An instance of the settings interface for the current component.
    # @return [nil] if the settings interface is not implemented.
    def settings
      @settings ||= settings_class&.new(self)
    end
  end

  # Open the Componentize Base Component.
  const_get(:Component).module_eval do
    const_set(:ClassMethods, ::Module.new) unless const_defined?(:ClassMethods)

    include Sidebar
    include Settings
  end

  # Eager load all the components declared.
  eager_load_components(File.join(__dir__, '../'))

  # Initializes the component host instance. This loads all components.
  #
  # @param context The context to execute all component instance methods on.
  def initialize(context)
    @context = context
    components
  end

  # @return [Array<Class>] Classes of effectively enabled components.
  def enabled_components
    @enabled_components ||= @context.current_course.enabled_components
  end

  # Instantiates the enabled components.
  #
  # @return [Array] The instantiated enabled components.
  def components
    @components ||= enabled_components.map { |component| component.new(@context) }
  end

  # Gets the component instance with the given key.
  #
  # @param [String|Symbol] component_key The key of the component to find.
  # @return [Object] The component with the given key.
  # @return [nil] If component is not enabled.
  def [](component_key)
    validate_component_key!(component_key)
    components.find { |component| component.key == component_key.to_sym }
  end

  # Gets the sidebar elements.
  #
  # Sidebar elements have the given format:
  #
  # ```
  #   {
  #      key: :item_key, # The unique key of the item to identify it among others. Can be nil if
  #                      # there is no need to distinguish between items.
  #                      # +normal+ type elements must have a key because their ordering is a
  #                      # user setting.
  #      title: 'Sidebar Item Title',
  #      type: :admin, # Will be considered as +:normal+ if not set. Currently +:normal+, +:admin+,
  #                    # and +:settings+ are used.
  #      weight: 100, # The default weight of the item. Larger weights (heavier items) sink.
  #      path: path_to_the_component,
  #      unread: 0 # Number of unread items. Can be +nil+, if not needed.
  #   }
  # ```
  #
  # The elements are rendered on all Course controller subclasses as part of a nested template.
  def sidebar_items
    @sidebar_items ||= components.flat_map(&:sidebar_items)
  end

  private

  # @param [String|Symbol] component_key The key of the component to validate.
  def validate_component_key!(key)
    raise ArgumentError, "Invalid component key: #{key}" unless component_key_set.include?(key.to_sym)
  end

  def component_key_set
    @component_key_set ||= Course::ControllerComponentHost.components.map(&:key).to_set
  end
end


================================================
FILE: app/controllers/components/course/discussion/topics_component.rb
================================================
# frozen_string_literal: true
class Course::Discussion::TopicsComponent < SimpleDelegator
  include Course::ControllerComponentHost::Component
  include Course::UnreadCountsConcern

  def sidebar_items
    main_sidebar_items + settings_sidebar_items
  end

  private

  def main_sidebar_items
    [
      {
        key: :discussion_topics,
        icon: :comments,
        title: settings.title,
        weight: 5,
        path: course_topics_path(current_course),
        unread: unread_comments_count
      }
    ]
  end

  def settings_sidebar_items
    [
      {
        key: :sidebar_discussion_topics,
        title: settings.title,
        type: :settings,
        weight: 7,
        path: course_admin_topics_path(current_course)
      }
    ]
  end
end


================================================
FILE: app/controllers/components/course/duplication_component.rb
================================================
# frozen_string_literal: true
class Course::DuplicationComponent < SimpleDelegator
  include Course::ControllerComponentHost::Component

  def sidebar_items
    return [] unless can?(:duplicate_from, current_course)

    [
      {
        key: :admin_duplication,
        icon: :duplication,
        type: :admin,
        weight: 5,
        path: course_duplication_path(current_course)
      }
    ]
  end
end


================================================
FILE: app/controllers/components/course/experience_points_component.rb
================================================
# frozen_string_literal: true
class Course::ExperiencePointsComponent < SimpleDelegator
  include Course::ControllerComponentHost::Component

  def self.gamified?
    true
  end

  def sidebar_items
    return [] unless can_create_experience_points_record?

    [
      {
        key: :sidebar_experience_points,
        icon: :experience,
        type: :admin,
        weight: 4,
        path: course_experience_points_records_path(current_course)
      }
    ]
  end

  private

  def can_create_experience_points_record?
    can?(:create, Course::ExperiencePointsRecord.
                    new(course_user: CourseUser.new(course: current_course)))
  end
end


================================================
FILE: app/controllers/components/course/forums_component.rb
================================================
# frozen_string_literal: true
class Course::ForumsComponent < SimpleDelegator
  include Course::ControllerComponentHost::Component
  include Course::UnreadCountsConcern

  def sidebar_items
    main_sidebar_items + settings_sidebar_items
  end

  private

  def main_sidebar_items
    [
      {
        key: :forums,
        icon: :forum,
        title: settings.title,
        weight: 10,
        path: course_forums_path(current_course),
        unread: unread_forum_topics_count
      }
    ]
  end

  def settings_sidebar_items
    [
      {
        key: self.class.key,
        title: settings.title,
        type: :settings,
        weight: 11,
        path: course_admin_forums_path(current_course)
      }
    ]
  end
end


================================================
FILE: app/controllers/components/course/groups_component.rb
================================================
# frozen_string_literal: true
class Course::GroupsComponent < SimpleDelegator
  include Course::ControllerComponentHost::Component
  include Course::Group::GroupManagerConcern

  def sidebar_items
    return [] unless show_group_sidebar_item?

    [
      {
        key: self.class.key,
        icon: :groups,
        type: :admin,
        weight: 7,
        path: group_category_url
      }
    ]
  end

  private

  def group_category_url
    if viewable_group_categories.empty?
      course_group_categories_path(current_course)
    else
      course_group_category_path(current_course, viewable_group_categories.ordered_by_name.first)
    end
  end

  # Only show if the user can view all categories or can manage any particular group.
  def show_group_sidebar_item?
    category = Course::GroupCategory.new(course: current_course)
    return true if can?(:read, category)

    !manageable_groups.empty?
  end
end


================================================
FILE: app/controllers/components/course/koditsu_platform_component.rb
================================================
# frozen_string_literal: true
class Course::KoditsuPlatformComponent < SimpleDelegator
  include Course::ControllerComponentHost::Component

  def self.enabled_by_default?
    false
  end
end


================================================
FILE: app/controllers/components/course/leaderboard_component.rb
================================================
# frozen_string_literal: true
class Course::LeaderboardComponent < SimpleDelegator
  include Course::ControllerComponentHost::Component

  def self.gamified?
    true
  end

  def sidebar_items
    main_sidebar_items + settings_sidebar_items
  end

  private

  def main_sidebar_items
    [
      {
        key: :leaderboard,
        icon: :leaderboard,
        title: settings.title,
        weight: 6,
        path: course_leaderboard_path(current_course)
      }
    ]
  end

  def settings_sidebar_items
    [
      {
        key: self.class.key,
        title: settings.title,
        type: :settings,
        weight: 8,
        path: course_admin_leaderboard_path(current_course)
      }
    ]
  end
end


================================================
FILE: app/controllers/components/course/learning_map_component.rb
================================================
# frozen_string_literal: true
class Course::LearningMapComponent < SimpleDelegator
  include Course::ControllerComponentHost::Component

  def self.enabled_by_default?
    false
  end

  def sidebar_items
    [
      {
        key: :learning_map,
        icon: :map,
        weight: 5,
        path: course_learning_map_path(current_course)
      }
    ]
  end
end


================================================
FILE: app/controllers/components/course/lesson_plan_component.rb
================================================
# frozen_string_literal: true
class Course::LessonPlanComponent < SimpleDelegator
  include Course::ControllerComponentHost::Component

  def self.lesson_plan_item_actable_names
    [Course::LessonPlan::Event.name]
  end

  def sidebar_items
    main_sidebar_items + settings_sidebar_items
  end

  private

  def main_sidebar_items
    [
      {
        key: :lesson_plan,
        icon: :lessonPlan,
        weight: 8,
        path: course_lesson_plan_path(current_course)
      }
    ]
  end

  def settings_sidebar_items
    [
      {
        key: self.class.key,
        type: :settings,
        weight: 9,
        path: course_admin_lesson_plan_path(current_course)
      }
    ]
  end
end


================================================
FILE: app/controllers/components/course/levels_component.rb
================================================
# frozen_string_literal: true
class Course::LevelsComponent < SimpleDelegator
  include Course::ControllerComponentHost::Component

  def self.gamified?
    true
  end

  def sidebar_items
    return [] unless can?(:read, Course::Level.new(course: current_course))

    [
      {
        key: self.class.key,
        icon: :levels,
        type: :admin,
        weight: 6,
        path: course_levels_path(current_course)
      }
    ]
  end
end


================================================
FILE: app/controllers/components/course/materials_component.rb
================================================
# frozen_string_literal: true
class Course::MaterialsComponent < SimpleDelegator
  include Course::ControllerComponentHost::Component

  def sidebar_items
    main_sidebar_items + settings_sidebar_items
  end

  private

  def main_sidebar_items
    [
      {
        key: :materials,
        icon: :material,
        title: settings.title,
        weight: 9,
        path: course_material_folders_path(current_course)
      }
    ]
  end

  def settings_sidebar_items
    [
      {
        key: self.class.key,
        title: settings.title,
        type: :settings,
        weight: 10,
        path: course_admin_materials_path(current_course)
      }
    ]
  end
end


================================================
FILE: app/controllers/components/course/monitoring_component.rb
================================================
# frozen_string_literal: true
class Course::MonitoringComponent < SimpleDelegator
  include Course::ControllerComponentHost::Component

  def self.enabled_by_default?
    false
  end
end


================================================
FILE: app/controllers/components/course/multiple_reference_timelines_component.rb
================================================
# frozen_string_literal: true
class Course::MultipleReferenceTimelinesComponent < SimpleDelegator
  include Course::ControllerComponentHost::Component

  def self.enabled_by_default?
    false
  end

  def sidebar_items
    return [] unless can?(:manage, Course::ReferenceTimeline.new(course: current_course))

    [
      {
        key: :admin_multiple_reference_timelines,
        icon: :timelines,
        type: :admin,
        weight: 9,
        path: course_reference_timelines_path(current_course)
      }
    ]
  end
end


================================================
FILE: app/controllers/components/course/plagiarism_component.rb
================================================
# frozen_string_literal: true
class Course::PlagiarismComponent < SimpleDelegator
  include Course::ControllerComponentHost::Component

  def self.enabled_by_default?
    false
  end

  def sidebar_items
    return [] unless can?(:manage_plagiarism, current_course)

    [
      {
        key: :admin_plagiarism,
        icon: :plagiarism,
        type: :admin,
        weight: 3,
        path: course_plagiarism_assessments_path(current_course)
      }
    ]
  end
end


================================================
FILE: app/controllers/components/course/rag_wise_component.rb
================================================
# frozen_string_literal: true
class Course::RagWiseComponent < SimpleDelegator
  include Course::ControllerComponentHost::Component

  def self.enabled_by_default?
    false
  end

  def sidebar_items
    settings_sidebar_items
  end

  private

  def settings_sidebar_items
    [
      {
        key: self.class.key,
        type: :settings,
        weight: 6,
        path: course_admin_rag_wise_path(current_course)
      }
    ]
  end
end


================================================
FILE: app/controllers/components/course/scholaistic_component.rb
================================================
# frozen_string_literal: true
class Course::ScholaisticComponent < SimpleDelegator
  include Course::ControllerComponentHost::Component
  include Course::Scholaistic::Concern

  def self.enabled_by_default?
    false
  end

  def sidebar_items
    main_sidebar_items + settings_sidebar_items
  end

  private

  def main_sidebar_items
    return [] unless scholaistic_course_linked?

    student_sidebar_items + admin_sidebar_items
  end

  def student_sidebar_items
    [
      {
        key: :scholaistic_assessments,
        icon: :chatbot,
        title: settings.assessments_title,
        weight: 4,
        path: course_scholaistic_assessments_path(current_course)
      }
    ] + assistant_sidebar_items
  end

  def assistant_sidebar_items
    ScholaisticApiService.assistants!(current_course).map do |assistant|
      {
        key: "scholaistic_assistant_#{assistant[:id]}",
        icon: :chatbot,
        title: assistant[:sidebar_title] || assistant[:title],
        weight: 4.5,
        path: course_scholaistic_assistant_path(current_course, assistant[:id])
      }
    end
  rescue StandardError => e
    Rails.logger.error("Failed to load Scholaistic assistants: #{e.message}")
    raise e unless Rails.env.production?

    []
  end

  def admin_sidebar_items
    return [] unless can?(:manage_scholaistic_assistants, current_course)

    [
      {
        key: :admin_scholaistic_assistants,
        type: :admin,
        icon: :chatbot,
        weight: 9,
        path: course_scholaistic_assistants_path(current_course),
        exact: true
      }
    ]
  end

  def settings_sidebar_items
    [
      {
        type: :settings,
        key: self.class.key,
        weight: 5,
        path: course_admin_scholaistic_path(current_course)
      }
    ]
  end
end


================================================
FILE: app/controllers/components/course/settings_component.rb
================================================
# frozen_string_literal: true
class Course::SettingsComponent < SimpleDelegator
  include Course::ControllerComponentHost::Component

  # Prevent user from locking him/herself out of settings.
  def self.can_be_disabled_for_course?
    false
  end

  def sidebar_items
    admin_sidebar_items + settings_sidebar_items
  end

  private

  def admin_sidebar_items
    return [] unless can?(:manage, current_course)

    [
      {
        key: :admin_settings,
        icon: :settings,
        type: :admin,
        weight: 100,
        path: course_admin_path(current_course)
      }
    ]
  end

  def settings_sidebar_items
    [
      settings_index_item,
      settings_components_item,
      settings_sidebar_item,
      settings_notifications
    ]
  end

  def settings_index_item
    {
      key: :admin_settings_general,
      type: :settings,
      weight: 1,
      path: course_admin_path(current_course)
    }
  end

  def settings_components_item
    {
      key: :admin_settings_component_settings,
      type: :settings,
      weight: 2,
      path: course_admin_components_path(current_course)
    }
  end

  def settings_sidebar_item
    {
      key: :admin_settings_sidebar_settings,
      type: :settings,
      weight: 3,
      path: course_admin_sidebar_path(current_course)
    }
  end

  def settings_notifications
    {
      key: :admin_settings_notifications,
      type: :settings,
      weight: 12,
      path: course_admin_notifications_path(current_course)
    }
  end
end


================================================
FILE: app/controllers/components/course/statistics_component.rb
================================================
# frozen_string_literal: true
class Course::StatisticsComponent < SimpleDelegator
  include Course::ControllerComponentHost::Component

  def sidebar_items
    return [] unless can?(:read_statistics, current_course)

    [
      {
        key: self.class.key,
        icon: :statistics,
        type: :admin,
        weight: 3,
        path: course_statistics_students_path(current_course)
      }
    ]
  end
end


================================================
FILE: app/controllers/components/course/stories_component.rb
================================================
# frozen_string_literal: true
class Course::StoriesComponent < SimpleDelegator
  include Course::ControllerComponentHost::Component

  def self.enabled_by_default?
    false
  end

  def sidebar_items
    main_sidebar_items + settings_sidebar_items
  end

  private

  def main_sidebar_items
    return [] unless
      current_course_user.present? &&
      current_component_host[:course_stories_component] &&
      current_course.settings(:course_stories_component).push_key.present?

    student_sidebar_items + staff_sidebar_items
  end

  def student_sidebar_items
    [
      {
        key: :learn,
        icon: :learn,
        title: settings.title,
        weight: 0,
        path: course_learn_path(current_course)
      }
    ]
  end

  def staff_sidebar_items
    return [] unless can?(:access_mission_control, current_course)

    [
      {
        key: :sidebar_stories_mission_control,
        icon: :mission_control,
        type: :admin,
        weight: 1,
        path: course_mission_control_path(current_course)
      }
    ]
  end

  def settings_sidebar_items
    [
      {
        key: self.class.key,
        type: :settings,
        weight: 5,
        path: course_admin_stories_path(current_course)
      }
    ]
  end
end


================================================
FILE: app/controllers/components/course/survey_component.rb
================================================
# frozen_string_literal: true
class Course::SurveyComponent < SimpleDelegator
  include Course::ControllerComponentHost::Component

  def self.lesson_plan_item_actable_names
    [Course::Survey.name]
  end

  def sidebar_items
    [
      {
        key: :surveys,
        icon: :survey,
        weight: 11,
        path: course_surveys_path(current_course)
      }
    ]
  end
end


================================================
FILE: app/controllers/components/course/users_component.rb
================================================
# frozen_string_literal: true
class Course::UsersComponent < SimpleDelegator
  include Course::ControllerComponentHost::Component
  include Course::UnreadCountsConcern

  def self.can_be_disabled_for_course?
    false
  end


  def sidebar_items
    main_sidebar_items + admin_sidebar_items
  end

  private

  def main_sidebar_items
    [
      {
        key: :users,
        icon: :users,
        weight: 7,
        path: course_users_path(current_course)
      }
    ]
  end

  # Direct the 'Manage Users' link to the usual course_users_students_path if current course user is a manager,
  # otherwise direct it to manage personalized timelines.
  def admin_sidebar_items
    can_manage_users = can?(:manage_users, current_course)
    can_manage_personal_times =
      current_course.show_personalized_timeline_features? && can?(:manage_personal_times, current_course)

    return [] unless can_manage_users || can_manage_personal_times

    [
      {
        key: :admin_users_manage_users,
        icon: :manageUsers,
        type: :admin,
        weight: 2,
        path:
          if can_manage_users
            course_users_students_path(current_course)
          else
            personal_times_course_users_path(current_course)
          end,
        unread: pending_enrol_requests_count
      }
    ]
  end
end


================================================
FILE: app/controllers/components/course/videos_component.rb
================================================
# frozen_string_literal: true
class Course::VideosComponent < SimpleDelegator
  include Course::ControllerComponentHost::Component
  include Course::UnreadCountsConcern

  def self.lesson_plan_item_actable_names
    [Course::Video.name]
  end

  def sidebar_items
    main_sidebar_items + settings_sidebar_items
  end

  private

  def main_sidebar_items
    [
      {
        key: :videos,
        icon: :video,
        title: settings.title,
        weight: 12,
        path: course_videos_path(current_course, tab: current_course.default_video_tab),
        unread: unwatched_videos_count
      }
    ]
  end

  def settings_sidebar_items
    [
      {
        key: self.class.key,
        title: settings.title,
        type: :settings,
        weight: 13,
        path: course_admin_videos_path(current_course)
      }
    ]
  end
end


================================================
FILE: app/controllers/concerns/application_ability_concern.rb
================================================
# frozen_string_literal: true
module ApplicationAbilityConcern
  # Override of Cancancan#current_ability to provide current course.
  def current_ability
    @current_ability ||= Ability.new(current_user, nil, nil, current_instance_user, current_session_id)
  end
end


================================================
FILE: app/controllers/concerns/application_announcements_concern.rb
================================================
# frozen_string_literal: true
module ApplicationAnnouncementsConcern
  extend ActiveSupport::Concern

  # Returns active global announcements unread by the current user, if one is signed in.
  #
  # @return [Array<GenericAnnouncement>] Unread announcements
  def unread_global_announcements
    user_signed_in? ? global_announcements.unread_by(current_user) : global_announcements
  end

  # Returns all active global announcements.
  #
  # @return [Array<GenericAnnouncement>] Active announcements
  def global_announcements
    GenericAnnouncement.for_instance(current_tenant).currently_active
  end
end


================================================
FILE: app/controllers/concerns/application_authentication_concern.rb
================================================
# frozen_string_literal: true
module ApplicationAuthenticationConcern
  extend ActiveSupport::Concern

  REQUIRES_AUTHENTICATION = { message: 'Requires authentication' }.freeze
  BAD_CREDENTIALS = {
    message: 'Bad credentials'
  }.freeze
  MALFORMED_AUTHORIZATION_HEADER = {
    error: 'invalid_request',
    error_description: 'Authorization header value must follow this format: Bearer access-token',
    message: 'Bad credentials'
  }.freeze

  def current_user_from_token
    token = authenticate_token
    User.joins(:emails).where('user_emails.email = ?', token[:email]).first if token
  end

  def current_session_id
    @current_session_id ||= current_decoded_token&.[](:session_state)
  end

  def token_from_request
    @token_from_request ||= get_token_from_bearer || get_token_from_cookies
  end

  def current_decoded_token
    @current_decoded_token ||= @decoded_token&.decoded_token
  end

  private

  def authenticate_token
    access_token = token_from_request

    return if performed?

    @decoded_token ||= Authentication::AuthenticationService.validate_token(access_token, :local)

    if @decoded_token.error
      # render json: { message: @decoded_token.error.message }, status: @decoded_token.error.status and return
      return nil
    end

    @decoded_token.decoded_token
  end

  def get_token_from_bearer
    authorization_header_elements = request.headers['Authorization']&.split

    # render json: REQUIRES_AUTHENTICATION, status: :unauthorized and return unless authorization_header_elements
    return nil unless authorization_header_elements

    unless authorization_header_elements.length == 2
      # render json: MALFORMED_AUTHORIZATION_HEADER, status: :unauthorized and return
      return nil
    end

    scheme, token = authorization_header_elements

    # render json: BAD_CREDENTIALS, status: :unauthorized and return unless scheme.downcase == 'bearer'
    return nil unless scheme.downcase == 'bearer'

    token
  end

  def get_token_from_cookies
    cookies.encrypted[:access_token]
  end
end


================================================
FILE: app/controllers/concerns/application_components_concern.rb
================================================
# frozen_string_literal: true
module ApplicationComponentsConcern
  extend ActiveSupport::Concern

  included do
    rescue_from ComponentNotFoundError, with: :handle_component_not_found
  end

  protected

  def handle_component_not_found(exception)
    @exception = exception
    render json: { error: 'Component not found' }, status: :not_found
  end
end


================================================
FILE: app/controllers/concerns/application_controller_multitenancy_concern.rb
================================================
# frozen_string_literal: true
module ApplicationControllerMultitenancyConcern
  extend ActiveSupport::Concern
  include ApplicationMultitenancy

  included do
    set_current_tenant_through_filter
    before_action :deduce_and_set_current_tenant

    helper_method :current_tenant
  end
end


================================================
FILE: app/controllers/concerns/application_instance_user_concern.rb
================================================
# frozen_string_literal: true
module ApplicationInstanceUserConcern
  extend ActiveSupport::Concern

  included do
    before_action :track_instance_user
  end

  def current_instance_user
    return nil unless current_user

    @current_instance_user ||= current_tenant.instance_users.find_by(user: current_user)
  end

  private

  def track_instance_user
    return if current_instance_user.nil?

    # Only update the timestamp every hour
    return if current_instance_user.last_active_at && current_instance_user.last_active_at > 1.hour.ago

    current_instance_user.update_column(:last_active_at, Time.zone.now)
  end
end


================================================
FILE: app/controllers/concerns/application_internationalization_concern.rb
================================================
# frozen_string_literal: true
module ApplicationInternationalizationConcern
  extend ActiveSupport::Concern

  included do
    before_action :set_locale
  end

  # Sets current locale to http accept(or compatible) language or default locale.
  def set_locale
    @client_language = @current_user&.locale&.to_sym || http_accept_language.
                       compatible_language_from(I18n.available_locales)
    I18n.locale = @client_language
  end
end


================================================
FILE: app/controllers/concerns/application_multitenancy.rb
================================================
# frozen_string_literal: true
module ApplicationMultitenancy
  private

  def deduce_and_set_current_tenant
    tenant = deduce_tenant
    ActsAsTenant.current_tenant = tenant
    ActsAsTenant.test_tenant = tenant
  end

  # Deduces the tenant from the host specified in the HTTP Request.
  # @return [Instance] The current tenant.
  # @return [nil] If there is no current tenant.
  def deduce_tenant
    tenant_host = deduce_tenant_host
    instance = Instance.find_tenant_by_host_or_default(tenant_host)

    if Rails.env.production? && instance.default? && instance.host.casecmp(tenant_host) != 0
      raise ActionController::RoutingError, 'Instance Not Found'
    end

    instance
  end

  # Deduces the current host. We strip any leading www from the host.
  # @return [String] The host, with www removed.
  def deduce_tenant_host
    if Rails.env.development?
      default_app_host = Application::Application.config.x.default_app_host

      if request.host.downcase.ends_with?(default_app_host)
        request.host.sub(default_app_host, 'coursemology.org')
      else
        'coursemology.org'
      end
    elsif request.host.downcase.start_with?('www.')
      request.host[4..]
    else
      request.host
    end
  end

  module ClassMethods
    def set_current_tenant_through_filter
      super
      class_eval do
        private :set_current_tenant
      end
    end
  end
end


================================================
FILE: app/controllers/concerns/application_pagination_concern.rb
================================================
# frozen_string_literal: true
module ApplicationPaginationConcern
  extend ActiveSupport::Concern

  protected

  # Retrieves page number and length from the GET request.
  # Note: this is meant to be used for backend pagination with React pages.
  def page_param
    return {} if params[:filter].blank?

    params[:filter].permit(:page_num, :length)
  end
end


================================================
FILE: app/controllers/concerns/application_user_concern.rb
================================================
# frozen_string_literal: true
module ApplicationUserConcern
  extend ActiveSupport::Concern
  include ApplicationAuthenticationConcern

  included do
    before_action :authenticate!, unless: :publicly_accessible?
    rescue_from CanCan::AccessDenied, with: :handle_access_denied
    helper_method :url_to_user_or_course_user
  end

  # URL to the profile page of the given +CourseUser+ or +User+ in the current course
  #
  # @param [CourseUser|User] course_user The CourseUser/User to link to
  # @return [String | nil] A URL that points to the +CourseUser+ or +User+ profile page
  def url_to_user_or_course_user(course, user)
    return course_user_path(course, user) if user.is_a?(CourseUser)
    return user_path(user) if user.is_a?(User)

    nil
  end

  def current_user
    @current_user ||= current_user_from_token
  end

  protected

  def publicly_accessible?
    action_name.to_sym == :index && controller_name == 'application'
  end

  def handle_access_denied(exception)
    render json: { errors: exception.message }, status: :forbidden
  end

  private

  def authenticate!
    raise AuthenticationError unless devise_controller? || current_user

    update_user_tracked_fields
    add_token_to_cookie
  end

  def add_token_to_cookie
    cookies.encrypted[:access_token] =
      { value: token_from_request, httponly: true, expires: 1.hour.from_now }
  end

  def update_user_tracked_fields
    return if !current_user || current_user.session_id == current_session_id

    update_tracked_fields
  end

  def update_tracked_fields
    old_current, new_current = current_user.current_sign_in_at, Time.now.utc
    current_user.last_sign_in_at     = old_current || new_current
    current_user.current_sign_in_at  = new_current

    old_current, new_current = current_user.current_sign_in_ip, request.remote_ip
    current_user.last_sign_in_ip     = old_current || new_current
    current_user.current_sign_in_ip  = new_current

    current_user.sign_in_count ||= 0
    current_user.sign_in_count += 1

    current_user.session_id = current_session_id
    current_user.save
  end
end


================================================
FILE: app/controllers/concerns/application_user_time_zone_concern.rb
================================================
# frozen_string_literal: true
module ApplicationUserTimeZoneConcern
  extend ActiveSupport::Concern

  included do
    around_action :set_time_zone, if: :current_user
  end

  protected

  # Set the time_zone for current request.
  def set_time_zone(&block) # rubocop:disable Naming/AccessorMethodName
    Time.use_zone(current_user.time_zone, &block)
  end
end


================================================
FILE: app/controllers/concerns/codaveri_language_concern.rb
================================================
# frozen_string_literal: true
module CodaveriLanguageConcern
  def codaveri_language
    programming_language_map[type.constantize]&.fetch(:language) || polyglot_name
  end

  def codaveri_version
    programming_language_map[type.constantize]&.fetch(:version) || polyglot_version
  end

  private

  # We only need to list the special cases here, any others will fall back to the default
  # name and version we are already using on our side.
  def programming_language_map
    {
      Coursemology::Polyglot::Language::CPlusPlus::CPlusPlus11 => {
        language: 'cpp',
        version: '10.2'
      },
      Coursemology::Polyglot::Language::CPlusPlus::CPlusPlus17 => {
        language: 'cpp',
        version: '10.2'
      },
      Coursemology::Polyglot::Language::Java::Java17 => {
        language: 'java',
        version: '17.0'
      },
      Coursemology::Polyglot::Language::Java::Java21 => {
        language: 'java',
        version: '21.0'
      },
      Coursemology::Polyglot::Language::CSharp::CSharp5Point0 => {
        language: 'csharp',
        version: '5.0.201'
      }
    }
  end
end


================================================
FILE: app/controllers/concerns/course/achievement_conditional_concern.rb
================================================
# frozen_string_literal: true
module Course::AchievementConditionalConcern
  extend ActiveSupport::Concern

  def success_action
    render partial: 'course/condition/conditions', locals: { conditional: @conditional }
  end

  def set_conditional
    @conditional = Course::Achievement.find(params[:achievement_id])
  end
end


================================================
FILE: app/controllers/concerns/course/activity_feeds_concern.rb
================================================
# frozen_string_literal: true
module Course::ActivityFeedsConcern
  extend ActiveSupport::Concern

  # Loads recent activity feeds of a given course.
  #
  # @return [Array<Course::Notification>] Recent activity feed notifications
  def recent_activity_feeds
    return [] if current_course.nil?

    current_course.notifications.feed.order(created_at: :desc)
  end
end


================================================
FILE: app/controllers/concerns/course/assessment/answer/update_answer_concern.rb
================================================
# frozen_string_literal: true
module Course::Assessment::Answer::UpdateAnswerConcern
  extend ActiveSupport::Concern

  private

  def update_answer(answer, answer_params)
    update_answer_params = update_answer_params(answer, answer_params)

    specific_answer = answer.specific
    specific_answer.assign_params(update_answer_params)
    # Saving the specific_answer to forward validation errors
    return true if specific_answer.save

    answer.errors.merge!(specific_answer.errors)
    false
  end

  protected

  def update_answer_params(answer, update_params)
    update_params.
      permit([:id, :client_version] + additional_answer_params(answer)).
      merge(last_session_id: current_session_id)
  end

  def additional_answer_params(answer)
    [].tap do |result|
      result.push(*update_specific_answer_type_params(answer)) if can?(:update, answer)
      result.push(:grade) if can?(:grade, answer) && !answer.submission.attempting?
    end
  end

  def update_specific_answer_type_params(answer) # rubocop:disable Metrics/MethodLength,Metrics/CyclomaticComplexity
    answer_actable_class = answer.actable.class.name
    scalar_params = []
    array_params = {}

    case answer_actable_class
    when 'Course::Assessment::Answer::MultipleResponse'
      update_multiple_response_params(array_params)
    when 'Course::Assessment::Answer::Programming'
      update_programming_params(array_params)
    when 'Course::Assessment::Answer::TextResponse'
      update_text_response_params(scalar_params)
    when 'Course::Assessment::Answer::RubricBasedResponse'
      update_rubric_based_response_params(scalar_params, array_params, answer)
    when 'Course::Assessment::Answer::VoiceResponse'
      update_voice_response_params(scalar_params)
    when 'Course::Assessment::Answer::Scribing'
      nil
    when 'Course::Assessment::Answer::ForumPostResponse'
      update_forum_post_response_params(scalar_params, array_params)
    end

    scalar_params.push(array_params)
  end

  def update_multiple_response_params(array_params)
    array_params[:option_ids] = []
  end

  def update_programming_params(array_params)
    array_params[:files_attributes] = [:id, :filename, :content]
  end

  def update_text_response_params(scalar_params)
    scalar_params.push(:answer_text)
    scalar_params.push(attachments_params)
  end

  def update_voice_response_params(scalar_params)
    scalar_params.push(attachments_params)
  end

  def update_rubric_based_response_params(scalar_params, array_params, answer)
    scalar_params.push(:answer_text)
    return unless can?(:grade, answer) && !answer.submission.attempting?

    array_params[:selections_attributes] = [:id, :answer_id, :category_id, :criterion_id, :grade, :explanation]
  end

  def update_forum_post_response_params(scalar_params, array_params)
    scalar_params.push(:answer_text)
    forum_post_attributes = [:id, :text, :creatorId, :updatedAt]
    array_params[:selected_post_packs] =
      [core_post: forum_post_attributes, parent_post: forum_post_attributes, topic: [:id]]
  end
end


================================================
FILE: app/controllers/concerns/course/assessment/koditsu_assessment_concern.rb
================================================
# frozen_string_literal: true
module Course::Assessment::KoditsuAssessmentConcern
  extend ActiveSupport::Concern

  def create_assessment_in_koditsu
    workspace_id = current_course.koditsu_workspace_id

    monitoring_object, seb_config_key = monitoring_configuration

    assessment_service = Course::Assessment::KoditsuAssessmentService.
                         new(@assessment, [], workspace_id, monitoring_object, seb_config_key)
    status, response = assessment_service.run_create_koditsu_assessment

    adjust_assessment_from_koditsu_response(status, response)
  end

  def adjust_assessment_from_koditsu_response(status, response)
    if status == 201
      @assessment.update!({
        is_synced_with_koditsu: true,
        koditsu_assessment_id: response['id']
      })
    else
      @assessment.update!(is_synced_with_koditsu: false)
    end
  end

  def update_assessment_in_koditsu
    assessment_id = @assessment.koditsu_assessment_id

    get_question_status, questions = questions_in_koditsu(assessment_id)

    unless get_question_status == 200
      raise KoditsuError,
            { status: get_question_status, body: questions }
    end

    status = edit_koditsu_assessment(@assessment, questions, current_course, monitoring_configuration)

    @assessment.update!(is_synced_with_koditsu: status == 200)
  end

  def create_or_update_assessment_in_koditsu
    if @assessment.koditsu_assessment_id
      update_assessment_in_koditsu
    else
      create_assessment_in_koditsu
    end
  end

  def flag_assessment_not_synced_with_koditsu
    @assessment.update!(is_synced_with_koditsu: false)
  end

  def remove_question_from_assessment_in_koditsu(question_id)
    assessment_id = @assessment.koditsu_assessment_id

    get_question_status, questions = questions_in_koditsu(assessment_id)
    return unless get_question_status == 200

    new_questions = questions.reject do |question|
      question['id'] == question_id
    end

    status = edit_koditsu_assessment(@assessment, new_questions, current_course, monitoring_configuration)

    return unless status == 200 && @assessment.questions.reload.all?(&:is_synced_with_koditsu)

    @assessment.update!(is_synced_with_koditsu: true)
  end

  def questions_in_koditsu(koditsu_assessment_id)
    service = KoditsuAsyncApiService.new("api/assessment/#{koditsu_assessment_id}", nil)
    status, response = service.get

    if status == 200
      [status, response['data']['questions']]
    else
      [status, nil]
    end
  end

  def monitoring_configuration
    if @assessment.monitor_id
      monitoring = @assessment.monitor
      monitoring_object = {
        heartbeatIntervalMs: monitoring.max_interval_ms,
        isEnabled: monitoring.enabled
      }

      is_using_seb = @assessment.monitor.browser_authorization? &&
                     @assessment.monitor.browser_authorization_method == 'seb_config_key'
      seb_config_key = is_using_seb ? @assessment.monitor.seb_config_key : nil
    else
      monitoring_object = {
        heartbeatIntervalMs: 0,
        isEnabled: false
      }
      seb_config_key = nil
    end

    [monitoring_object, seb_config_key]
  end

  def edit_koditsu_assessment(assessment, questions, course, monitoring_config)
    assessment_id = assessment.koditsu_assessment_id
    workspace_id = course.koditsu_workspace_id
    monitoring_object, seb_config_key = monitoring_config

    service = Course::Assessment::KoditsuAssessmentService.
              new(assessment, questions, workspace_id, monitoring_object, seb_config_key)
    status, = service.run_edit_koditsu_assessment(assessment_id)

    status
  end
end


================================================
FILE: app/controllers/concerns/course/assessment/koditsu_assessment_invitation_concern.rb
================================================
# frozen_string_literal: true
module Course::Assessment::KoditsuAssessmentInvitationConcern
  extend ActiveSupport::Concern

  def send_invitation_for_koditsu_assessment(assessment)
    invitation_validity_period = {
      startAt: assessment.start_at - 12.hours,
      endAt: assessment.end_at
    }

    course_users = assessment.course.course_users.preload(user: :emails)
    users = course_users.map { |cu| [cu, cu.user] }

    invitation_service = Course::Assessment::KoditsuAssessmentInvitationService.
                         new(assessment, users, invitation_validity_period)
    status, response = invitation_service.run_invite_users_to_koditsu_assessment

    [status, response]
  end

  def all_invitation_successful?(invitation_response)
    failure_count = invitation_response.filter do |invitation|
      invitation['status'] == 'errorOther'
    end.length

    failure_count == 0
  end
end


================================================
FILE: app/controllers/concerns/course/assessment/live_feedback/file_concern.rb
================================================
# frozen_string_literal: true
module Course::Assessment::LiveFeedback::FileConcern
  extend ActiveSupport::Concern

  def snapshot_files_hash(file_ids)
    Course::Assessment::LiveFeedback::File.where(id: file_ids).to_h do |file|
      [file.filename, file]
    end
  end

  def answer_files_hash
    @answer.actable.files.to_h do |file|
      [file.filename, file]
    end
  end

  def fetch_all_unchanged_files(file_hash, current_answer_file_hash)
    file_hash.each_with_object([]) do |(filename, file), unchanged|
      if current_answer_file_hash[filename] && current_answer_file_hash[filename].content == file.content
        unchanged << file
      end
    end
  end

  def fetch_all_modified_files(file_hash, current_answer_file_hash)
    current_answer_file_hash.each_with_object([]) do |(filename, file), modified|
      if !file_hash[filename] || file_hash[filename].content != file.content
        modified << { filename: file.filename,
                      content: file.content }
      end
    end
  end

  def fetch_all_files_to_be_associated(file_ids)
    file_hash = snapshot_files_hash(file_ids)
    current_answer_file_hash = answer_files_hash

    unchanged_files = fetch_all_unchanged_files(file_hash, current_answer_file_hash)
    modified_files = fetch_all_modified_files(file_hash, current_answer_file_hash)

    [unchanged_files, modified_files]
  end
end


================================================
FILE: app/controllers/concerns/course/assessment/live_feedback/message_concern.rb
================================================
# frozen_string_literal: true
module Course::Assessment::LiveFeedback::MessageConcern
  extend ActiveSupport::Concern
  include Course::Assessment::LiveFeedback::MessageFileConcern

  def handle_save_user_message
    @thread = Course::Assessment::LiveFeedback::Thread.where(codaveri_thread_id: @thread_id).first

    @thread.class.transaction do
      new_message = create_new_message

      new_options = @options.map do |option_id|
        {
          message_id: new_message.id,
          option_id: option_id
        }
      end

      options = Course::Assessment::LiveFeedback::MessageOption.insert_all(new_options)
      raise ActiveRecord::Rollback if !new_options.empty? && (options.nil? || options.rows.empty?)

      associate_new_message_with_new_or_existing_files(new_message)
    end
  end

  def create_new_message
    new_message = Course::Assessment::LiveFeedback::Message.create({
      thread_id: @thread.id,
      is_error: false,
      content: @message,
      creator_id: current_user.id,
      created_at: Time.zone.now,
      option_id: @option_id
    })

    raise ActiveRecord::Rollback unless new_message.persisted?

    new_message
  end
end


================================================
FILE: app/controllers/concerns/course/assessment/live_feedback/message_file_concern.rb
================================================
# frozen_string_literal: true
module Course::Assessment::LiveFeedback::MessageFileConcern
  extend ActiveSupport::Concern
  include Course::Assessment::LiveFeedback::FileConcern

  def associate_new_message_with_new_or_existing_files(new_message)
    file_ids = associated_file_ids_with_last_message(new_message)
    unchanged_files, modified_files = fetch_all_files_to_be_associated(file_ids)
    new_files = Course::Assessment::LiveFeedback::File.insert_all(modified_files)

    raise ActiveRecord::Rollback if !modified_files.empty? && (new_files.nil? || new_files.rows.empty?)

    associated_file_ids = unchanged_files.map(&:id) + new_files.rows.flatten
    save_message_file_association(new_message, associated_file_ids)
  end

  def associated_file_ids_with_last_message(new_message)
    last_message = @thread.messages.where.not(id: new_message.id).order(id: :desc).first

    if last_message
      Course::Assessment::LiveFeedback::MessageFile.where(message_id: last_message.id).pluck(:file_id)
    else
      []
    end
  end

  def save_message_file_association(new_message, associated_file_ids)
    new_message_files = associated_file_ids.map do |file_id|
      {
        message_id: new_message.id,
        file_id: file_id
      }
    end

    files = Course::Assessment::LiveFeedback::MessageFile.insert_all(new_message_files)
    raise ActiveRecord::Rollback if !new_message_files.empty? && (files.nil? || files.rows.empty?)
  end
end


================================================
FILE: app/controllers/concerns/course/assessment/live_feedback/thread_concern.rb
================================================
# frozen_string_literal: true
module Course::Assessment::LiveFeedback::ThreadConcern
  extend ActiveSupport::Concern

  def safe_create_and_save_thread_info
    submission_question = Course::Assessment::SubmissionQuestion.where(
      submission_id: @submission, question_id: @answer.question
    ).first

    submission_question.with_lock do
      existing_active_threads = Course::Assessment::LiveFeedback::Thread.
                                where(submission_question_id: submission_question.id, is_active: true)

      return existing_thread_status(existing_active_threads.first) unless existing_active_threads.empty?

      create_and_save_thread_if_empty(submission_question)
    end
  end

  def existing_thread_status(thread)
    thread_status = thread.is_active? ? 'active' : 'expired'

    [
      200,
      'thread' => { 'id' => thread.codaveri_thread_id, 'status' => thread_status }
    ]
  end

  def create_and_save_thread_if_empty(submission_question)
    status, body = @answer.create_live_feedback_chat

    new_thread = save_thread_info(body['thread'], submission_question.id)

    [status, body]
  end

  def save_thread_info(thread_info, submission_question_id)
    Course::Assessment::LiveFeedback::Thread.create!({
      submission_question_id: submission_question_id,
      codaveri_thread_id: thread_info['id'],
      is_active: thread_info['status'] == 'active',
      submission_creator_id: @submission.creator_id,
      created_at: Time.zone.now
    })
  end
end


================================================
FILE: app/controllers/concerns/course/assessment/monitoring/seb_payload_concern.rb
================================================
# frozen_string_literal: true
module Course::Assessment::Monitoring::SebPayloadConcern
  extend ActiveSupport::Concern

  private

  def seb_payload_from_request(request)
    url = request.headers['X-SafeExamBrowser-Url']
    seb_config_key_hash = request.headers['X-SafeExamBrowser-ConfigKeyHash']
    return unless url && seb_config_key_hash

    # It's safe to not strip URL fragments (#) here because fragments are never sent to the server.
    { config_key_hash: seb_config_key_hash, url: url }
  end

  def stub_heartbeat_from_request(request)
    Course::Monitoring::Heartbeat.new(
      user_agent: request.user_agent,
      seb_payload: seb_payload_from_request(request)
    )
  end
end


================================================
FILE: app/controllers/concerns/course/assessment/monitoring_concern.rb
================================================
# frozen_string_literal: true
module Course::Assessment::MonitoringConcern
  extend ActiveSupport::Concern

  include Course::Assessment::Monitoring::SebPayloadConcern

  included do
    alias_method :load_monitor, :monitor
    alias_method :load_can_manage_monitor?, :can_manage_monitor?
    alias_method :load_monitoring_component_enabled?, :monitoring_component_enabled?

    before_action :load_monitor, only: [:edit, :show]
    before_action :load_can_manage_monitor?, only: [:index, :edit]
    before_action :load_monitoring_component_enabled?, only: [:index, :edit]

    before_action :raise_if_no_monitor, only: [:monitoring, :unblock_monitor, :seb_payload]
    before_action :check_blocked_by_monitor, only: [:show]
  end

  def monitoring
    authorize! :read, @monitor
  end

  # We need this endpoint because Safe Exam Browser (SEB) doesn't append keys in request headers
  # of WebSocket connections.
  def seb_payload
    payload = seb_payload_from_request(request)
    return head(:ok) unless payload

    render json: payload
  end

  def unblock_monitor
    session_password = unblock_monitor_params[:password]

    if monitoring_service&.unblock(session_password)
      render json: { redirectUrl: course_assessment_path(current_course, @assessment) }
    else
      render json: { errors: t('course.assessment.assessments.unblock_monitor.invalid_password') }, status: :bad_request
    end
  end

  def upsert_monitoring!
    monitoring_service&.upsert!(monitoring_params.merge({
      enabled: @assessment.view_password_protected? ? monitoring_params[:enabled] : false,
      blocks: should_disable_block? ? false : monitoring_params[:blocks]
    }))
  end

  private

  def monitoring_params
    params.require(:assessment).permit(monitoring: Course::Assessment::MonitoringService.params)[:monitoring]
  end

  def unblock_monitor_params
    params.require(:assessment).permit(:password)
  end

  def raise_if_no_monitor
    raise ComponentNotFoundError if monitor.nil?
  end

  def check_blocked_by_monitor
    render 'blocked_by_monitor' if blocked_by_monitor?
  end

  def blocked_by_monitor?
    cannot?(:read, monitor) && monitoring_service&.should_block?(request) && !submitted_assessment?
  end

  def monitoring_service
    return unless monitoring_component_enabled?

    @monitoring_service ||= Course::Assessment::MonitoringService.new(@assessment, session)
  end

  def monitoring_component_enabled?
    @monitoring_component_enabled ||= current_component_host[:course_monitoring_component].present?
  end

  def can_manage_monitor?
    @can_manage_monitor ||= can?(:manage, Course::Monitoring::Monitor.new)
  end

  def monitor
    @monitor ||= monitoring_service&.monitor
  end

  def should_disable_block?
    !@assessment.session_password_protected? || !monitor&.browser_authorization?
  end

  def submitted_assessment?
    @submissions.find { |submission| !submission.attempting? }.present?
  end
end


================================================
FILE: app/controllers/concerns/course/assessment/question/codaveri_question_concern.rb
================================================
# frozen_string_literal: true
module Course::Assessment::Question::CodaveriQuestionConcern
  extend ActiveSupport::Concern

  def safe_create_or_update_codaveri_question(question)
    question.with_lock do
      next if question.is_synced_with_codaveri

      # we bypass the processing of the package since this function is called only when
      # we create the Codaveri question from duplicate on-demand, which means that
      # the question has already been created; we just need to propagate this question
      # to Codaveri
      question.skip_process_package = true
      Course::Assessment::Question::ProgrammingCodaveriService.
        create_or_update_question(question, question.attachment)
    end
  end

  def extract_pathname_from_java_file(file_content)
    # extracts pathname based on public class of java file
    class_name_extractor = /(?:^|;)\s*public\s+class\s+([A-Za-z_][A-Za-z0-9_]*)/
    match = file_content.match(class_name_extractor)

    match ? "#{match[1]}.java" : nil
  end
end


================================================
FILE: app/controllers/concerns/course/assessment/question/koditsu_question_concern.rb
================================================
# frozen_string_literal: true
# rubocop:disable Metrics/ModuleLength
module Course::Assessment::Question::KoditsuQuestionConcern
  extend ActiveSupport::Concern
  include Course::Assessment::KoditsuAssessmentConcern

  def create_koditsu_question
    workspace_id = current_course.koditsu_workspace_id
    service = Course::Assessment::Question::KoditsuQuestionService.
              new(@programming_question, workspace_id, @meta, current_course)

    status, response = service.run_create_koditsu_question

    adjust_question_from_koditsu_response(status, response)
  end

  def adjust_question_from_koditsu_response(status, response)
    @question = @programming_question.acting_as

    if status == 201
      @question.update!({
        koditsu_question_id: response['id'],
        is_synced_with_koditsu: true
      })
      @assessment.update!(is_synced_with_koditsu: false)
    else
      @question.update!(is_synced_with_koditsu: false)
    end
  end

  def arrange_questions_in_assessment_in_koditsu
    @assessment.reload && @assessment.questions.reload

    koditsu_questions = @assessment.questions.map do |question|
      {
        id: question.koditsu_question_id,
        type: 'QuestionCoding',
        score: question.maximum_grade.to_i,
        maxAttempts: question.specific.attempt_limit&.to_i
      }
    end

    status = edit_koditsu_assessment(@assessment, koditsu_questions, current_course, monitoring_configuration)

    return unless status == 200 && @assessment.questions.reload.all?(&:is_synced_with_koditsu)

    @assessment.update!(is_synced_with_koditsu: true)
  end

  def edit_koditsu_question
    koditsu_question_id = @question.koditsu_question_id

    service = Course::Assessment::Question::KoditsuQuestionService.
              new(@programming_question, nil, @meta, current_course)
    status = service.run_edit_koditsu_question(koditsu_question_id)

    @question.update!(is_synced_with_koditsu: true) if status == 200
  end

  def delete_koditsu_question(id)
    api_service = KoditsuAsyncApiService.new("api/question/coding/#{id}", nil)
    response_status, = api_service.delete

    response_status
  end

  def create_or_edit_question_in_koditsu
    extract_programming_question_metadata

    if @programming_question.acting_as.koditsu_question_id
      edit_koditsu_question
    else
      create_koditsu_question
    end
  end

  def extract_programming_question_metadata
    return unless @programming_question.edit_online?

    @meta = programming_package_service.extract_meta
  end

  def programming_package_service
    @service = Course::Assessment::Question::Programming::ProgrammingPackageService.new(
      @programming_question, nil
    )
  end

  def koditsu_programming_language_map
    {
      Coursemology::Polyglot::Language::CPlusPlus => {
        language: 'cpp',
        version: '10.2',
        filename: 'template.cpp'
      },
      Coursemology::Polyglot::Language::CPlusPlus::CPlusPlus11 => {
        language: 'cpp',
        version: '10.2',
        filename: 'template.cpp'
      },
      Coursemology::Polyglot::Language::Python::Python3Point4 => {
        language: 'python',
        version: '3.4',
        filename: 'main.py'
      },
      Coursemology::Polyglot::Language::Python::Python3Point5 => {
        language: 'python',
        version: '3.5',
        filename: 'main.py'
      },
      Coursemology::Polyglot::Language::Python::Python3Point6 => {
        language: 'python',
        version: '3.6',
        filename: 'main.py'
      },
      Coursemology::Polyglot::Language::Python::Python3Point7 => {
        language: 'python',
        version: '3.7',
        filename: 'main.py'
      },
      Coursemology::Polyglot::Language::Python::Python3Point9 => {
        language: 'python',
        version: '3.9',
        filename: 'main.py'
      },
      Coursemology::Polyglot::Language::Python::Python3Point10 => {
        language: 'python',
        version: '3.10',
        filename: 'main.py'
      },
      Coursemology::Polyglot::Language::Python::Python3Point12 => {
        language: 'python',
        version: '3.12',
        filename: 'main.py'
      },
      Coursemology::Polyglot::Language::Python::Python3Point13 => {
        language: 'python',
        version: '3.13',
        filename: 'main.py'
      }
    }
  end
end
# rubocop:enable Metrics/ModuleLength


================================================
FILE: app/controllers/concerns/course/assessment/question/multiple_responses_concern.rb
================================================
# frozen_string_literal: true
module Course::Assessment::Question::MultipleResponsesConcern
  extend ActiveSupport::Concern

  def switch_mcq_mrq_type(is_mcq, unsubmit)
    grading_scheme = is_mcq ? :any_correct : :all_correct

    result = @multiple_response_question.update(grading_scheme: grading_scheme)
    if result
      unsubmit_submissions if unsubmit
    else
      @multiple_response_question.reload
    end

    result
  end

  def unsubmit_submissions
    submission_ids = @question_assessment.assessment.submissions.pluck(:id)
    Course::Assessment::Submission::UnsubmittingJob.
      perform_later(current_user,
                    submission_ids,
                    @assessment,
                    @multiple_response_question.question).job
  end
end


================================================
FILE: app/controllers/concerns/course/assessment/question/rubric_based_response_controller_concern.rb
================================================
# frozen_string_literal: true
module Course::Assessment::Question::RubricBasedResponseControllerConcern
  include Course::Assessment::Question::RubricBasedResponseQuestionConcern
  extend ActiveSupport::Concern

  def create_new_category_grade_instances(new_category_ids)
    answers = Course::Assessment::Answer.where(
      actable_type: 'Course::Assessment::Answer::RubricBasedResponse',
      question_id: @rubric_based_response_question.acting_as.id
    ).includes(:actable).map(&:actable)

    new_category_selections = answers.product(new_category_ids).map do |answer, category_id|
      {
        answer_id: answer.id,
        category_id: category_id,
        criterion_id: nil,
        grade: nil,
        explanation: nil
      }
    end

    selections = Course::Assessment::Answer::RubricBasedResponseSelection.insert_all(new_category_selections)
    raise ActiveRecord::Rollback if !new_category_selections.empty? && (selections.nil? || selections.rows.empty?)

    true
  end

  def update_all_submission_answer_grades
    all_assessment_submission_ids = @assessment.submissions.map(&:id)
    @all_rubric_based_response_answers = Course::Assessment::Answer.where(
      submission_id: all_assessment_submission_ids,
      actable_type: 'Course::Assessment::Answer::RubricBasedResponse'
    ).includes(:question, actable: [selections: :criterion])

    answer_score_array = construct_answer_score_array

    raise ActiveRecord::Rollback unless Course::Assessment::Answer.upsert_all(answer_score_array, update_only: :grade,
                                                                                                  unique_by: :id)

    true
  end

  def preload_criterions_per_category
    @rubric_based_response_question = Course::Assessment::Question::RubricBasedResponse.
                                      includes(categories: :criterions).
                                      find(@rubric_based_response_question.id)
  end
end


================================================
FILE: app/controllers/concerns/course/assessment/question/rubric_based_response_question_concern.rb
================================================
# frozen_string_literal: true
module Course::Assessment::Question::RubricBasedResponseQuestionConcern
  extend ActiveSupport::Concern

  def construct_answer_score_array
    @all_rubric_based_response_answers.filter_map do |answer|
      selections = answer.actable&.selections
      next unless selections

      answer_object(answer, total_grade_for(selections, answer.question.maximum_grade))
    end
  end

  def total_grade_for(selections, maximum_grade)
    total_grade = selections.sum { grade_value(_1) }

    total_grade.clamp(0, maximum_grade)
  end

  def grade_value(selection)
    selection.grade.presence || selection.criterion&.grade.to_i
  end

  def answer_object(answer, total_grade)
    { id: answer.id, submission_id: answer.submission_id, question_id: answer.question_id, grade: total_grade,
      workflow_state: answer.workflow_state, correct: answer.correct, submitted_at: answer.submitted_at }
  end
end


================================================
FILE: app/controllers/concerns/course/assessment/question_bundle_assignment_concern.rb
================================================
# frozen_string_literal: true
module Course::Assessment::QuestionBundleAssignmentConcern
  extend ActiveSupport::Concern

  # All validations need to present a ValidationResult of this form, which will be consumed by the view.
  # This struct is loosely inspired by Rails' model validation, but heavily extended.
  # rubocop:disable Layout/CommentIndentation
  ValidationResult = Struct.new(
    :type,              # Hard or soft
    :pass,              # Whether this should be displayed as a tick or cross on the validation summary
    :score_penalty,     # For selecting the best randomized outcome
    :info,              # For displaying additional information. I18n string.
    :offending_cells,   # For highlighting the cell and displaying the error in a tooltip. I18n string.
                        # E.g. { (student, group): 'Lift: 1.4' }
    keyword_init: true
  )
  # rubocop:enable Layout/CommentIndentation

  # Computations on a large set of QBAs are expensive, and we need a lean in-memory representation of a set of QBAs.
  #
  # An AssignmentSet is a (thin) abstraction over a set of QBAs for an assessment which assumes consistency of the
  # underlying data. The constructing code is responsible for data translation / validation.
  #
  # Essentially a nested hash of Student -> Group -> Bundle. Group is nil if assigned bundle is extraneous. Everything
  # is identified by an integer ID.
  class AssignmentSet
    attr_accessor :assignments, :group_bundles

    def initialize(students, group_bundles)
      @assignments = students.to_h { |x| [x, nil => []] }
      @group_bundles = group_bundles
      @group_bundles_lookup = group_bundles.flat_map do |group, bundles|
        bundles.map { |bundle| [bundle, group] }
      end.to_h
    end

    def add_assignment(student, bundle)
      group = @group_bundles_lookup[bundle]
      @assignments[student] ||= { nil => [] }
      if @assignments[student][group].nil?
        @assignments[student][group] = bundle
      else
        @assignments[student][nil].append(bundle)
      end
    end
  end

  class AssignmentRandomizer
    attr_accessor :assignments, :students, :group_bundles, :name_lookup

    def initialize(assessment)
      @assessment = assessment
      @students = assessment.course.user_ids
      @group_bundles = assessment.question_group_ids.to_h { |x| [x, []] }
      assessment.question_bundles.each { |bundle| @group_bundles[bundle.group_id].append(bundle.id) }

      # Reverse lookup of user_id -> course_user.name or user.name
      # Retrieve for current course users, users with submissions, and users with bundle assignments
      @name_lookup = User.where(id: @assessment.question_bundle_assignments.select(:user_id)).
                     pluck(:id, :name).to_h.
                     merge(@assessment.course.course_users.pluck(:user_id, :name).to_h)
    end

    def load
      AssignmentSet.new(@students, @group_bundles).tap do |assignment_set|
        @assessment.question_bundle_assignments.where(submission: nil).each do |qba|
          assignment_set.add_assignment(qba.user_id, qba.bundle_id)
        end
      end
    end

    def save(assignment_set)
      # Deletion must be done atomically to prevent race conditions
      @assessment.question_bundle_assignments.where(submission: nil).delete_all
      new_question_bundle_assignments = []
      assignment_set.assignments.each do |student_id, assigned_group_bundles|
        assigned_group_bundles.each do |group_id, bundle_id|
          next if group_id.nil? || bundle_id.nil?

          new_question_bundle_assignments << Course::Assessment::QuestionBundleAssignment.new(
            user_id: student_id,
            assessment_id: @assessment.id,
            bundle_id: bundle_id
          )
        end
      end
      Course::Assessment::QuestionBundleAssignment.import! new_question_bundle_assignments
    end

    def randomize
      # Naive strategy: For each group, add a random bundle
      AssignmentSet.new(@students, @group_bundles).tap do |assignment_set|
        @students.each do |student|
          @group_bundles.each do |_, bundles|
            assignment_set.add_assignment(student, bundles.sample)
          end
        end
      end
    end

    def validate(assignment_set)
      [
        validate_no_overlapping_questions,
        validate_no_empty_groups,
        validate_one_bundle_assigned(assignment_set),
        validate_no_repeat_bundles(assignment_set)
      ].reduce(&:merge)
    end

    private

    def validate_no_overlapping_questions
      questions = Course::Assessment::Question.
                  where(id: @assessment.question_bundle_questions.group(:question_id).
                            having('count(*) > 1').
                            select(:question_id)).
                  pluck(:title).
                  to_sentence
      {
        no_overlapping_questions:
          ValidationResult.new(
            type: :hard,
            pass: questions.empty?,
            info: questions.empty? ? nil : t_scoped('.no_overlapping_questions.fail', questions: questions)
          )
      }
    end

    def validate_no_empty_groups
      groups = @assessment.question_groups.
               where.not(id: @assessment.question_bundles.select(:group_id)).
               pluck(:title).to_sentence
      {
        no_empty_groups:
          ValidationResult.new(
            type: :hard,
            pass: groups.empty?,
            info: groups.empty? ? nil : t_scoped('.no_empty_groups.fail', groups: groups)
          )
      }
    end

    def validate_one_bundle_assigned(assignment_set)
      student_ids = Set.new
      offending_cells = {}
      assignment_set.assignments.each do |student_id, assignment|
        assignment_set.group_bundles.each_key do |group_bundle|
          if assignment[group_bundle].nil?
            student_ids << student_id
            offending_cells[[student_id, group_bundle]] = t_scoped('.one_bundle_assigned.missing_bundle')
          end
        end
        if assignment[nil].present?
          student_ids << student_id
          offending_cells[[student_id, nil]] = t_scoped('.one_bundle_assigned.unbundled')
        end
      end
      students = student_ids.map { |student_id| @name_lookup[student_id] }.to_sentence
      {
        one_bundle_assigned:
          ValidationResult.new(
            type: :hard,
            pass: students.empty?,
            info: students.empty? ? nil : t_scoped('.one_bundle_assigned.fail', students: students),
            offending_cells: offending_cells
          )
      }
    end

    def validate_no_repeat_bundles(assignment_set)
      attempted_questions = {}
      @assessment.question_bundle_assignments.where.not(submission: nil).pluck(:user_id, :bundle_id).
        each do |user_id, bundle_id|
        attempted_questions[user_id] ||= Set.new
        attempted_questions[user_id] << bundle_id
      end
      student_ids = Set.new
      offending_cells = {}
      assignment_set.assignments.each do |student_id, assignment|
        assignment_set.group_bundles.each_key do |group_bundle|
          if assignment[group_bundle].present? && assignment[group_bundle].in?(attempted_questions[student_id] || [])
            student_ids << student_id
            offending_cells[[student_id, group_bundle]] = t_scoped('.no_repeat_bundles.repeat_bundle')
          end
        end
        if assignment[nil].present? && assignment[nil].any? { |b| b.in?(attempted_questions[student_id] || []) }
          student_ids << student_id
          offending_cells[[student_id, nil]] = t_scoped('.no_repeat_bundles.repeat_bundle')
        end
      end
      students = student_ids.map { |student_id| @name_lookup[student_id] }.to_sentence
      {
        no_repeat_bundles:
          ValidationResult.new(
            type: :hard,
            pass: students.empty?,
            info: students.empty? ? nil : t_scoped('.no_repeat_bundles.fail', students: students),
            offending_cells: offending_cells
          )
      }
    end

    # We can't use the default I18n lazy lookups because this is a concern, so we roll our own.
    def t_scoped(key, *args, **kwargs)
      I18n.t("course.assessment.question_bundle_assignments.validations#{key}", *args, **kwargs)
    end
  end
end


================================================
FILE: app/controllers/concerns/course/assessment/submission/koditsu/answers_concern.rb
================================================
# frozen_string_literal: true
module Course::Assessment::Submission::Koditsu::AnswersConcern
  extend ActiveSupport::Concern

  def build_answer_hash(answers)
    @answer_hash = answers.to_h do |answer|
      question = answer.question
      koditsu_question_id = question.koditsu_question_id
      [koditsu_question_id, [question, answer]]
    end
  end

  def destroy_all_existing_autogradings(answers)
    Course::Assessment::Answer::ProgrammingAutoGrading.where(answer: answers).destroy_all
  end

  def destroy_all_existing_files(answers)
    answer_ids = answers.map(&:actable_id)

    Course::Assessment::Answer::ProgrammingFile.where(answer_id: answer_ids).destroy_all
  end

  def update_all_submission_files(submission_answers)
    updated_files = submission_answers.flat_map do |submission_answer|
      _, answer = @answer_hash[submission_answer['questionId']]

      submission_answer['files'].map do |file|
        {
          filename: file['path'],
          content: file['content'],
          answer_id: answer.actable_id
        }
      end
    end

    raise ActiveRecord::Rollback unless Course::Assessment::Answer::ProgrammingFile.
                                        insert_all(updated_files)
  end

  def process_all_answers(submission_answers)
    update_all_submission_files(submission_answers)

    process_all_test_case_results(submission_answers)
  end

  def process_all_test_case_results(submission_answers)
    submission_with_test_case_results = submission_answers.reject do |sa|
      sa['exprTestcaseResults'].empty?
    end

    @autograding_id_hash = submission_with_test_case_results.to_h do |submission_answer|
      _, answer = @answer_hash[submission_answer['questionId']]

      autograding_id = new_autograding_id(answer)

      [answer.id, autograding_id]
    end

    update_all_answer_status(submission_with_test_case_results)
    save_all_test_case_results(submission_with_test_case_results)
  end

  def update_all_answer_status(submission_answers)
    submitted_answers = submission_answers.filter { |answer| answer['status'] == 'submitted' }

    updated_answer_objects = submitted_answers.map do |submitted_answer|
      question, answer = @answer_hash[submitted_answer['questionId']]
      build_answer_object(question, answer, submitted_answer)
    end

    raise ActiveRecord::Rollback unless Course::Assessment::Answer.upsert_all(updated_answer_objects)
  end

  def build_answer_object(question, answer, submitted_answer)
    {
      id: answer.id,
      submission_id: answer.submission_id,
      question_id: question.id,
      workflow_state: 'submitted',
      correct: submitted_answer['exprTestcaseResults'].all? { |tc| tc['result']['success'] },
      submitted_at: DateTime.parse(submitted_answer['filesSavedAt']).in_time_zone&.iso8601 ||
        Time.now.utc
    }
  end

  def save_all_test_case_results(submission_answers)
    test_case_result_objects = submission_answers.flat_map do |submission_answer|
      question, answer = @answer_hash[submission_answer['questionId']]
      test_case_index_id_hash = @test_cases_order[question.id]
      test_case_results = submission_answer['exprTestcaseResults']

      test_case_results.map do |tc_result|
        {
          auto_grading_id: @autograding_id_hash[answer.id],
          test_case_id: test_case_index_id_hash[tc_result['testcase']['index']],
          passed: tc_result['result']['success'],
          messages: { output: tc_result['result']['display'] }
        }
      end
    end

    raise ActiveRecord::Rollback unless Course::Assessment::Answer::ProgrammingAutoGradingTestResult.
                                        insert_all(test_case_result_objects)
  end

  def new_autograding_id(answer)
    autograding = Course::Assessment::Answer::ProgrammingAutoGrading.new(answer: answer)
    raise ActiveRecord::Rollback unless autograding.save!

    autograding.id
  end
end


================================================
FILE: app/controllers/concerns/course/assessment/submission/koditsu/submission_times_concern.rb
================================================
# frozen_string_literal: true
module Course::Assessment::Submission::Koditsu::SubmissionTimesConcern
  extend ActiveSupport::Concern

  def calculate_submission_time(state, questions)
    return nil unless state == 'submitted'

    attempted_questions = questions.reject do |question|
      question['status'] == 'notStarted'
    end

    final_submission_time(attempted_questions)
  end

  private

  def final_submission_time(attempted_questions)
    return @assessment.end_at&.iso8601 || Time.now.utc if attempted_questions.empty?

    attempted_questions.map do |question|
      DateTime.parse(question['filesSavedAt']).in_time_zone
    end.max&.iso8601
  end
end


================================================
FILE: app/controllers/concerns/course/assessment/submission/koditsu/submissions_concern.rb
================================================
# frozen_string_literal: true
module Course::Assessment::Submission::Koditsu::SubmissionsConcern
  extend ActiveSupport::Concern
  include Course::Assessment::Question::KoditsuQuestionConcern
  include Course::Assessment::Submission::Koditsu::UsersConcern
  include Course::Assessment::Submission::Koditsu::AnswersConcern
  include Course::Assessment::Submission::Koditsu::TestCasesConcern
  include Course::Assessment::Submission::Koditsu::SubmissionTimesConcern

  def fetch_all_submissions_from_koditsu(assessment, user)
    @assessment = assessment
    @user = user
    submission_service = Course::Assessment::Submission::KoditsuSubmissionService.new(@assessment)
    status, response = submission_service.run_fetch_all_submissions

    return [status, nil] if status != 200 && status != 207

    process_fetch_submissions_response(response)
  end

  def process_fetch_submissions_response(response)
    @all_submissions = response
    @questions = @assessment.questions.includes({ actable: :test_cases })
    @test_cases_order = test_cases_order_for(@questions)
    @cu_submission_hash = course_user_submission_hash(@all_submissions)

    process_all_submissions
  end

  private

  def submission_status_hash
    {
      'inProgress' => 'attempting',
      'submitted' => 'submitted'
    }
  end

  def process_all_submissions
    create_new_submissions_if_not_existing

    @submission_hash = Course::Assessment::Submission.where(assessment: @assessment).to_h do |s|
      [s.creator_id, s]
    end

    @cu_submission_hash.each do |creator, submission|
      process_submission(submission, @submission_hash[creator.id])
    end
  end

  def process_submission(submission, cm_submission)
    state = submission_status_hash[submission['status']]
    submitted_at = calculate_submission_time(state, submission['questions'])

    cm_submission.class.transaction do
      update_submission(cm_submission, state, submitted_at)
      process_submission_answers(submission, cm_submission)
    end
  end

  def create_new_submissions_if_not_existing
    existing_submission_user_ids = Course::Assessment::Submission.where(assessment: @assessment).
                                   pluck(:creator_id)
    koditsu_submission_user_ids = @cu_submission_hash.keys.map { |creator, _| creator.id }
    user_ids_without_submission = koditsu_submission_user_ids - existing_submission_user_ids

    return if user_ids_without_submission.empty?

    user_info_hash = user_related_hash(user_ids_without_submission)

    user_ids_without_submission.each do |user_id|
      user, course_user = user_info_hash[user_id]

      create_new_submission_for(user, course_user)
    end
  end

  def create_new_submission_for(creator, course_user)
    User.with_stamper(creator) do
      new_submission = @assessment.submissions.new(creator: creator,
                                                   course_user: course_user)
      success = @assessment.create_new_submission(new_submission, course_user)

      raise ActiveRecord::Rollback unless success

      new_submission.create_new_answers
    end
  end

  def update_submission(cm_submission, state, submitted_at)
    update_submission_object = { workflow_state: state, submitted_at: submitted_at }

    User.with_stamper(@user) do
      raise ActiveRecord::Rollback unless cm_submission.update!(update_submission_object)
    end
  end

  def process_submission_answers(submission, cm_submission)
    answers = Course::Assessment::Answer.includes(:question).where(submission_id: cm_submission.id)

    build_answer_hash(answers)

    raise ActiveRecord::Rollback unless destroy_all_existing_autogradings(answers)
    raise ActiveRecord::Rollback unless destroy_all_existing_files(answers)

    submission_answers = submission['questions'].reject do |submission_answer|
      ['notStarted', 'error'].include?(submission_answer['status'])
    end

    process_all_answers(submission_answers)
  end
end


================================================
FILE: app/controllers/concerns/course/assessment/submission/koditsu/test_cases_concern.rb
================================================
# frozen_string_literal: true
module Course::Assessment::Submission::Koditsu::TestCasesConcern
  extend ActiveSupport::Concern

  def test_cases_order_for(questions)
    questions.to_h do |question|
      test_cases = question.actable.test_cases
      [question.id, sort_for_koditsu(test_cases)]
    end
  end

  private

  def order_test_cases_type
    {
      'public' => 0,
      'private' => 1,
      'evaluation' => 2
    }
  end

  def sort_for_koditsu(test_cases)
    return [] if test_cases.empty?

    mapped_test_cases = test_cases.map do |tc|
      [tc.id, tc.identifier.split('/').last]
    end

    sorted_test_cases = mapped_test_cases.sort_by do |_, identifier|
      parts = identifier.split('_')

      [order_test_cases_type[parts[1]], parts[2].to_i]
    end

    sorted_test_cases.map { |id, _| id }.each_with_index.to_h { |id, index| [index + 1, id] }
  end
end


================================================
FILE: app/controllers/concerns/course/assessment/submission/koditsu/users_concern.rb
================================================
# frozen_string_literal: true
module Course::Assessment::Submission::Koditsu::UsersConcern
  extend ActiveSupport::Concern

  def user_related_hash(user_ids)
    user_hash = User.where(id: user_ids).to_h { |u| [u.id, u] }
    course_user_hash = CourseUser.where(course_id: @assessment.course.id,
                                        user_id: user_ids).to_h do |cu|
      [cu.user_id, cu]
    end

    user_ids.to_h do |uid|
      [uid, [user_hash[uid], course_user_hash[uid]]]
    end
  end

  def course_user_submission_hash(submissions)
    es_hash = email_submission_hash(submissions)
    ecu_hash = email_course_user_hash(es_hash.keys)

    ecu_hash.to_h do |email, user|
      [user, es_hash[email]]
    end
  end

  def email_course_user_hash(emails)
    user_hash = User.
                joins(:emails).
                where(user_emails: { email: emails }).to_h do |user|
      [user.id, user]
    end

    CourseUser.where(course_id: @assessment.course.id,
                     user_id: user_hash.keys).to_h do |cu|
      [user_hash[cu.user_id].email, user_hash[cu.user_id]]
    end
  end

  def email_submission_hash(submissions)
    attempted_submissions = submissions.reject do |submission|
      submission['status'] == 'notStarted' || submission['status'] == 'error'
    end

    attempted_submissions.to_h { |s| [s['user']['email'], s] }
  end
end


================================================
FILE: app/controllers/concerns/course/assessment/submission/monitoring_concern.rb
================================================
# frozen_string_literal: true
module Course::Assessment::Submission::MonitoringConcern
  extend ActiveSupport::Concern

  included do
    before_action :check_blocked_by_monitor, only: [:create, :edit, :update]

    after_action :stop_monitoring_session_if_submitted, only: [:update]
  end

  def should_monitor? # rubocop:disable Metrics/CyclomaticComplexity
    monitoring_component_enabled? &&
      current_user.id == @submission.creator_id &&
      current_course_user&.student? &&
      can?(:create, Course::Monitoring::Session.new(creator_id: current_user.id)) &&
      @assessment&.monitor&.enabled? &&
      @submission.attempting?
  end

  def monitoring_service
    return unless should_monitor? || can_update_monitoring_session?

    @monitoring_service ||= Course::Assessment::Submission::MonitoringService.for(@submission, @assessment, session)
  end

  private

  def monitoring_component_enabled?
    current_component_host[:course_monitoring_component].present?
  end

  def can_update_monitoring_session?
    can?(:update, Course::Monitoring::Session.new)
  end

  def stop_monitoring_session_if_submitted
    monitoring_service&.stop! if @submission.submitted?
  end

  def check_blocked_by_monitor
    render json: { newSessionUrl: course_assessment_path(current_course, @assessment) } if blocked_by_monitor?
  end

  def blocked_by_monitor?
    should_monitor? && monitoring_service&.should_block?(request)
  end
end


================================================
FILE: app/controllers/concerns/course/assessment/submission/submissions_controller_service_concern.rb
================================================
# frozen_string_literal: true
module Course::Assessment::Submission::SubmissionsControllerServiceConcern
  extend ActiveSupport::Concern

  private

  # Get the service class based on the assessment display mode.
  #
  # @return [Class] The class of the service.
  def service_class
    Course::Assessment::Submission::UpdateService
  end

  # Instantiate a service based on the assessment display mode.
  #
  # @return [Course::Assessment::Submission::UpdateService] The service instance.
  def service
    @service ||= service_class.new(self, assessment: @assessment, submission: @submission)
  end

  # Extract the defined instance variables from the service, so that views can access them.
  # Call this method at the end of the action if there are any instance variables defined in the
  # action.
  # @param [Course::Assessment::UpdateService] service the service instance.
  def extract_instance_variables(service)
    service.instance_variables.each do |name|
      value = service.instance_variable_get(name)
      instance_variable_set(name, value)
    end
  end

  module ClassMethods
    # Delegate the action to the service and extract the instance variables from the service after
    # the action is done.
    # @param [Symbol] action the name of the action to delegate.
    def delegate_to_service(action)
      define_method(action) do
        service.public_send(action)
        extract_instance_variables(service)
      end
    end
  end
end


================================================
FILE: app/controllers/concerns/course/assessment/submission_concern.rb
================================================
# frozen_string_literal: true
module Course::Assessment::SubmissionConcern
  extend ActiveSupport::Concern

  private

  def authorize_submission!
    if @submission.attempting?
      authorize!(:update, @submission)
    else
      authorize!(:read, @submission)
    end
  end

  def check_password
    return unless @submission.attempting?
    return if !@assessment.session_password_protected? || can?(:manage, @assessment)
    return if authentication_service.authenticated?

    log_service.log_submission_access(request)

    render json: { newSessionUrl: new_session_path }
  end

  def authentication_service
    @authentication_service ||=
      Course::Assessment::SessionAuthenticationService.new(@assessment, current_session_id, @submission)
  end

  def log_service
    @log_service ||=
      Course::Assessment::SessionLogService.new(@assessment, current_session_id, @submission)
  end

  def new_session_path
    new_course_assessment_session_path(
      current_course, @assessment, submission_id: @submission.id
    )
  end
end


================================================
FILE: app/controllers/concerns/course/assessment_conditional_concern.rb
================================================
# frozen_string_literal: true
module Course::AssessmentConditionalConcern
  extend ActiveSupport::Concern

  def success_action
    render partial: 'course/condition/conditions', locals: { conditional: @conditional }
  end

  def set_conditional
    @conditional = Course::Assessment.find(conditional_params[:assessment_id])
  end

  private

  def conditional_params
    params.permit(:assessment_id)
  end
end


================================================
FILE: app/controllers/concerns/course/cikgo_chats_concern.rb
================================================
# frozen_string_literal: true
module Course::CikgoChatsConcern
  extend ActiveSupport::Concern

  def find_or_create_room(course_user)
    return unless course_user.present?

    user = course_user.user
    create_cikgo_user(user) if user.cikgo_user.nil?
    Cikgo::ChatsService.find_or_create_room!(course_user)
  end

  def get_mission_control_url(course_user)
    Cikgo::ChatsService.mission_control!(course_user)
  end

  private

  def create_cikgo_user(user)
    provider_user_id = current_decoded_token[:sub]
    image_url = helpers.user_image(user, url: true)
    provided_user_id = Cikgo::UsersService.authenticate!(user, provider_user_id, image_url)

    (user.cikgo_user || user.build_cikgo_user).provided_user_id = provided_user_id
    user.cikgo_user.save!
  end
end


================================================
FILE: app/controllers/concerns/course/cikgo_push_concern.rb
================================================
# frozen_string_literal: true
module Course::CikgoPushConcern
  extend ActiveSupport::Concern
  include Cikgo::PushableItemConcern

  private

  def push_lesson_plan_items_to_remote_course
    return unless current_course.component_enabled?(Course::StoriesComponent)

    Cikgo::ResourcesService.push_repository!(
      current_course,
      course_url(current_course),
      pushable_lesson_plan_items.filter_map do |item|
        actable = item.actable
        kind = actable.class.name.demodulize

        {
          id: item.id.to_s,
          kind: kind,
          name: item.title,
          description: item.description,
          url: send("course_#{kind.underscore}_url", current_course, actable)
        }
      end
    )
  end

  def pushable_lesson_plan_items
    current_course.lesson_plan_items.published.includes(:actable).
      where(actable_type: pushable_lesson_plan_item_types.map(&:name))
  end
end


================================================
FILE: app/controllers/concerns/course/discussion/posts_concern.rb
================================================
# frozen_string_literal: true
module Course::Discussion::PostsConcern
  extend ActiveSupport::Concern

  included do
    before_action :set_topic
    load_and_authorize_resource :post, through: :discussion_topic,
                                       class: 'Course::Discussion::Post', parent: false
  end

  protected

  # Update pending status of the topic:
  #   If the student replies to the topic, set to true.
  #   If the staff replies the post, set to false.
  #
  # @return [Boolean] Boolean on whether the update is successful.
  def update_topic_pending_status
    return true if !current_course_user || skip_update_topic_status

    if current_course_user.teaching_staff?
      @post.topic.unmark_as_pending
    else
      @post.topic.mark_as_pending
    end
  end

  # Option for controller to skip the topic_status.
  def skip_update_topic_status
    false
  end

  # Create topic subscriptions for related users
  #
  # @return [Boolean] True if all subscriptions are created successfully.
  def create_topic_subscription
    raise NotImplementedError, 'To be implemented by the concrete topic posts controller.'
  end

  # The discussion topic record that posts belong to.
  # When your model uses 'acts_as :topic', you can write: 'your_instance.topic' in this method.
  #
  # @return [Course::Discussion::Topic] The discussion topic record.
  def discussion_topic
    raise NotImplementedError, 'To be implemented by the concrete topic posts controller.'
  end

  private

  def post_params
    params.require(:discussion_post).permit(:title, :text, :parent_id, :workflow_state, :is_anonymous,
                                            codaveri_feedback_attributes: [:id, :rating, :status])
  end

  def set_topic
    @discussion_topic ||= discussion_topic
  end
end


================================================
FILE: app/controllers/concerns/course/forum/auto_answering_concern.rb
================================================
# frozen_string_literal: true
module Course::Forum::AutoAnsweringConcern
  extend ActiveSupport::Concern

  def auto_answer_action(query_post, topic, is_regenerated_response: false)
    return unless current_course.component_enabled?(Course::RagWiseComponent)

    return if response_should_not_be_generated?(is_regenerated_response)

    settings = rag_settings
    # ensures that when manually generating new reply it will always draft
    settings[:response_workflow] = '0' if is_regenerated_response

    system ||= User.find(User::SYSTEM_USER_ID)
    raise 'No system user. Did you run rake db:seed?' unless system

    query_post.rag_auto_answer!(topic, system, nil, settings)
  end

  def publish_post_action
    return false unless current_course.component_enabled?(Course::RagWiseComponent)

    @post.publish!
    publish_post(@post, @topic, current_user, current_course_user)
  end

  def last_rag_auto_answering_job
    return head(:bad_request) unless current_course.component_enabled?(Course::RagWiseComponent)

    job = @post.rag_auto_answering&.job
    (job&.status == 'submitted') ? job : nil
  end

  def rag_settings
    rag_component = current_component_host[:course_rag_wise_component]&.settings
    {
      response_workflow: rag_component&.response_workflow,
      roleplay: rag_component&.roleplay
    }
  end

  def publish_post(post, topic, current_author, current_course_author)
    # In case of conditional publish, when non course-creator publish AI responses
    # The post creator will become the person who pressed the publish button
    post.creator = current_author
    post.updater = current_author

    result = ActiveRecord::Base.transaction do
      raise ActiveRecord::Rollback unless post.save && create_topic_subscription(topic, current_author)
      raise ActiveRecord::Rollback unless topic.update_column(:latest_post_at, post.updated_at)

      true
    end

    send_created_notification(current_author, current_course_author, post) if result
    result
  end

  def create_topic_subscription(topic, current_user)
    if topic.forum.forum_topics_auto_subscribe
      topic.ensure_subscribed_by(current_user)
    else
      true
    end
  end

  def send_created_notification(current_author, current_course_author, post)
    return unless current_author

    Course::Forum::PostNotifier.post_replied(current_author, current_course_author, post)
  end

  private

  def response_should_not_be_generated?(is_regenerated_response)
    !is_regenerated_response && (current_course_user.staff? || rag_settings[:response_workflow] == 'no')
  end
end


================================================
FILE: app/controllers/concerns/course/forum/topic_controller_hiding_concern.rb
================================================
# frozen_string_literal: true
module Course::Forum::TopicControllerHidingConcern
  extend ActiveSupport::Concern

  def set_hidden
    if @topic.update(hidden_params)
      head :ok
    else
      render json: { errors: @topic.errors }, status: :bad_request
    end
  end

  private

  def hidden_params
    params.permit(:hidden)
  end
end


================================================
FILE: app/controllers/concerns/course/forum/topic_controller_locking_concern.rb
================================================
# frozen_string_literal: true
module Course::Forum::TopicControllerLockingConcern
  extend ActiveSupport::Concern

  def set_locked
    if @topic.update(locked_params)
      head :ok
    else
      render json: { errors: @topic.errors }, status: :bad_request
    end
  end

  private

  def locked_params
    params.permit(:locked)
  end
end


================================================
FILE: app/controllers/concerns/course/forum/topic_controller_subscription_concern.rb
================================================
# frozen_string_literal: true
module Course::Forum::TopicControllerSubscriptionConcern
  extend ActiveSupport::Concern

  def subscribe
    authorize!(:read, @topic)
    if set_subscription_state
      head :ok
    else
      render json: { errors: @topic.errors }, status: :bad_request
    end
  end

  private

  def set_subscription_state
    if subscribe?
      @topic.subscriptions.create(user: current_user)
    else
      @topic.subscriptions.where(user: current_user).destroy_all
    end
  end

  def subscribe?
    params[:subscribe] == true
  end
end


================================================
FILE: app/controllers/concerns/course/group/group_manager_concern.rb
================================================
# frozen_string_literal: true
module Course::Group::GroupManagerConcern
  extend ActiveSupport::Concern
  def manageable_groups
    @manageable_groups ||= current_course.groups.accessible_by(current_ability, :manage)
  end

  def viewable_group_categories
    @viewable_group_categories ||= current_course.group_categories.accessible_by(current_ability)
  end
end


================================================
FILE: app/controllers/concerns/course/koditsu_workspace_concern.rb
================================================
# frozen_string_literal: true
module Course::KoditsuWorkspaceConcern
  extend ActiveSupport::Concern

  def setup_koditsu_workspace
    workspace_service = Course::KoditsuWorkspaceService.new(current_course)
    response = workspace_service.run_create_koditsu_workspace_service

    workspace_id = response['id']
    current_course.update!(koditsu_workspace_id: workspace_id)
  end
end


================================================
FILE: app/controllers/concerns/course/lesson_plan/acts_as_lesson_plan_item_concern.rb
================================================
# frozen_string_literal: true
module Course::LessonPlan::ActsAsLessonPlanItemConcern
  extend ActiveSupport::Concern

  module ClassMethods
    # Use method to build new specific lesson_plan_items
    # Refer to app/controllers/course/assessment/question/controller.rb for motivation
    def build_and_authorize_new_lesson_plan_item(item_name, options)
      before_action only: options[:only], except: options[:except] do
        specific_item = options[:class].new
        specific_item.lesson_plan_item.course = @course
        if action_name != 'new'
          item_params = send("#{item_name}_params")
          specific_item.assign_attributes(item_params.except(:item))
        end
        authorize!(action_name.to_sym, specific_item)
        instance_variable_set("@#{item_name}", specific_item) unless instance_variable_get("@#{item_name}")
      end
    end
  end
end


================================================
FILE: app/controllers/concerns/course/lesson_plan/learning_rate_concern.rb
================================================
# frozen_string_literal: true
module Course::LessonPlan::LearningRateConcern
  extend ActiveSupport::Concern

  include Course::LessonPlan::StoriesConcern

  # Returns { lesson_plan_item_id => submitted_time or nil }.
  # If the lesson plan item is a key in this hash then we consider the item "submitted" regardless of whether we have a
  # submission time for it.
  #
  # @param [CourseUser] course_user The course user to compute the lesson plan items submission time hash for.
  # @return [Hash{Integer=>ActiveSupport::TimeWithZone|nil}] A hash of submitted lesson plan items' ID to their
  #   submitted time, if relevant/available.
  def lesson_plan_items_submission_time_hash(course_user)
    lesson_plan_items_submission_time_hash = {}
    # Extend this if more lesson plan items to personalize are added in the future.
    merge_course_assessments(lesson_plan_items_submission_time_hash, course_user)
    merge_course_videos(lesson_plan_items_submission_time_hash, course_user)
    merge_course_stories(lesson_plan_items_submission_time_hash, course_user)
  end

  # Computes the learning rate exponential moving average for the given course user.
  #
  # @param [CourseUser] course_user The course user to compute the learning rate for.
  # @param [Array<Course::LessonPlan::Item>] items_affecting_personal_times An array of lesson plan items that affect
  #   personal times, sorted by the start_at for the given user, i.e. via time_for(course_user).start_at.
  # @param [Hash{Integer=>ActiveSupport::TimeWithZone|nil}] submitted_items A hash of submitted lesson plan items' ID to
  #   their submitted time, if relevant/available.
  # @param [Float] alpha Alpha value used in exponential moving average computation.
  # @return [Float|nil] Learning rate exponential moving average, if computable.
  def compute_learning_rate_ema(course_user, items_affecting_personal_times, submitted_items, alpha = 0.4) # rubocop:disable Metrics/AbcSize
    submitted_items_affecting_personal_times = items_affecting_personal_times.
                                               select { |i| i.id.in? submitted_items.keys }.
                                               select { |i| i.time_for(course_user).end_at.present? }
    return nil if submitted_items_affecting_personal_times.empty?

    learning_rate_ema = 1.0
    # Currently, for the item to affect learning rate, it needs to have an end_at timing.
    # In the future, we may want to consider other ways of computing how much an item affects learning rate.
    submitted_items_affecting_personal_times.each do |item|
      times = item.time_for(course_user)
      next if times.end_at - times.start_at == 0 || submitted_items[item.id].nil?

      learning_rate = (submitted_items[item.id] - times.start_at) / (times.end_at - times.start_at)
      learning_rate = [learning_rate, 0].max
      learning_rate_ema = (alpha * learning_rate) + ((1 - alpha) * learning_rate_ema)
    end
    learning_rate_ema
  end

  # Bounds the learning rate based on a given min and max learning rate.
  # Min/max overall learning rate refers to how early/late a student is allowed to complete the course.
  #
  # E.g. if max_overall_lr = 2 means a student is allowed to complete a 1-month course over 2 months.
  # However, if the student somehow managed to complete half of the course within the first day, then we can allow him
  # to continue at lr = 4 and still have the student complete the course over 2 months. This method computes the
  # effective limits to preserve the overall min/max lr.
  #
  # NOTE: It is completely possible for negative results (even -infinity), i.e. student needs to go back in time in
  # order to have any hope of completing the course within the limits. The algorithm needs to take care of this.
  #
  # @param [CourseUser] course_user The course user to compute the learning rate for.
  # @param [Array<Course::LessonPlan::Item>] items An array of lesson plan items for the course user's course,
  #   sorted by the start_at for the given user, i.e. via time_for(course_user).start_at.
  # @param [Hash{Integer=>ActiveSupport::TimeWithZone|nil}] submitted_items A hash of submitted lesson plan items' ID to
  #   their submitted time, if relevant/available.
  # @param [Float] min_learning_rate The minimum overall learning rate.
  # @param [Float] max_learning_rate The maximum overall learning rate.
  # @return [Array<Float>] An array pair containing [min learning rate, max learning rate].
  def compute_learning_rate_effective_limits(course_user, items, submitted_items, min_learning_rate, max_learning_rate) # rubocop:disable Metrics/AbcSize
    course_start = items.first.start_at
    course_end = items.last.start_at
    last_submitted_item = items.reverse_each.lazy.
                          # TODO: Look into whether there's a need to filter on affects_personal_times?
                          select { |item| item.affects_personal_times? && item.id.in?(submitted_items.keys) }.
                          first
    return [min_learning_rate, max_learning_rate] if last_submitted_item.nil?

    reference_remaining_time = items.last.start_at - last_submitted_item.reference_time_for(course_user).start_at
    reference_remaining_time += 1e-99 # Prevent division by zero.

    min_remaining_time = course_start + (min_learning_rate * (course_end - course_start)) -
                         last_submitted_item.time_for(course_user).start_at
    max_remaining_time = course_start + (max_learning_rate * (course_end - course_start)) -
                         last_submitted_item.time_for(course_user).start_at

    [min_remaining_time / reference_remaining_time, max_remaining_time / reference_remaining_time]
  end

  def lesson_plan_items_with_sorted_times_for(course_user)
    course_user.course.lesson_plan_items.published.
      with_reference_times_for(course_user).
      with_personal_times_for(course_user).
      to_a.
      concat(stories_for(course_user)).
      sort_by { |item| item.time_for(course_user).start_at }
  end

  private

  # Merges course assessment submissions into the given hash, with the following format:
  # { lesson_plan_item_id => submitted_time }
  #
  # @param [Hash{Integer=>ActiveSupport::TimeWithZone|nil}] hash A hash of submitted lesson plan items' ID to their
  #   submitted time, if relevant/available.
  # @param [CourseUser] course_user Course user to retrieve course assessments for.
  # @return [Hash{Integer=>ActiveSupport::TimeWithZone|nil}] Data with course assessment submission data merged in.
  def merge_course_assessments(hash, course_user)
    # Assessments - consider submitted only if submitted_at is present
    hash.merge!(
      course_user.course.assessments.
      with_submissions_by(course_user.user).
      select { |x| x.submissions.present? && x.submissions.first.submitted_at.present? }.
      to_h { |x| [x.lesson_plan_item.id, x.submissions.first.submitted_at] }
    )
  end

  # Merges course video submissions into the given hash, with the following format:
  # { lesson_plan_item_id => nil }
  #
  # @param [Hash{Integer=>ActiveSupport::TimeWithZone|nil}] hash A hash of submitted lesson plan items' ID to their
  #   submitted time, if relevant/available.
  # @param [CourseUser] course_user Course user to retrieve course videos for.
  # @return [Hash{Integer=>ActiveSupport::TimeWithZone|nil}] Data with course video submission data merged in.
  def merge_course_videos(hash, course_user)
    # Videos - consider submitted as long as submission exists
    hash.merge!(
      course_user.course.videos.
      with_submissions_by(course_user.user).
      select { |x| x.submissions.present? }.
      to_h { |x| [x.lesson_plan_item.id, nil] }
    )
  end

  def merge_course_stories(hash, course_user)
    hash.merge!(stories_for(course_user).filter(&:submitted_at).to_h { |s| [s.id, s.submitted_at] })
  end
end


================================================
FILE: app/controllers/concerns/course/lesson_plan/personalization_concern.rb
================================================
# frozen_string_literal: true
module Course::LessonPlan::PersonalizationConcern
  extend ActiveSupport::Concern

  # Dispatches the call to the correct personalization algorithm strategy.
  # If the algorithm takes too long (e.g. voodoo AI magic), it is responsible for scheduling an async job.
  #
  # Some properties for the algorithms:
  # - We don't shift personal dates that have already passed. This is to prevent items becoming locked
  #   when students are switched between different algos. There are thus quite a few checks for
  #   > Time.zone.now. The only exception is the backwards-shifting of already-past deadlines, which
  #   allows students to slow down their learning more effectively.
  # - We don't shift closing dates forward when the item has already opened for the student. This is to
  #   prevent students from being shocked that their deadlines have shifted forward suddenly.
  #
  # @param [CourseUser] course_user The user to update the personalized timeline for.
  # @param [String|nil] timeline_algorithm The timeline algorithm to run. If not provided, the user's timeline algorithm
  #   is used.
  # @param [Set<Number>|nil] items_to_shift A set of lesson plan item IDs to shift. If not in this set, the item won't
  #   be shifted.
  def update_personalized_timeline_for_user(course_user, timeline_algorithm = nil, items_to_shift = nil)
    timeline_algorithm ||= course_user.timeline_algorithm

    strategy = case timeline_algorithm
               when 'otot'
                 Course::LessonPlan::Strategies::OtotPersonalizationStrategy.new
               when 'fomo'
                 Course::LessonPlan::Strategies::FomoPersonalizationStrategy.new
               when 'stragglers'
                 Course::LessonPlan::Strategies::StragglersPersonalizationStrategy.new
               else
                 # Default to fixed.
                 Course::LessonPlan::Strategies::FixedPersonalizationStrategy.new
               end

    precomputed_data = strategy.precompute_data(course_user)
    strategy.execute(course_user, precomputed_data, items_to_shift)
    return if precomputed_data[:learning_rate_ema].nil?

    # Log the information for future usages
    learning_rate_record = Course::LearningRateRecord.new(course_user: course_user,
                                                          learning_rate: precomputed_data[:learning_rate_ema],
                                                          effective_min: precomputed_data[:effective_min],
                                                          effective_max: precomputed_data[:effective_max])
    learning_rate_record.save!
  end

  # Updates the personalized timeline for all course users in the course of the given lesson plan item.
  # Only the timing for the lesson plan item will be shifted. Generally, you should only call this if the timing of the
  # lesson plan item has shifted, or other personalized timeline related changes have been made for a specific item.
  def update_personalized_timeline_for_item(lesson_plan_item)
    course = Course.includes(:course_users).find(lesson_plan_item.course_id)
    course.course_users.each do |course_user|
      update_personalized_timeline_for_user(course_user, nil, Set[lesson_plan_item.id])
    end
  end
end


================================================
FILE: app/controllers/concerns/course/lesson_plan/stories_concern.rb
================================================
# frozen_string_literal: true
module Course::LessonPlan::StoriesConcern
  extend ActiveSupport::Concern

  def delete_all_future_stories_personal_times(course_user)
    future_story_ids = stories_for(course_user).filter_map do |story|
      story.id if story.personal_time_for(course_user) && story.submitted_at.blank?
    end

    return if future_story_ids.blank?

    Cikgo::TimelinesService.delete_times!(course_user, future_story_ids)
  rescue StandardError => e
    Rails.logger.error("Cikgo: Cannot delete personal times for story IDs #{future_story_ids}: #{e}")
    raise e unless Rails.env.production?
  end

  private

  def stories_for(course_user)
    @stories_for ||= Course::Story.for_course_user!(course_user) || []
  rescue StandardError => e
    Rails.logger.error("Cannot fetch stories for course user #{course_user.id}: #{e}")
    raise e unless Rails.env.production?

    []
  end
end


================================================
FILE: app/controllers/concerns/course/lesson_plan/strategies/base_personalization_strategy.rb
================================================
# frozen_string_literal: true
# The BasePersonalizationStrategy declares operations common to all, if not most, personalized timeline algorithms.
# It also defines the interface to use when calling the algorithm defined by the subclasses.
class Course::LessonPlan::Strategies::BasePersonalizationStrategy
  include Course::LessonPlan::LearningRateConcern
  # To override any of these constants, simply define the same constant in the subclass.
  LEARNING_RATE_ALPHA = 0.4
  MIN_LEARNING_RATE = 1.0
  MAX_LEARNING_RATE = 1.0
  HARD_MIN_LEARNING_RATE = 1.0
  # How generously we round off. E.g. if `threshold` = 0.5, then a datetime with a time of > 0.5 * 1.day will be
  # snapped to the next day.
  DATE_ROUNDING_THRESHOLD = 0.5

  # Returns precomputed data for the given course user.
  # The data returned depends on the strategy requirements, and will need to be of the same format
  # that the execute method accepts.
  #
  # By default, the data returned is a hash containing {
  #   items: Array<Course::LessonPlan::Item>,
  #   submitted_items: Hash{Integer=>DateTime or nil},
  #   learning_rate_ema: Float|nil
  # }
  # where items is a sorted array of lesson plan items based on the course_user start_at,
  # submitted_items is a hash of the user's submitted lesson plan items to the submission time (if available),
  # and learning_rate_ema is a learning rate exponential moving average, bounded based on algorithm specifications.
  #
  # @param [CourseUser] course_user The course user to compute data for.
  # @return [Hash] Precomputed data to aid execution.
  def precompute_data(course_user) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
    submitted_items = lesson_plan_items_submission_time_hash(course_user)
    items = lesson_plan_items_with_sorted_times_for(course_user)
    items_affecting_personal_times = items.select(&:affects_personal_times?)
    learning_rate_ema = compute_learning_rate_ema(
      course_user, items_affecting_personal_times, submitted_items, self.class::LEARNING_RATE_ALPHA
    )
    unless learning_rate_ema.nil?
      effective_min, effective_max = compute_learning_rate_effective_limits(course_user, items, submitted_items,
                                                                            self.class::MIN_LEARNING_RATE,
                                                                            self.class::MAX_LEARNING_RATE)

      effective_min = [effective_min, self.class::HARD_MIN_LEARNING_RATE].max
      effective_max = [effective_max, self.class::HARD_MIN_LEARNING_RATE].max
      learning_rate_ema = learning_rate_ema.clamp(effective_min, effective_max)
    end

    { submitted_items: submitted_items, items: items, learning_rate_ema: learning_rate_ema,
      effective_min: effective_min, effective_max: effective_max }
  end

  # Executes the relevant personalization strategy for the given course user, using the given precomputed
  # data.
  #
  # @param [CourseUser] course_user The course user to execute the strategy on.
  # @param [Hash|nil] precomputed_data Data to determine strategy execution.
  # @param [Set<Number>|nil] items_to_shift Set of item ids to shift. If provided, only items with ids in this set will
  #   be shifted.
  def execute(_course_user, _precomputed_data, _items_to_shift = nil)
    raise NotImplementedError, 'Subclasses must implmement a execute method.'
  end

  protected

  # Round to "nearest" date in course's time zone, NOT user's time zone.
  #
  # @param [ActiveSupport::TimeWithZone] datetime The datetime object to round.
  # @param [String] course_tz The time zone of the course.
  # @param [Boolean] to_2359 Whether to round off to 2359. This will set the datetime to be 2359 of the date before the
  #   rounded date.
  def round_to_date(datetime, course_tz, to_2359: false)
    prev_day = datetime.in_time_zone(course_tz).to_date.in_time_zone(course_tz).in_time_zone
    date = ((datetime - prev_day) < self.class::DATE_ROUNDING_THRESHOLD ? prev_day : prev_day + 1.day)
    to_2359 ? date - 1.minute : date
  end
end


================================================
FILE: app/controllers/concerns/course/lesson_plan/strategies/fixed_personalization_strategy.rb
================================================
# frozen_string_literal: true
class Course::LessonPlan::Strategies::FixedPersonalizationStrategy <
  Course::LessonPlan::Strategies::BasePersonalizationStrategy
  # Returns a hash containing lesson plan item ids to submission time.
  #
  # @param [CourseUser] course_user The course user to compute data for.
  # @return [Hash{Integer=>ActiveSupport::TimeWithZone|nil}] A hash of submitted lesson plan items' IDs to their
  #   submitted time, if relevant/available.
  def precompute_data(course_user)
    lesson_plan_items_submission_time_hash(course_user)
  end

  # Deletes all personal times that are not fixed or submitted. This basically causes the course user to follow the
  # reference timeline moving forward.
  #
  # @param [CourseUser] course_user The course user to compute data for.
  # @param [Hash{Integer=>ActiveSupport::TimeWithZone|nil}] precompute_data A hash of submitted lesson plan items' ID to
  #   their submitted time, if relevant/available.
  # @param [Set<Number>|nil] items_to_shift Unused and does not affect behaviour.
  def execute(course_user, precompute_data, _items_to_shift)
    course_user.personal_times.where(fixed: false).
      where.not(lesson_plan_item_id: precompute_data.keys).delete_all

    delete_all_future_stories_personal_times(course_user)
  end
end


================================================
FILE: app/controllers/concerns/course/lesson_plan/strategies/fomo_personalization_strategy.rb
================================================
# frozen_string_literal: true
class Course::LessonPlan::Strategies::FomoPersonalizationStrategy <
  Course::LessonPlan::Strategies::BasePersonalizationStrategy
  MIN_LEARNING_RATE = 0.67
  MAX_LEARNING_RATE = 1.0
  HARD_MIN_LEARNING_RATE = 0.5
  DATE_ROUNDING_THRESHOLD = 0.8

  # Shifts start_at of relevant lesson plan items and resets the bonus_end_at and end_at
  # of the same items. The amount shifted is based the learning rate precomputed.
  #
  # The expected precomputed_data is the default data from precompute_data.
  #
  # @param [CourseUser] course_user The user to adjust the personalized timeline for.
  # @param [Hash] precomputed_data The default data precomputed by precompute_data.
  # @param [Set<Number>|nil] items_to_shift Set of item ids to shift. If provided, only items with ids in this set will
  #   be shifted.
  def execute(course_user, precomputed_data, items_to_shift = nil) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
    return if precomputed_data[:learning_rate_ema].nil?

    @course_tz = course_user.course.time_zone
    reference_point = personal_point = precomputed_data[:items].first.reference_time_for(course_user).start_at
    course_user.transaction do
      precomputed_data[:items].each do |item|
        reference_point, personal_point = update_points(course_user, item, precomputed_data[:submitted_items],
                                                        reference_point, personal_point)
        next if cannot_shift_item(course_user, item, precomputed_data[:submitted_items], items_to_shift)

        reference_time = item.reference_time_for(course_user)
        personal_time = item.find_or_create_personal_time_for(course_user)
        next if item_is_open_and_straggling(personal_time, reference_time)

        shift_start_at(personal_time, reference_time, personal_point, reference_point,
                       precomputed_data[:learning_rate_ema])
        reset_bonus_end_at(personal_time, reference_time)
        reset_end_at(personal_time, reference_time)
        personal_time.save!
      end
    end
  end

  private

  # Checks if the given item should act as the most recent "anchor point" for the following shifts.
  # If the item should act, returns an array [new_reference_point, new_personal_point] computed with that item.
  # If the item should not act, then the original reference_point and personal_point will be returned.
  #
  # @param [CourseUser] course_user The user to update points for.
  # @param [Course::LessonPlan::Item] item The item to reference for the update of points.
  # @param [Hash{Integer=>ActiveSupport::TimeWithZone|nil}] submitted_items A hash of submitted lesson plan items' ID to
  #   their submitted time, if relevant/available.
  # @param [DateTime] reference_point The current reference_point.
  # @param [DateTime] personal_point The current personal_point.
  # @return [Array<ActiveSupport::TimeWithZone>] An array containing [new_reference_point, new_personal_point].
  def update_points(course_user, item, submitted_items, reference_point, personal_point)
    if item.affects_personal_times? && item.id.in?(submitted_items.keys)
      return [item.reference_time_for(course_user).start_at, item.time_for(course_user).start_at]
    end

    [reference_point, personal_point]
  end

  # Checks if the lesson plan item cannot be shifted. If cannot, the timings for this item will not be adjusted.
  # Currently, it checks for the following conditions, for it to be possible to be shifted:
  # - Item has personal times
  # - Item is not submitted
  # - Item's personal time isn't fixed
  # - Item isn't currently open with an adjusted end_at from stragglers algorithm
  # - Item ID is in the set of items to shift, if provided
  #
  # @param [CourseUser] course_user The user whose item we are checking.
  # @param [Course::LessonPlan::Item] item The item that we are checking.
  # @param [Hash{Integer=>ActiveSupport::TimeWithZone|nil}] submitted_items A hash of submitted lesson plan items' ID
  #   to their submitted time, if relevant/available.
  # @param [Set<Number>|nil] items_to_shift Set of item ids to shift. If provided, only items with ids in this set will
  #   be shifted.
  # @return [Boolean] Whether the item cannot be shifted.
  def cannot_shift_item(course_user, item, submitted_items, items_to_shift)
    !item.has_personal_times? || item.id.in?(submitted_items.keys) || item.personal_time_for(course_user)&.fixed? ||
      (!items_to_shift.nil? && !items_to_shift.include?(item.id))
  end

  def item_is_straggling(personal_time, reference_time)
    if reference_time.end_at.present? && personal_time.end_at.present?
      return reference_time.end_at < personal_time.end_at
    elsif reference_time.end_at.present? && personal_time.end_at.nil?
      return true
    end

    false
  end

  # Checks if the item is already open with a deadline shifted back by stragglers algorithm.
  # If the user was previously on the stragglers algorithm and just switched over, and has already open
  # items, we want to keep those items as they are.
  #
  # @param [Course::PersonalTime] personal_time Personal time that we are checking.
  # @param [Course::ReferenceTime] reference_time Reference time that we are referring.
  # @return [Boolean] Whether the item is already open with a deadline shifted back by stragglers algorithm
  def item_is_open_and_straggling(personal_time, reference_time)
    item_is_straggling = item_is_straggling(personal_time, reference_time)
    item_is_open = personal_time.start_at < Time.zone.now
    item_is_straggling && item_is_open
  end

  # Shifts the start_at of the personal_time forward based on the learning rate of the user and the most recent
  # personal and reference points. This major shift only occurs if the personal_time's current start_at is in the
  # future.
  #
  # In addition, it also handles the case where the reference_time's start_at has shifted forward, as the
  # start_at of the personal_time will never be later than the start_at of the reference time.
  #
  # @param [Course::PersonalTime] personal_time Personal time that we are shifting.
  # @param [Course::ReferenceTime] reference_time Reference time that we are referring.
  # @param [ActiveSupport::TimeWithZone] personal_point Personal point from the most recent item.
  # @param [ActiveSupport::TimeWithZone] reference_point Reference point from the most recent item.
  # @param [Float] learning_rate_ema Learning rate to use for computing the shift amount.
  def shift_start_at(personal_time, reference_time, personal_point, reference_point, learning_rate_ema)
    if personal_time.start_at > Time.zone.now
      personal_time.start_at =
        round_to_date(
          personal_point + ((reference_time.start_at - reference_point) * learning_rate_ema),
          @course_tz
        )
    end
    # Hard limits to make sure we don't fail bounds checks
    personal_time.start_at = [personal_time.start_at, reference_time.start_at, reference_time.end_at].compact.min
  end

  # Resets the bonus_end_at of the personal_time to that of the reference_time if the personal_time has bonus_end_at.
  # The personal time's current bonus_end_at timing must also be in the future.
  #
  # @param [Course::PersonalTime] personal_time Personal time that we are resetting.
  # @param [Course::ReferenceTime] reference_time Reference time that we are using as reference.
  def reset_bonus_end_at(personal_time, reference_time)
    return unless personal_time.bonus_end_at && personal_time.bonus_end_at > Time.zone.now

    personal_time.bonus_end_at = reference_time.bonus_end_at
  end

  # Resets the end_at of the personal_time to that of the reference_time if the personal_time has end_at.
  # The personal time's current end_at timing must also be in the future.
  #
  # @param [Course::PersonalTime] personal_time Personal time that we are resetting.
  # @param [Course::ReferenceTime] reference_time Reference time that we are using as reference.
  def reset_end_at(personal_time, reference_time)
    return unless personal_time.end_at && personal_time.end_at > Time.zone.now

    personal_time.end_at = reference_time.end_at
  end
end


================================================
FILE: app/controllers/concerns/course/lesson_plan/strategies/otot_personalization_strategy.rb
================================================
# frozen_string_literal: true
class Course::LessonPlan::Strategies::OtotPersonalizationStrategy <
  Course::LessonPlan::Strategies::BasePersonalizationStrategy
  # Returns precomputed data for the given course user.
  # This method is identical to that of BasePersonalizationStrategy except for the fact that the effective
  # learning rate is constrained based on limits determined by the initial learning rate.
  #
  # @param [CourseUser] course_user The course user to compute data for.
  # @return [Hash] Precomputed data to aid execution.
  def precompute_data(course_user) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
    submitted_items = lesson_plan_items_submission_time_hash(course_user)
    items = lesson_plan_items_with_sorted_times_for(course_user)
    items_affecting_personal_times = items.select(&:affects_personal_times?)
    learning_rate_ema = compute_learning_rate_ema(
      course_user, items_affecting_personal_times, submitted_items, self.class::LEARNING_RATE_ALPHA
    )
    unless learning_rate_ema.nil?
      strategy = if learning_rate_ema < 1
                   Course::LessonPlan::Strategies::FomoPersonalizationStrategy
                 else
                   Course::LessonPlan::Strategies::StragglersPersonalizationStrategy
                 end
      effective_min, effective_max = compute_learning_rate_effective_limits(course_user, items, submitted_items,
                                                                            strategy::MIN_LEARNING_RATE,
                                                                            strategy::MAX_LEARNING_RATE)
      effective_min = [effective_min, strategy::HARD_MIN_LEARNING_RATE].max
      effective_max = [effective_max, strategy::HARD_MIN_LEARNING_RATE].max
      bounded_learning_rate_ema = learning_rate_ema.clamp(effective_min, effective_max)
    end

    { submitted_items: submitted_items, items: items, learning_rate_ema: bounded_learning_rate_ema,
      original_learning_rate_ema: learning_rate_ema, effective_min: effective_min, effective_max: effective_max }
  end

  # Applies the appropriate algorithm strategy for the student based on the student's learning rate.
  #
  # The expected precomputed_data is the default data from precompute_data.
  #
  # @param [CourseUser] course_user The user to adjust the personalized timeline for.
  # @param [Hash] precomputed_data The default data precomputed by precompute_data.
  # @param [Set<Number>|nil] items_to_shift Set of item ids to shift. If provided, only items with ids in this set will
  #   be shifted.
  def execute(course_user, precomputed_data, items_to_shift = nil)
    return if precomputed_data[:learning_rate_ema].nil?

    # Apply the appropriate algo depending on student's original learning rate
    new_strategy = if precomputed_data[:original_learning_rate_ema] < 1
                     Course::LessonPlan::Strategies::FomoPersonalizationStrategy.new
                   else
                     Course::LessonPlan::Strategies::StragglersPersonalizationStrategy.new
                   end
    new_strategy.execute(course_user, precomputed_data, items_to_shift)
  end
end


================================================
FILE: app/controllers/concerns/course/lesson_plan/strategies/stragglers_personalization_strategy.rb
================================================
# frozen_string_literal: true
class Course::LessonPlan::Strategies::StragglersPersonalizationStrategy <
  Course::LessonPlan::Strategies::BasePersonalizationStrategy
  MIN_LEARNING_RATE = 1.0
  MAX_LEARNING_RATE = 2.0
  HARD_MIN_LEARNING_RATE = 0.8
  DATE_ROUNDING_THRESHOLD = 0.2
  STRAGGLERS_FIXES = 1

  # Shifts end_at of relevant lesson plan items and resets the bonus_end_at and start_at
  # of the same items. The amount shifted is based the learning rate precomputed.
  #
  # The expected precomputed_data is the default data from precompute_data.
  #
  # @param [CourseUser] course_user The user to adjust the personalized timeline for.
  # @param [Hash] precomputed_data The default data precomputed by precompute_data.
  # @param [Set<Number>|nil] items_to_shift Set of item ids to shift. If provided, only items with ids in this set will
  #   be shifted.
  de
Download .txt
Showing preview only (339K chars total). Download the full file or copy to clipboard to get everything.
gitextract_31rkx6m_/

├── .circleci/
│   └── config.yml
├── .codecov.yml
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── 1-bug-report.yml
│   │   ├── 2-feature-request.yml
│   │   └── config.yml
│   └── dependabot.yml
├── .gitignore
├── .gitmodules
├── .hound.yml
├── .rspec
├── .rubocop.unhound.yml
├── .rubocop.yml
├── .yardopts
├── CONTRIBUTING.md
├── Gemfile
├── LICENSE
├── README.md
├── Rakefile
├── app/
│   ├── README.md
│   ├── assets/
│   │   └── config/
│   │       └── manifest.js
│   ├── channels/
│   │   ├── application_cable/
│   │   │   ├── channel.rb
│   │   │   └── connection.rb
│   │   ├── concerns/
│   │   │   ├── application_cable_ability_concern.rb
│   │   │   ├── application_cable_authentication_concern.rb
│   │   │   ├── application_cable_component_concern.rb
│   │   │   ├── application_cable_course_concern.rb
│   │   │   └── application_cable_multitenancy_concern.rb
│   │   └── course/
│   │       ├── channel.rb
│   │       └── monitoring/
│   │           ├── heartbeat_channel.rb
│   │           └── live_monitoring_channel.rb
│   ├── controllers/
│   │   ├── announcements_controller.rb
│   │   ├── application_controller.rb
│   │   ├── attachment_references_controller.rb
│   │   ├── components/
│   │   │   └── course/
│   │   │       ├── achievements_component.rb
│   │   │       ├── announcements_component.rb
│   │   │       ├── assessments_component.rb
│   │   │       ├── codaveri_component.rb
│   │   │       ├── controller_component_host.rb
│   │   │       ├── discussion/
│   │   │       │   └── topics_component.rb
│   │   │       ├── duplication_component.rb
│   │   │       ├── experience_points_component.rb
│   │   │       ├── forums_component.rb
│   │   │       ├── groups_component.rb
│   │   │       ├── koditsu_platform_component.rb
│   │   │       ├── leaderboard_component.rb
│   │   │       ├── learning_map_component.rb
│   │   │       ├── lesson_plan_component.rb
│   │   │       ├── levels_component.rb
│   │   │       ├── materials_component.rb
│   │   │       ├── monitoring_component.rb
│   │   │       ├── multiple_reference_timelines_component.rb
│   │   │       ├── plagiarism_component.rb
│   │   │       ├── rag_wise_component.rb
│   │   │       ├── scholaistic_component.rb
│   │   │       ├── settings_component.rb
│   │   │       ├── statistics_component.rb
│   │   │       ├── stories_component.rb
│   │   │       ├── survey_component.rb
│   │   │       ├── users_component.rb
│   │   │       └── videos_component.rb
│   │   ├── concerns/
│   │   │   ├── application_ability_concern.rb
│   │   │   ├── application_announcements_concern.rb
│   │   │   ├── application_authentication_concern.rb
│   │   │   ├── application_components_concern.rb
│   │   │   ├── application_controller_multitenancy_concern.rb
│   │   │   ├── application_instance_user_concern.rb
│   │   │   ├── application_internationalization_concern.rb
│   │   │   ├── application_multitenancy.rb
│   │   │   ├── application_pagination_concern.rb
│   │   │   ├── application_user_concern.rb
│   │   │   ├── application_user_time_zone_concern.rb
│   │   │   ├── codaveri_language_concern.rb
│   │   │   ├── course/
│   │   │   │   ├── achievement_conditional_concern.rb
│   │   │   │   ├── activity_feeds_concern.rb
│   │   │   │   ├── assessment/
│   │   │   │   │   ├── answer/
│   │   │   │   │   │   └── update_answer_concern.rb
│   │   │   │   │   ├── koditsu_assessment_concern.rb
│   │   │   │   │   ├── koditsu_assessment_invitation_concern.rb
│   │   │   │   │   ├── live_feedback/
│   │   │   │   │   │   ├── file_concern.rb
│   │   │   │   │   │   ├── message_concern.rb
│   │   │   │   │   │   ├── message_file_concern.rb
│   │   │   │   │   │   └── thread_concern.rb
│   │   │   │   │   ├── monitoring/
│   │   │   │   │   │   └── seb_payload_concern.rb
│   │   │   │   │   ├── monitoring_concern.rb
│   │   │   │   │   ├── question/
│   │   │   │   │   │   ├── codaveri_question_concern.rb
│   │   │   │   │   │   ├── koditsu_question_concern.rb
│   │   │   │   │   │   ├── multiple_responses_concern.rb
│   │   │   │   │   │   ├── rubric_based_response_controller_concern.rb
│   │   │   │   │   │   └── rubric_based_response_question_concern.rb
│   │   │   │   │   ├── question_bundle_assignment_concern.rb
│   │   │   │   │   ├── submission/
│   │   │   │   │   │   ├── koditsu/
│   │   │   │   │   │   │   ├── answers_concern.rb
│   │   │   │   │   │   │   ├── submission_times_concern.rb
│   │   │   │   │   │   │   ├── submissions_concern.rb
│   │   │   │   │   │   │   ├── test_cases_concern.rb
│   │   │   │   │   │   │   └── users_concern.rb
│   │   │   │   │   │   ├── monitoring_concern.rb
│   │   │   │   │   │   └── submissions_controller_service_concern.rb
│   │   │   │   │   └── submission_concern.rb
│   │   │   │   ├── assessment_conditional_concern.rb
│   │   │   │   ├── cikgo_chats_concern.rb
│   │   │   │   ├── cikgo_push_concern.rb
│   │   │   │   ├── discussion/
│   │   │   │   │   └── posts_concern.rb
│   │   │   │   ├── forum/
│   │   │   │   │   ├── auto_answering_concern.rb
│   │   │   │   │   ├── topic_controller_hiding_concern.rb
│   │   │   │   │   ├── topic_controller_locking_concern.rb
│   │   │   │   │   └── topic_controller_subscription_concern.rb
│   │   │   │   ├── group/
│   │   │   │   │   └── group_manager_concern.rb
│   │   │   │   ├── koditsu_workspace_concern.rb
│   │   │   │   ├── lesson_plan/
│   │   │   │   │   ├── acts_as_lesson_plan_item_concern.rb
│   │   │   │   │   ├── learning_rate_concern.rb
│   │   │   │   │   ├── personalization_concern.rb
│   │   │   │   │   ├── stories_concern.rb
│   │   │   │   │   └── strategies/
│   │   │   │   │       ├── base_personalization_strategy.rb
│   │   │   │   │       ├── fixed_personalization_strategy.rb
│   │   │   │   │       ├── fomo_personalization_strategy.rb
│   │   │   │   │       ├── otot_personalization_strategy.rb
│   │   │   │   │       └── stragglers_personalization_strategy.rb
│   │   │   │   ├── reminder_service_concern.rb
│   │   │   │   ├── scholaistic/
│   │   │   │   │   └── concern.rb
│   │   │   │   ├── ssid_folder_concern.rb
│   │   │   │   ├── statistics/
│   │   │   │   │   ├── counts_concern.rb
│   │   │   │   │   ├── grades_concern.rb
│   │   │   │   │   ├── reference_times_concern.rb
│   │   │   │   │   ├── submissions_concern.rb
│   │   │   │   │   ├── times_concern.rb
│   │   │   │   │   └── users_concern.rb
│   │   │   │   ├── survey/
│   │   │   │   │   └── reordering_concern.rb
│   │   │   │   ├── unread_counts_concern.rb
│   │   │   │   └── users_controller_management_concern.rb
│   │   │   └── signals/
│   │   │       ├── emission_concern.rb
│   │   │       └── slices/
│   │   │           ├── announcements.rb
│   │   │           ├── assessment_submissions.rb
│   │   │           ├── cikgo_mission_control.rb
│   │   │           ├── cikgo_open_threads_count.rb
│   │   │           ├── comments.rb
│   │   │           ├── enrol_requests.rb
│   │   │           ├── forums.rb
│   │   │           └── videos.rb
│   │   ├── course/
│   │   │   ├── achievement/
│   │   │   │   ├── achievements_controller.rb
│   │   │   │   ├── condition/
│   │   │   │   │   ├── achievements_controller.rb
│   │   │   │   │   ├── assessments_controller.rb
│   │   │   │   │   ├── levels_controller.rb
│   │   │   │   │   ├── scholaistic_assessments_controller.rb
│   │   │   │   │   └── surveys_controller.rb
│   │   │   │   └── controller.rb
│   │   │   ├── admin/
│   │   │   │   ├── admin_controller.rb
│   │   │   │   ├── announcement_settings_controller.rb
│   │   │   │   ├── assessment_settings_controller.rb
│   │   │   │   ├── assessments/
│   │   │   │   │   ├── categories_controller.rb
│   │   │   │   │   └── tabs_controller.rb
│   │   │   │   ├── codaveri_settings_controller.rb
│   │   │   │   ├── component_settings_controller.rb
│   │   │   │   ├── controller.rb
│   │   │   │   ├── discussion/
│   │   │   │   │   └── topic_settings_controller.rb
│   │   │   │   ├── forum_settings_controller.rb
│   │   │   │   ├── leaderboard_settings_controller.rb
│   │   │   │   ├── lesson_plan_settings_controller.rb
│   │   │   │   ├── material_settings_controller.rb
│   │   │   │   ├── notification_settings_controller.rb
│   │   │   │   ├── rag_wise_settings_controller.rb
│   │   │   │   ├── scholaistic_settings_controller.rb
│   │   │   │   ├── sidebar_settings_controller.rb
│   │   │   │   ├── stories_settings_controller.rb
│   │   │   │   ├── video_settings_controller.rb
│   │   │   │   └── videos/
│   │   │   │       └── tabs_controller.rb
│   │   │   ├── announcements_controller.rb
│   │   │   ├── assessment/
│   │   │   │   ├── assessments_controller.rb
│   │   │   │   ├── categories_controller.rb
│   │   │   │   ├── component_controller.rb
│   │   │   │   ├── condition/
│   │   │   │   │   ├── achievements_controller.rb
│   │   │   │   │   ├── assessments_controller.rb
│   │   │   │   │   ├── levels_controller.rb
│   │   │   │   │   ├── scholaistic_assessments_controller.rb
│   │   │   │   │   └── surveys_controller.rb
│   │   │   │   ├── controller.rb
│   │   │   │   ├── mock_answers_controller.rb
│   │   │   │   ├── question/
│   │   │   │   │   ├── controller.rb
│   │   │   │   │   ├── forum_post_responses_controller.rb
│   │   │   │   │   ├── multiple_responses_controller.rb
│   │   │   │   │   ├── programming_controller.rb
│   │   │   │   │   ├── rubric_based_responses_controller.rb
│   │   │   │   │   ├── scribing_controller.rb
│   │   │   │   │   ├── text_responses_controller.rb
│   │   │   │   │   └── voice_responses_controller.rb
│   │   │   │   ├── question_bundle_assignments_controller.rb
│   │   │   │   ├── question_bundle_questions_controller.rb
│   │   │   │   ├── question_bundles_controller.rb
│   │   │   │   ├── question_groups_controller.rb
│   │   │   │   ├── questions_controller.rb
│   │   │   │   ├── rubrics_controller.rb
│   │   │   │   ├── sessions_controller.rb
│   │   │   │   ├── skill_branches_controller.rb
│   │   │   │   ├── skills_controller.rb
│   │   │   │   ├── submission/
│   │   │   │   │   ├── answer/
│   │   │   │   │   │   ├── answers_controller.rb
│   │   │   │   │   │   ├── controller.rb
│   │   │   │   │   │   ├── forum_post_response/
│   │   │   │   │   │   │   └── posts_controller.rb
│   │   │   │   │   │   ├── programming/
│   │   │   │   │   │   │   ├── annotations_controller.rb
│   │   │   │   │   │   │   ├── controller.rb
│   │   │   │   │   │   │   └── programming_controller.rb
│   │   │   │   │   │   ├── scribing/
│   │   │   │   │   │   │   ├── controller.rb
│   │   │   │   │   │   │   └── scribbles_controller.rb
│   │   │   │   │   │   └── text_response/
│   │   │   │   │   │       ├── controller.rb
│   │   │   │   │   │       └── text_response_controller.rb
│   │   │   │   │   ├── controller.rb
│   │   │   │   │   ├── live_feedback_controller.rb
│   │   │   │   │   ├── logs_controller.rb
│   │   │   │   │   └── submissions_controller.rb
│   │   │   │   ├── submission_question/
│   │   │   │   │   ├── comments_controller.rb
│   │   │   │   │   ├── controller.rb
│   │   │   │   │   └── submission_questions_controller.rb
│   │   │   │   └── submissions_controller.rb
│   │   │   ├── component_controller.rb
│   │   │   ├── condition/
│   │   │   │   ├── achievements_controller.rb
│   │   │   │   ├── assessments_controller.rb
│   │   │   │   ├── levels_controller.rb
│   │   │   │   ├── scholaistic_assessments_controller.rb
│   │   │   │   └── surveys_controller.rb
│   │   │   ├── conditions_controller.rb
│   │   │   ├── controller.rb
│   │   │   ├── courses_controller.rb
│   │   │   ├── discussion/
│   │   │   │   ├── posts_controller.rb
│   │   │   │   └── topics_controller.rb
│   │   │   ├── duplications_controller.rb
│   │   │   ├── enrol_requests_controller.rb
│   │   │   ├── experience_points/
│   │   │   │   ├── disbursement_controller.rb
│   │   │   │   └── forum_disbursement_controller.rb
│   │   │   ├── experience_points_records_controller.rb
│   │   │   ├── forum/
│   │   │   │   ├── component_controller.rb
│   │   │   │   ├── controller.rb
│   │   │   │   ├── forums_controller.rb
│   │   │   │   ├── posts_controller.rb
│   │   │   │   └── topics_controller.rb
│   │   │   ├── group/
│   │   │   │   ├── group_categories_controller.rb
│   │   │   │   └── groups_controller.rb
│   │   │   ├── leaderboards_controller.rb
│   │   │   ├── learning_map_controller.rb
│   │   │   ├── lesson_plan/
│   │   │   │   ├── controller.rb
│   │   │   │   ├── events_controller.rb
│   │   │   │   ├── items_controller.rb
│   │   │   │   ├── milestones_controller.rb
│   │   │   │   └── todos_controller.rb
│   │   │   ├── levels_controller.rb
│   │   │   ├── material/
│   │   │   │   ├── controller.rb
│   │   │   │   ├── folders_controller.rb
│   │   │   │   └── materials_controller.rb
│   │   │   ├── object_duplications_controller.rb
│   │   │   ├── personal_times_controller.rb
│   │   │   ├── plagiarism/
│   │   │   │   ├── assessments_controller.rb
│   │   │   │   ├── controller.rb
│   │   │   │   └── plagiarism_controller.rb
│   │   │   ├── reference_timelines_controller.rb
│   │   │   ├── reference_times_controller.rb
│   │   │   ├── rubrics_controller.rb
│   │   │   ├── scholaistic/
│   │   │   │   ├── assistants_controller.rb
│   │   │   │   ├── controller.rb
│   │   │   │   ├── scholaistic_assessments_controller.rb
│   │   │   │   └── submissions_controller.rb
│   │   │   ├── statistics/
│   │   │   │   ├── aggregate_controller.rb
│   │   │   │   ├── assessments_controller.rb
│   │   │   │   ├── controller.rb
│   │   │   │   ├── statistics_controller.rb
│   │   │   │   └── users_controller.rb
│   │   │   ├── stories/
│   │   │   │   └── stories_controller.rb
│   │   │   ├── survey/
│   │   │   │   ├── controller.rb
│   │   │   │   ├── questions_controller.rb
│   │   │   │   ├── responses_controller.rb
│   │   │   │   ├── sections_controller.rb
│   │   │   │   └── surveys_controller.rb
│   │   │   ├── user_email_subscriptions_controller.rb
│   │   │   ├── user_invitations_controller.rb
│   │   │   ├── user_notifications_controller.rb
│   │   │   ├── user_registrations_controller.rb
│   │   │   ├── users_controller.rb
│   │   │   ├── video/
│   │   │   │   ├── controller.rb
│   │   │   │   ├── submission/
│   │   │   │   │   ├── controller.rb
│   │   │   │   │   ├── sessions_controller.rb
│   │   │   │   │   └── submissions_controller.rb
│   │   │   │   ├── topics_controller.rb
│   │   │   │   └── videos_controller.rb
│   │   │   └── video_submissions_controller.rb
│   │   ├── csrf_token_controller.rb
│   │   ├── health_check_controller.rb
│   │   ├── instance_user_role_requests_controller.rb
│   │   ├── jobs_controller.rb
│   │   ├── system/
│   │   │   └── admin/
│   │   │       ├── admin_controller.rb
│   │   │       ├── announcements_controller.rb
│   │   │       ├── controller.rb
│   │   │       ├── courses_controller.rb
│   │   │       ├── get_help_controller.rb
│   │   │       ├── instance/
│   │   │       │   ├── admin_controller.rb
│   │   │       │   ├── announcements_controller.rb
│   │   │       │   ├── components_controller.rb
│   │   │       │   ├── controller.rb
│   │   │       │   ├── courses_controller.rb
│   │   │       │   ├── get_help_controller.rb
│   │   │       │   ├── user_invitations_controller.rb
│   │   │       │   └── users_controller.rb
│   │   │       ├── instances_controller.rb
│   │   │       └── users_controller.rb
│   │   ├── test/
│   │   │   ├── controller.rb
│   │   │   ├── factories_controller.rb
│   │   │   └── mailer_controller.rb
│   │   ├── user/
│   │   │   ├── confirmations_controller.rb
│   │   │   ├── emails_controller.rb
│   │   │   ├── passwords_controller.rb
│   │   │   ├── profiles_controller.rb
│   │   │   ├── registrations_controller.rb
│   │   │   └── sessions_controller.rb
│   │   └── users_controller.rb
│   ├── helpers/
│   │   ├── application_formatters_helper.rb
│   │   ├── application_helper.rb
│   │   ├── application_html_formatters_helper.rb
│   │   ├── application_jobs_helper.rb
│   │   ├── application_mailer_helper.rb
│   │   ├── application_notifications_helper.rb
│   │   ├── consolidated_opening_reminder_mailer_helper.rb
│   │   ├── course/
│   │   │   ├── achievement/
│   │   │   │   ├── achievements_helper.rb
│   │   │   │   └── controller_helper.rb
│   │   │   ├── assessment/
│   │   │   │   ├── answer/
│   │   │   │   │   └── programming_test_case_helper.rb
│   │   │   │   ├── assessments_helper.rb
│   │   │   │   ├── question/
│   │   │   │   │   └── programming_helper.rb
│   │   │   │   ├── submission/
│   │   │   │   │   └── submissions_helper.rb
│   │   │   │   └── submissions_helper.rb
│   │   │   ├── condition/
│   │   │   │   └── conditions_helper.rb
│   │   │   ├── controller_helper.rb
│   │   │   ├── discussion/
│   │   │   │   └── topics_helper.rb
│   │   │   ├── forum/
│   │   │   │   └── controller_helper.rb
│   │   │   ├── group/
│   │   │   │   └── group_categories_helper.rb
│   │   │   ├── leaderboards_helper.rb
│   │   │   ├── material/
│   │   │   │   └── folders_helper.rb
│   │   │   ├── object_duplications_helper.rb
│   │   │   └── users_helper.rb
│   │   ├── route_overrides_helper.rb
│   │   └── tmp_cleanup_helper.rb
│   ├── jobs/
│   │   ├── application_job.rb
│   │   ├── consolidated_item_email_job.rb
│   │   ├── course/
│   │   │   ├── announcement/
│   │   │   │   └── opening_reminder_job.rb
│   │   │   ├── assessment/
│   │   │   │   ├── answer/
│   │   │   │   │   ├── auto_grading_job.rb
│   │   │   │   │   ├── base_auto_grading_job.rb
│   │   │   │   │   ├── programming_codaveri_feedback_job.rb
│   │   │   │   │   └── reduce_priority_auto_grading_job.rb
│   │   │   │   ├── closing_reminder_job.rb
│   │   │   │   ├── invite_to_koditsu_job.rb
│   │   │   │   ├── plagiarism_check_job.rb
│   │   │   │   ├── question/
│   │   │   │   │   ├── answers_evaluation_job.rb
│   │   │   │   │   ├── codaveri_import_job.rb
│   │   │   │   │   └── programming_import_job.rb
│   │   │   │   └── submission/
│   │   │   │       ├── auto_feedback_job.rb
│   │   │   │       ├── auto_grading_job.rb
│   │   │   │       ├── csv_download_job.rb
│   │   │   │       ├── deleting_job.rb
│   │   │   │       ├── fetch_submissions_from_koditsu_job.rb
│   │   │   │       ├── force_submit_timed_submission_job.rb
│   │   │   │       ├── force_submitting_job.rb
│   │   │   │       ├── publishing_job.rb
│   │   │   │       ├── statistics_download_job.rb
│   │   │   │       ├── unsubmitting_job.rb
│   │   │   │       └── zip_download_job.rb
│   │   │   ├── conditional/
│   │   │   │   ├── conditional_satisfiability_evaluation_job.rb
│   │   │   │   └── coursewide_conditional_satisfiability_evaluation_job.rb
│   │   │   ├── discussion/
│   │   │   │   └── post/
│   │   │   │       └── codaveri_feedback_rating_job.rb
│   │   │   ├── duplication_job.rb
│   │   │   ├── experience_points_download_job.rb
│   │   │   ├── forum/
│   │   │   │   ├── auto_answering_job.rb
│   │   │   │   └── importing_job.rb
│   │   │   ├── lesson_plan/
│   │   │   │   └── coursewide_personalized_timeline_update_job.rb
│   │   │   ├── material/
│   │   │   │   ├── text_chunk_job.rb
│   │   │   │   └── zip_download_job.rb
│   │   │   ├── object_duplication_job.rb
│   │   │   ├── rubric/
│   │   │   │   └── rubric_evaluation_export_job.rb
│   │   │   ├── statistics/
│   │   │   │   └── assessments_score_summary_download_job.rb
│   │   │   ├── survey/
│   │   │   │   ├── closing_reminder_job.rb
│   │   │   │   └── survey_download_job.rb
│   │   │   ├── user_deletion_job.rb
│   │   │   └── video/
│   │   │       └── closing_reminder_job.rb
│   │   ├── read_marks_clean_up_job.rb
│   │   ├── user_email_database_cleanup_job.rb
│   │   └── video_statistic_update_job.rb
│   ├── mailers/
│   │   ├── activity_mailer.rb
│   │   ├── application_mailer.rb
│   │   ├── consolidated_opening_reminder_mailer.rb
│   │   ├── course/
│   │   │   └── mailer.rb
│   │   ├── instance/
│   │   │   └── mailer.rb
│   │   └── instance_user_role_request_mailer.rb
│   ├── models/
│   │   ├── .rubocop.yml
│   │   ├── ability.rb
│   │   ├── activity.rb
│   │   ├── application_record.rb
│   │   ├── attachment.rb
│   │   ├── attachment_reference.rb
│   │   ├── cikgo_user.rb
│   │   ├── components/
│   │   │   ├── ability_host.rb
│   │   │   ├── course/
│   │   │   │   ├── achievements_ability_component.rb
│   │   │   │   ├── announcements_ability_component.rb
│   │   │   │   ├── assessments_ability_component.rb
│   │   │   │   ├── conditions_ability_component.rb
│   │   │   │   ├── course_ability_component.rb
│   │   │   │   ├── course_user_ability_component.rb
│   │   │   │   ├── discussions_ability_component.rb
│   │   │   │   ├── duplication_ability_component.rb
│   │   │   │   ├── experience_points_disbursement_ability_component.rb
│   │   │   │   ├── experience_points_records_ability_component.rb
│   │   │   │   ├── forums_ability_component.rb
│   │   │   │   ├── groups_ability_component.rb
│   │   │   │   ├── learning_map_ability_component.rb
│   │   │   │   ├── lesson_plan_ability_component.rb
│   │   │   │   ├── levels_ability_component.rb
│   │   │   │   ├── materials_ability_component.rb
│   │   │   │   ├── model_component_host.rb
│   │   │   │   ├── monitoring_ability_component.rb
│   │   │   │   ├── plagiarism_ability_component.rb
│   │   │   │   ├── rag_wise_setting_ability_component.rb
│   │   │   │   ├── scholaistic_ability_component.rb
│   │   │   │   ├── statistics_ability_component.rb
│   │   │   │   ├── stories_ability_component.rb
│   │   │   │   ├── surveys_ability_component.rb
│   │   │   │   ├── timelines_ability_component.rb
│   │   │   │   ├── user_email_unsubscriptions_ability_component.rb
│   │   │   │   └── videos_ability_component.rb
│   │   │   ├── system/
│   │   │   │   └── admin/
│   │   │   │       ├── instance_admin_ability_component.rb
│   │   │   │       ├── instance_announcements_ability_component.rb
│   │   │   │       ├── system_admin_ability_component.rb
│   │   │   │       └── system_announcements_ability_component.rb
│   │   │   ├── user_notifications_ability_component.rb
│   │   │   └── users_ability_component.rb
│   │   ├── concerns/
│   │   │   ├── announcement_concern.rb
│   │   │   ├── application_acts_as_concern.rb
│   │   │   ├── application_userstamp_concern.rb
│   │   │   ├── cikgo/
│   │   │   │   └── pushable_item_concern.rb
│   │   │   ├── component_settings_concern.rb
│   │   │   ├── course/
│   │   │   │   ├── assessment/
│   │   │   │   │   ├── new_submission_concern.rb
│   │   │   │   │   ├── questions_concern.rb
│   │   │   │   │   ├── submission/
│   │   │   │   │   │   ├── answers_concern.rb
│   │   │   │   │   │   ├── cikgo_task_completion_concern.rb
│   │   │   │   │   │   ├── notification_concern.rb
│   │   │   │   │   │   ├── todo_concern.rb
│   │   │   │   │   │   └── workflow_event_concern.rb
│   │   │   │   │   └── todo_concern.rb
│   │   │   │   ├── closing_reminder_concern.rb
│   │   │   │   ├── course_components_concern.rb
│   │   │   │   ├── course_user_type_concern.rb
│   │   │   │   ├── discussion/
│   │   │   │   │   ├── post/
│   │   │   │   │   │   ├── ordering_concern.rb
│   │   │   │   │   │   └── retrieval_concern.rb
│   │   │   │   │   └── topic/
│   │   │   │   │       └── posts_concern.rb
│   │   │   │   ├── duplication_concern.rb
│   │   │   │   ├── forum_participation_concern.rb
│   │   │   │   ├── lesson_plan/
│   │   │   │   │   ├── item/
│   │   │   │   │   │   └── cikgo_push_concern.rb
│   │   │   │   │   └── item_todo_concern.rb
│   │   │   │   ├── levels_concern.rb
│   │   │   │   ├── material/
│   │   │   │   │   └── folder/
│   │   │   │   │       └── ordering_concern.rb
│   │   │   │   ├── material_concern.rb
│   │   │   │   ├── opening_reminder_concern.rb
│   │   │   │   ├── sanitize_description_concern.rb
│   │   │   │   ├── search_concern.rb
│   │   │   │   ├── settings/
│   │   │   │   │   └── lesson_plan_settings_concern.rb
│   │   │   │   ├── survey/
│   │   │   │   │   └── response/
│   │   │   │   │       ├── cikgo_task_completion_concern.rb
│   │   │   │   │       └── todo_concern.rb
│   │   │   │   └── video/
│   │   │   │       ├── interval_query_concern.rb
│   │   │   │       ├── submission/
│   │   │   │       │   ├── notification_concern.rb
│   │   │   │       │   ├── statistic/
│   │   │   │       │   │   └── cikgo_task_completion_concern.rb
│   │   │   │       │   └── todo_concern.rb
│   │   │   │       ├── url_concern.rb
│   │   │   │       └── watch_statistics_concern.rb
│   │   │   ├── course_component_query_concern.rb
│   │   │   ├── course_user/
│   │   │   │   ├── achievements_concern.rb
│   │   │   │   ├── level_progress_concern.rb
│   │   │   │   ├── staff_concern.rb
│   │   │   │   └── todo_concern.rb
│   │   │   ├── duplication_state_tracking_concern.rb
│   │   │   ├── generic/
│   │   │   │   └── collection_concern.rb
│   │   │   ├── instance/
│   │   │   │   └── course_components_concern.rb
│   │   │   ├── instance_user_search_concern.rb
│   │   │   ├── safe_mark_as_read_concern.rb
│   │   │   ├── time_zone_concern.rb
│   │   │   ├── user_authentication_concern.rb
│   │   │   ├── user_notifications_concern.rb
│   │   │   └── user_search_concern.rb
│   │   ├── course/
│   │   │   ├── achievement.rb
│   │   │   ├── announcement.rb
│   │   │   ├── assessment/
│   │   │   │   ├── answer/
│   │   │   │   │   ├── auto_grading.rb
│   │   │   │   │   ├── forum_post.rb
│   │   │   │   │   ├── forum_post_response.rb
│   │   │   │   │   ├── multiple_response.rb
│   │   │   │   │   ├── multiple_response_option.rb
│   │   │   │   │   ├── programming.rb
│   │   │   │   │   ├── programming_ability.rb
│   │   │   │   │   ├── programming_auto_grading.rb
│   │   │   │   │   ├── programming_auto_grading_test_result.rb
│   │   │   │   │   ├── programming_file.rb
│   │   │   │   │   ├── programming_file_annotation.rb
│   │   │   │   │   ├── rubric_based_response.rb
│   │   │   │   │   ├── rubric_based_response_selection.rb
│   │   │   │   │   ├── rubric_playground_answer_adapter.rb
│   │   │   │   │   ├── scribing.rb
│   │   │   │   │   ├── scribing_scribble.rb
│   │   │   │   │   ├── text_response.rb
│   │   │   │   │   └── voice_response.rb
│   │   │   │   ├── answer.rb
│   │   │   │   ├── assessment_ability.rb
│   │   │   │   ├── category.rb
│   │   │   │   ├── link.rb
│   │   │   │   ├── live_feedback/
│   │   │   │   │   ├── file.rb
│   │   │   │   │   ├── message.rb
│   │   │   │   │   ├── message_file.rb
│   │   │   │   │   ├── message_option.rb
│   │   │   │   │   ├── option.rb
│   │   │   │   │   └── thread.rb
│   │   │   │   ├── live_feedback.rb
│   │   │   │   ├── live_feedback_code.rb
│   │   │   │   ├── live_feedback_comment.rb
│   │   │   │   ├── plagiarism_check.rb
│   │   │   │   ├── question/
│   │   │   │   │   ├── forum_post_response.rb
│   │   │   │   │   ├── mock_answer/
│   │   │   │   │   │   └── answer_adapter.rb
│   │   │   │   │   ├── mock_answer.rb
│   │   │   │   │   ├── multiple_response.rb
│   │   │   │   │   ├── multiple_response_option.rb
│   │   │   │   │   ├── programming.rb
│   │   │   │   │   ├── programming_template_file.rb
│   │   │   │   │   ├── programming_test_case.rb
│   │   │   │   │   ├── question_rubric.rb
│   │   │   │   │   ├── rubric_based_response.rb
│   │   │   │   │   ├── rubric_based_response_category.rb
│   │   │   │   │   ├── rubric_based_response_criterion.rb
│   │   │   │   │   ├── scribing.rb
│   │   │   │   │   ├── text_response.rb
│   │   │   │   │   ├── text_response_comprehension_group.rb
│   │   │   │   │   ├── text_response_comprehension_point.rb
│   │   │   │   │   ├── text_response_comprehension_solution.rb
│   │   │   │   │   ├── text_response_solution.rb
│   │   │   │   │   └── voice_response.rb
│   │   │   │   ├── question.rb
│   │   │   │   ├── question_bundle.rb
│   │   │   │   ├── question_bundle_assignment.rb
│   │   │   │   ├── question_bundle_question.rb
│   │   │   │   ├── question_group.rb
│   │   │   │   ├── skill.rb
│   │   │   │   ├── skill_ability.rb
│   │   │   │   ├── skill_branch.rb
│   │   │   │   ├── submission/
│   │   │   │   │   └── log.rb
│   │   │   │   ├── submission.rb
│   │   │   │   ├── submission_question.rb
│   │   │   │   └── tab.rb
│   │   │   ├── assessment.rb
│   │   │   ├── condition/
│   │   │   │   ├── achievement.rb
│   │   │   │   ├── assessment.rb
│   │   │   │   ├── level.rb
│   │   │   │   ├── scholaistic_assessment.rb
│   │   │   │   ├── survey.rb
│   │   │   │   └── video.rb
│   │   │   ├── condition.rb
│   │   │   ├── discussion/
│   │   │   │   ├── post/
│   │   │   │   │   ├── codaveri_feedback.rb
│   │   │   │   │   └── vote.rb
│   │   │   │   ├── post.rb
│   │   │   │   ├── topic/
│   │   │   │   │   └── subscription.rb
│   │   │   │   └── topic.rb
│   │   │   ├── discussion.rb
│   │   │   ├── enrol_request.rb
│   │   │   ├── experience_points/
│   │   │   │   ├── disbursement.rb
│   │   │   │   └── forum_disbursement.rb
│   │   │   ├── experience_points_record.rb
│   │   │   ├── forum/
│   │   │   │   ├── discussion.rb
│   │   │   │   ├── discussion_reference.rb
│   │   │   │   ├── import.rb
│   │   │   │   ├── rag_auto_answering.rb
│   │   │   │   ├── search.rb
│   │   │   │   ├── subscription.rb
│   │   │   │   ├── topic/
│   │   │   │   │   └── view.rb
│   │   │   │   └── topic.rb
│   │   │   ├── forum.rb
│   │   │   ├── group.rb
│   │   │   ├── group_category.rb
│   │   │   ├── group_user.rb
│   │   │   ├── learning_map.rb
│   │   │   ├── learning_rate_record.rb
│   │   │   ├── lesson_plan/
│   │   │   │   ├── event.rb
│   │   │   │   ├── event_material.rb
│   │   │   │   ├── item.rb
│   │   │   │   ├── milestone.rb
│   │   │   │   └── todo.rb
│   │   │   ├── lesson_plan.rb
│   │   │   ├── level.rb
│   │   │   ├── material/
│   │   │   │   ├── folder.rb
│   │   │   │   ├── text_chunk.rb
│   │   │   │   ├── text_chunk_reference.rb
│   │   │   │   └── text_chunking.rb
│   │   │   ├── material.rb
│   │   │   ├── monitoring/
│   │   │   │   ├── browser_authorization/
│   │   │   │   │   ├── base.rb
│   │   │   │   │   ├── seb_config_key.rb
│   │   │   │   │   └── user_agent.rb
│   │   │   │   ├── heartbeat.rb
│   │   │   │   ├── monitor.rb
│   │   │   │   └── session.rb
│   │   │   ├── monitoring.rb
│   │   │   ├── notification.rb
│   │   │   ├── personal_time.rb
│   │   │   ├── question_assessment.rb
│   │   │   ├── reference_time.rb
│   │   │   ├── reference_timeline.rb
│   │   │   ├── registration.rb
│   │   │   ├── rubric/
│   │   │   │   ├── answer_evaluation/
│   │   │   │   │   └── selection.rb
│   │   │   │   ├── answer_evaluation.rb
│   │   │   │   ├── category/
│   │   │   │   │   └── criterion.rb
│   │   │   │   ├── category.rb
│   │   │   │   ├── mock_answer_evaluation/
│   │   │   │   │   └── selection.rb
│   │   │   │   ├── mock_answer_evaluation.rb
│   │   │   │   └── rubric_adapter.rb
│   │   │   ├── rubric.rb
│   │   │   ├── scholaistic_assessment.rb
│   │   │   ├── scholaistic_submission.rb
│   │   │   ├── settings/
│   │   │   │   ├── announcements_component.rb
│   │   │   │   ├── assessments_component.rb
│   │   │   │   ├── codaveri_component.rb
│   │   │   │   ├── component.rb
│   │   │   │   ├── components.rb
│   │   │   │   ├── email.rb
│   │   │   │   ├── forums_component.rb
│   │   │   │   ├── leaderboard_component.rb
│   │   │   │   ├── learning_map_component.rb
│   │   │   │   ├── lesson_plan_component.rb
│   │   │   │   ├── lesson_plan_items.rb
│   │   │   │   ├── materials_component.rb
│   │   │   │   ├── pan_component.rb
│   │   │   │   ├── rag_wise_component.rb
│   │   │   │   ├── scholaistic_component.rb
│   │   │   │   ├── sidebar.rb
│   │   │   │   ├── sidebar_item.rb
│   │   │   │   ├── stories_component.rb
│   │   │   │   ├── survey_component.rb
│   │   │   │   ├── topics_component.rb
│   │   │   │   ├── users_component.rb
│   │   │   │   └── videos_component.rb
│   │   │   ├── settings.rb
│   │   │   ├── story.rb
│   │   │   ├── survey/
│   │   │   │   ├── answer.rb
│   │   │   │   ├── answer_option.rb
│   │   │   │   ├── question.rb
│   │   │   │   ├── question_option.rb
│   │   │   │   ├── response.rb
│   │   │   │   └── section.rb
│   │   │   ├── survey.rb
│   │   │   ├── user_achievement.rb
│   │   │   ├── user_email_unsubscription.rb
│   │   │   ├── user_invitation.rb
│   │   │   ├── video/
│   │   │   │   ├── event.rb
│   │   │   │   ├── session.rb
│   │   │   │   ├── statistic.rb
│   │   │   │   ├── submission/
│   │   │   │   │   └── statistic.rb
│   │   │   │   ├── submission.rb
│   │   │   │   ├── tab.rb
│   │   │   │   └── topic.rb
│   │   │   └── video.rb
│   │   ├── course.rb
│   │   ├── course_user.rb
│   │   ├── duplication_traceable/
│   │   │   ├── assessment.rb
│   │   │   └── course.rb
│   │   ├── duplication_traceable.rb
│   │   ├── generic_announcement.rb
│   │   ├── instance/
│   │   │   ├── announcement.rb
│   │   │   ├── settings/
│   │   │   │   └── components.rb
│   │   │   ├── settings.rb
│   │   │   ├── user_invitation.rb
│   │   │   └── user_role_request.rb
│   │   ├── instance.rb
│   │   ├── instance_user.rb
│   │   ├── settings.rb
│   │   ├── system/
│   │   │   └── announcement.rb
│   │   ├── user/
│   │   │   ├── email.rb
│   │   │   └── identity.rb
│   │   ├── user.rb
│   │   └── user_notification.rb
│   ├── notifiers/
│   │   ├── course/
│   │   │   ├── achievement_notifier.rb
│   │   │   ├── announcement_notifier.rb
│   │   │   ├── assessment/
│   │   │   │   ├── answer/
│   │   │   │   │   └── comment_notifier.rb
│   │   │   │   └── submission_question/
│   │   │   │       └── comment_notifier.rb
│   │   │   ├── assessment_notifier.rb
│   │   │   ├── consolidated_opening_reminder_notifier.rb
│   │   │   ├── forum/
│   │   │   │   ├── post_notifier.rb
│   │   │   │   └── topic_notifier.rb
│   │   │   ├── level_notifier.rb
│   │   │   └── video_notifier.rb
│   │   └── notifier/
│   │       └── base.rb
│   ├── services/
│   │   ├── authentication/
│   │   │   ├── authentication_service.rb
│   │   │   ├── jwt_verification_service.rb
│   │   │   ├── keycloak_verification_service.rb
│   │   │   └── verification_service.rb
│   │   ├── cikgo/
│   │   │   ├── chats_service.rb
│   │   │   ├── resources_service.rb
│   │   │   ├── service.rb
│   │   │   ├── timelines_service.rb
│   │   │   └── users_service.rb
│   │   ├── codaveri_async_api_service.rb
│   │   ├── concerns/
│   │   │   ├── cikgo/
│   │   │   │   └── course_concern.rb
│   │   │   ├── course/
│   │   │   │   └── user_invitation_service/
│   │   │   │       ├── email_invitation_concern.rb
│   │   │   │       ├── parse_invitation_concern.rb
│   │   │   │       └── process_invitation_concern.rb
│   │   │   └── instance/
│   │   │       └── user_invitation_service/
│   │   │           ├── email_invitation_concern.rb
│   │   │           ├── parse_invitation_concern.rb
│   │   │           └── process_invitation_concern.rb
│   │   ├── course/
│   │   │   ├── announcement/
│   │   │   │   └── reminder_service.rb
│   │   │   ├── assessment/
│   │   │   │   ├── achievement_preload_service.rb
│   │   │   │   ├── answer/
│   │   │   │   │   ├── ai_generated_post_service.rb
│   │   │   │   │   ├── auto_grading_service.rb
│   │   │   │   │   ├── live_feedback/
│   │   │   │   │   │   ├── feedback_service.rb
│   │   │   │   │   │   └── thread_service.rb
│   │   │   │   │   ├── multiple_response_auto_grading_service.rb
│   │   │   │   │   ├── programming_auto_grading_service.rb
│   │   │   │   │   ├── programming_codaveri_async_feedback_service.rb
│   │   │   │   │   ├── programming_codaveri_auto_grading_service.rb
│   │   │   │   │   ├── prompts/
│   │   │   │   │   │   ├── rubric_auto_grading_output_format.json
│   │   │   │   │   │   ├── rubric_auto_grading_system_prompt.json
│   │   │   │   │   │   └── rubric_auto_grading_user_prompt.json
│   │   │   │   │   ├── rubric_auto_grading_service.rb
│   │   │   │   │   ├── rubric_based_response/
│   │   │   │   │   │   └── answer_adapter.rb
│   │   │   │   │   ├── text_response_auto_grading_service.rb
│   │   │   │   │   └── text_response_comprehension_auto_grading_service.rb
│   │   │   │   ├── authentication_service.rb
│   │   │   │   ├── koditsu_assessment_invitation_service.rb
│   │   │   │   ├── koditsu_assessment_service.rb
│   │   │   │   ├── monitoring_service.rb
│   │   │   │   ├── programming_codaveri_evaluation_service.rb
│   │   │   │   ├── programming_evaluation_service.rb
│   │   │   │   ├── question/
│   │   │   │   │   ├── answers_evaluation_service.rb
│   │   │   │   │   ├── codaveri_problem_generation_service.rb
│   │   │   │   │   ├── koditsu_question_service.rb
│   │   │   │   │   ├── mrq_generation_service.rb
│   │   │   │   │   ├── programming/
│   │   │   │   │   │   ├── c_sharp/
│   │   │   │   │   │   │   ├── c_sharp_makefile
│   │   │   │   │   │   │   └── c_sharp_package_service.rb
│   │   │   │   │   │   ├── cpp/
│   │   │   │   │   │   │   ├── cpp_autograde_include.cc
│   │   │   │   │   │   │   ├── cpp_autograde_post.cc
│   │   │   │   │   │   │   ├── cpp_autograde_pre.cc
│   │   │   │   │   │   │   ├── cpp_makefile
│   │   │   │   │   │   │   └── cpp_package_service.rb
│   │   │   │   │   │   ├── go/
│   │   │   │   │   │   │   ├── go_makefile
│   │   │   │   │   │   │   └── go_package_service.rb
│   │   │   │   │   │   ├── java/
│   │   │   │   │   │   │   ├── RunTests.java
│   │   │   │   │   │   │   ├── java_autograde_pre.java
│   │   │   │   │   │   │   ├── java_build.xml
│   │   │   │   │   │   │   ├── java_package_service.rb
│   │   │   │   │   │   │   ├── java_simple_makefile
│   │   │   │   │   │   │   └── java_standard_makefile
│   │   │   │   │   │   ├── java_script/
│   │   │   │   │   │   │   ├── java_script_makefile
│   │   │   │   │   │   │   └── java_script_package_service.rb
│   │   │   │   │   │   ├── language_package_service.rb
│   │   │   │   │   │   ├── programming_package_service.rb
│   │   │   │   │   │   ├── python/
│   │   │   │   │   │   │   ├── python_autograde_post.py
│   │   │   │   │   │   │   ├── python_autograde_pre.py
│   │   │   │   │   │   │   ├── python_makefile
│   │   │   │   │   │   │   └── python_package_service.rb
│   │   │   │   │   │   ├── r/
│   │   │   │   │   │   │   ├── r_makefile
│   │   │   │   │   │   │   └── r_package_service.rb
│   │   │   │   │   │   ├── rust/
│   │   │   │   │   │   │   ├── rust_makefile
│   │   │   │   │   │   │   └── rust_package_service.rb
│   │   │   │   │   │   └── type_script/
│   │   │   │   │   │       ├── type_script_makefile
│   │   │   │   │   │       └── type_script_package_service.rb
│   │   │   │   │   ├── programming_codaveri/
│   │   │   │   │   │   ├── c_sharp/
│   │   │   │   │   │   │   └── c_sharp_package_service.rb
│   │   │   │   │   │   ├── go/
│   │   │   │   │   │   │   └── go_package_service.rb
│   │   │   │   │   │   ├── java/
│   │   │   │   │   │   │   └── java_package_service.rb
│   │   │   │   │   │   ├── java_script/
│   │   │   │   │   │   │   └── java_script_package_service.rb
│   │   │   │   │   │   ├── language_package_service.rb
│   │   │   │   │   │   ├── programming_codaveri_package_service.rb
│   │   │   │   │   │   ├── python/
│   │   │   │   │   │   │   └── python_package_service.rb
│   │   │   │   │   │   ├── r/
│   │   │   │   │   │   │   └── r_package_service.rb
│   │   │   │   │   │   ├── rust/
│   │   │   │   │   │   │   └── rust_package_service.rb
│   │   │   │   │   │   └── type_script/
│   │   │   │   │   │       └── type_script_package_service.rb
│   │   │   │   │   ├── programming_codaveri_service.rb
│   │   │   │   │   ├── programming_import_service.rb
│   │   │   │   │   ├── prompts/
│   │   │   │   │   │   ├── mcq_generation_system_prompt.json
│   │   │   │   │   │   ├── mcq_generation_user_prompt.json
│   │   │   │   │   │   ├── mcq_mrq_generation_output_format.json
│   │   │   │   │   │   ├── mrq_generation_system_prompt.json
│   │   │   │   │   │   └── mrq_generation_user_prompt.json
│   │   │   │   │   ├── question_adapter.rb
│   │   │   │   │   ├── rubric_based_response/
│   │   │   │   │   │   └── rubric_adapter.rb
│   │   │   │   │   ├── scribing_import_service.rb
│   │   │   │   │   └── text_response_lemma_service.rb
│   │   │   │   ├── reminder_service.rb
│   │   │   │   ├── session_authentication_service.rb
│   │   │   │   ├── session_log_service.rb
│   │   │   │   └── submission/
│   │   │   │       ├── auto_grading_service.rb
│   │   │   │       ├── base_zip_download_service.rb
│   │   │   │       ├── calculate_exp_service.rb
│   │   │   │       ├── csv_download_service.rb
│   │   │   │       ├── koditsu_submission_service.rb
│   │   │   │       ├── monitoring_service.rb
│   │   │   │       ├── ssid_plagiarism_service.rb
│   │   │   │       ├── ssid_zip_download_service.rb
│   │   │   │       ├── statistics_download_service.rb
│   │   │   │       ├── update_service.rb
│   │   │   │       └── zip_download_service.rb
│   │   │   ├── conditional/
│   │   │   │   ├── conditional_satisfiability_evaluation_service.rb
│   │   │   │   └── satisfiability_graph_build_service.rb
│   │   │   ├── course_owner_preload_service.rb
│   │   │   ├── course_user_preload_service.rb
│   │   │   ├── discussion/
│   │   │   │   └── post/
│   │   │   │       └── codaveri_feedback_rating_service.rb
│   │   │   ├── duplication/
│   │   │   │   ├── base_service.rb
│   │   │   │   ├── course_duplication_service.rb
│   │   │   │   └── object_duplication_service.rb
│   │   │   ├── experience_points_download_service.rb
│   │   │   ├── group_manager_preload_service.rb
│   │   │   ├── koditsu_workspace_service.rb
│   │   │   ├── material/
│   │   │   │   ├── preload_service.rb
│   │   │   │   └── zip_download_service.rb
│   │   │   ├── reference_time/
│   │   │   │   └── time_offset_service.rb
│   │   │   ├── rubric/
│   │   │   │   ├── llm_service/
│   │   │   │   │   ├── answer_adapter.rb
│   │   │   │   │   ├── question_adapter.rb
│   │   │   │   │   └── rubric_adapter.rb
│   │   │   │   └── llm_service.rb
│   │   │   ├── skills_mastery_preload_service.rb
│   │   │   ├── ssid_folder_service.rb
│   │   │   ├── statistics/
│   │   │   │   └── assessments_score_summary_download_service.rb
│   │   │   ├── survey/
│   │   │   │   ├── reminder_service.rb
│   │   │   │   └── survey_download_service.rb
│   │   │   ├── user_invitation_service.rb
│   │   │   ├── user_registration_service.rb
│   │   │   └── video/
│   │   │       └── reminder_service.rb
│   │   ├── instance/
│   │   │   └── user_invitation_service.rb
│   │   ├── koditsu_async_api_service.rb
│   │   ├── rag_wise/
│   │   │   ├── chunking_service.rb
│   │   │   ├── discussion_extraction_service.rb
│   │   │   ├── llm_service.rb
│   │   │   ├── prompts/
│   │   │   │   ├── forum_assistant_system_prompt.json
│   │   │   │   └── guess_course_material_name_system_prompt_template.json
│   │   │   ├── rag_workflow_service.rb
│   │   │   ├── response_evaluation_service.rb
│   │   │   └── tools/
│   │   │       ├── course_forum_discussions_tool.rb
│   │   │       └── course_materials_tool.rb
│   │   ├── scholaistic_api_service.rb
│   │   ├── sidekiq_api_service.rb
│   │   ├── ssid_async_api_service.rb
│   │   └── user/
│   │       └── instance_preload_service.rb
│   ├── uploaders/
│   │   ├── file_uploader.rb
│   │   └── image_uploader.rb
│   └── views/
│       ├── announcements/
│       │   ├── _announcement_data.json.jbuilder
│       │   ├── _announcement_list_data.json.jbuilder
│       │   └── index.json.jbuilder
│       ├── application/
│       │   └── index.json.jbuilder
│       ├── attachment_references/
│       │   └── create.json.jbuilder
│       ├── attachments/
│       │   └── _attachment_reference.json.jbuilder
│       ├── course/
│       │   ├── achievement/
│       │   │   └── achievements/
│       │   │       ├── _achievement.json.jbuilder
│       │   │       ├── _achievement_conditional.json.jbuilder
│       │   │       ├── _achievement_data.json.jbuilder
│       │   │       ├── _achievement_list_data.json.jbuilder
│       │   │       ├── index.json.jbuilder
│       │   │       └── show.json.jbuilder
│       │   ├── admin/
│       │   │   ├── admin/
│       │   │   │   ├── index.json.jbuilder
│       │   │   │   └── time_zones.json.jbuilder
│       │   │   ├── announcement_settings/
│       │   │   │   └── edit.json.jbuilder
│       │   │   ├── assessment_settings/
│       │   │   │   └── edit.json.jbuilder
│       │   │   ├── codaveri_settings/
│       │   │   │   ├── assessment.json.jbuilder
│       │   │   │   └── edit.json.jbuilder
│       │   │   ├── component_settings/
│       │   │   │   └── edit.json.jbuilder
│       │   │   ├── discussion/
│       │   │   │   └── topic_settings/
│       │   │   │       └── edit.json.jbuilder
│       │   │   ├── forum_settings/
│       │   │   │   └── edit.json.jbuilder
│       │   │   ├── leaderboard_settings/
│       │   │   │   └── edit.json.jbuilder
│       │   │   ├── lesson_plan_settings/
│       │   │   │   └── edit.json.jbuilder
│       │   │   ├── material_settings/
│       │   │   │   └── edit.json.jbuilder
│       │   │   ├── notification_settings/
│       │   │   │   └── edit.json.jbuilder
│       │   │   ├── rag_wise_settings/
│       │   │   │   ├── courses.json.jbuilder
│       │   │   │   ├── edit.json.jbuilder
│       │   │   │   ├── folders.json.jbuilder
│       │   │   │   ├── forums.json.jbuilder
│       │   │   │   └── materials.json.jbuilder
│       │   │   ├── scholaistic_settings/
│       │   │   │   └── edit.json.jbuilder
│       │   │   ├── sidebar_settings/
│       │   │   │   ├── edit.json.jbuilder
│       │   │   │   └── show.json.jbuilder
│       │   │   ├── stories_settings/
│       │   │   │   └── edit.json.jbuilder
│       │   │   └── video_settings/
│       │   │       └── edit.json.jbuilder
│       │   ├── announcements/
│       │   │   └── index.json.jbuilder
│       │   ├── assessment/
│       │   │   ├── answer/
│       │   │   │   ├── forum_post_responses/
│       │   │   │   │   └── _forum_post_response.json.jbuilder
│       │   │   │   ├── multiple_responses/
│       │   │   │   │   └── _multiple_response.json.jbuilder
│       │   │   │   ├── programming/
│       │   │   │   │   ├── _annotations.json.jbuilder
│       │   │   │   │   └── _programming.json.jbuilder
│       │   │   │   ├── rubric_based_responses/
│       │   │   │   │   └── _rubric_based_response.json.jbuilder
│       │   │   │   ├── scribing/
│       │   │   │   │   └── _scribing.json.jbuilder
│       │   │   │   ├── text_responses/
│       │   │   │   │   └── _text_response.json.jbuilder
│       │   │   │   └── voice_responses/
│       │   │   │       └── _voice_response.json.jbuilder
│       │   │   ├── answers/
│       │   │   │   └── _answer.json.jbuilder
│       │   │   ├── assessments/
│       │   │   │   ├── _achievement_badges.json.jbuilder
│       │   │   │   ├── _assessment_actions.json.jbuilder
│       │   │   │   ├── _assessment_conditional.json.jbuilder
│       │   │   │   ├── _assessment_lesson_plan_item.json.jbuilder
│       │   │   │   ├── _assessment_list_data.json.jbuilder
│       │   │   │   ├── _assessment_question_bundle_buttons.html.slim
│       │   │   │   ├── _monitoring_details.json.jbuilder
│       │   │   │   ├── authenticate.json.jbuilder
│       │   │   │   ├── blocked_by_monitor.json.jbuilder
│       │   │   │   ├── edit.json.jbuilder
│       │   │   │   ├── index.json.jbuilder
│       │   │   │   ├── monitoring.json.jbuilder
│       │   │   │   └── show.json.jbuilder
│       │   │   ├── categories/
│       │   │   │   ├── _category.json.jbuilder
│       │   │   │   └── index.json.jbuilder
│       │   │   ├── mock_answers/
│       │   │   │   └── index.json.jbuilder
│       │   │   ├── programming_evaluations/
│       │   │   │   ├── _programming_evaluation.json.jbuilder
│       │   │   │   ├── allocate.json.jbuilder
│       │   │   │   ├── show.json.jbuilder
│       │   │   │   └── update_result.json.jbuilder
│       │   │   ├── question/
│       │   │   │   ├── _form.json.jbuilder
│       │   │   │   ├── _skills.json.jbuilder
│       │   │   │   ├── forum_post_responses/
│       │   │   │   │   ├── _form.json.jbuilder
│       │   │   │   │   ├── _forum_post_response.json.jbuilder
│       │   │   │   │   ├── edit.json.jbuilder
│       │   │   │   │   └── new.json.jbuilder
│       │   │   │   ├── multiple_responses/
│       │   │   │   │   ├── _form.json.jbuilder
│       │   │   │   │   ├── _multiple_response.json.jbuilder
│       │   │   │   │   ├── _multiple_response_details.json.jbuilder
│       │   │   │   │   ├── _switch_question_type_button.json.jbuilder
│       │   │   │   │   ├── edit.json.jbuilder
│       │   │   │   │   └── new.json.jbuilder
│       │   │   │   ├── programming/
│       │   │   │   │   ├── _form.json.jbuilder
│       │   │   │   │   ├── _import_result.json.jbuilder
│       │   │   │   │   ├── _languages.json.jbuilder
│       │   │   │   │   ├── _package_ui.json.jbuilder
│       │   │   │   │   ├── _programming.json.jbuilder
│       │   │   │   │   ├── _question.json.jbuilder
│       │   │   │   │   ├── _response.json.jbuilder
│       │   │   │   │   ├── _test_cases.json.jbuilder
│       │   │   │   │   ├── _test_ui.json.jbuilder
│       │   │   │   │   ├── edit.json.jbuilder
│       │   │   │   │   ├── import_result.json.jbuilder
│       │   │   │   │   ├── metadata/
│       │   │   │   │   │   ├── _c_cpp.json.jbuilder
│       │   │   │   │   │   ├── _csharp.json.jbuilder
│       │   │   │   │   │   ├── _default.json.jbuilder
│       │   │   │   │   │   ├── _golang.json.jbuilder
│       │   │   │   │   │   ├── _java.json.jbuilder
│       │   │   │   │   │   ├── _javascript.json.jbuilder
│       │   │   │   │   │   ├── _python.json.jbuilder
│       │   │   │   │   │   ├── _r.json.jbuilder
│       │   │   │   │   │   ├── _rust.json.jbuilder
│       │   │   │   │   │   ├── _typescript.json.jbuilder
│       │   │   │   │   │   └── partials/
│       │   │   │   │   │       ├── _file.json.jbuilder
│       │   │   │   │   │       └── _test_cases.json.jbuilder
│       │   │   │   │   └── new.json.jbuilder
│       │   │   │   ├── rubric_based_responses/
│       │   │   │   │   ├── _category_details.json.jbuilder
│       │   │   │   │   ├── _form.json.jbuilder
│       │   │   │   │   ├── _grade_details.json.jbuilder
│       │   │   │   │   ├── _rubric_based_response.json.jbuilder
│       │   │   │   │   ├── edit.json.jbuilder
│       │   │   │   │   └── new.json.jbuilder
│       │   │   │   ├── scribing/
│       │   │   │   │   ├── _scribing.json.jbuilder
│       │   │   │   │   └── _scribing_question.json.jbuilder
│       │   │   │   ├── text_responses/
│       │   │   │   │   ├── _form.json.jbuilder
│       │   │   │   │   ├── _solution_details.json.jbuilder
│       │   │   │   │   ├── _text_response.json.jbuilder
│       │   │   │   │   ├── edit.json.jbuilder
│       │   │   │   │   └── new.json.jbuilder
│       │   │   │   └── voice_responses/
│       │   │   │       ├── _form.json.jbuilder
│       │   │   │       ├── _voice_response.json.jbuilder
│       │   │   │       ├── edit.json.jbuilder
│       │   │   │       └── new.json.jbuilder
│       │   │   ├── question_bundle_assignments/
│       │   │   │   ├── _form.html.slim
│       │   │   │   ├── _validation_result.html.slim
│       │   │   │   ├── edit.html.slim
│       │   │   │   └── index.html.slim
│       │   │   ├── question_bundle_questions/
│       │   │   │   ├── _form.html.slim
│       │   │   │   ├── edit.html.slim
│       │   │   │   ├── index.html.slim
│       │   │   │   └── new.html.slim
│       │   │   ├── question_bundles/
│       │   │   │   ├── _form.html.slim
│       │   │   │   ├── edit.html.slim
│       │   │   │   ├── index.html.slim
│       │   │   │   └── new.html.slim
│       │   │   ├── question_groups/
│       │   │   │   ├── _form.html.slim
│       │   │   │   ├── edit.html.slim
│       │   │   │   ├── index.html.slim
│       │   │   │   └── new.html.slim
│       │   │   ├── questions/
│       │   │   │   └── show.json.jbuilder
│       │   │   ├── rubrics/
│       │   │   │   ├── fetch_answer_evaluations.json.jbuilder
│       │   │   │   ├── fetch_mock_answer_evaluations.json.jbuilder
│       │   │   │   ├── index.json.jbuilder
│       │   │   │   └── rubric_answers.json.jbuilder
│       │   │   ├── skill_branches/
│       │   │   │   ├── _skill_branch_list_data.json.jbuilder
│       │   │   │   └── _skill_branch_user_list_data.json.jbuilder
│       │   │   ├── skills/
│       │   │   │   ├── _options.json.jbuilder
│       │   │   │   ├── _skill_list_data.json.jbuilder
│       │   │   │   ├── _skill_user_list_data.json.jbuilder
│       │   │   │   └── index.json.jbuilder
│       │   │   ├── submission/
│       │   │   │   ├── answer/
│       │   │   │   │   ├── answers/
│       │   │   │   │   │   └── show.json.jbuilder
│       │   │   │   │   └── forum_post_response/
│       │   │   │   │       └── posts/
│       │   │   │   │           ├── _post_packs.json.jbuilder
│       │   │   │   │           └── selected.json.jbuilder
│       │   │   │   ├── logs/
│       │   │   │   │   ├── _info.json.jbuilder
│       │   │   │   │   ├── _logs.json.jbuilder
│       │   │   │   │   └── index.json.jbuilder
│       │   │   │   └── submissions/
│       │   │   │       ├── _answers.json.jbuilder
│       │   │   │       ├── _history.json.jbuilder
│       │   │   │       ├── _question.json.jbuilder
│       │   │   │       ├── _questions.json.jbuilder
│       │   │   │       ├── _submission.json.jbuilder
│       │   │   │       ├── _topics.json.jbuilder
│       │   │   │       ├── create_live_feedback_chat.json.jbuilder
│       │   │   │       ├── edit.json.jbuilder
│       │   │   │       ├── fetch_live_feedback_chat.json.jbuilder
│       │   │   │       ├── fetch_live_feedback_status.json.jbuilder
│       │   │   │       └── index.json.jbuilder
│       │   │   ├── submission_question/
│       │   │   │   └── submission_questions/
│       │   │   │       └── all_answers.json.jbuilder
│       │   │   └── submissions/
│       │   │       ├── _filter.json.jbuilder
│       │   │       ├── _submissions_list_data.json.jbuilder
│       │   │       ├── _tabs.json.jbuilder
│       │   │       ├── index.json.jbuilder
│       │   │       └── pending.json.jbuilder
│       │   ├── condition/
│       │   │   ├── _condition_data.json.jbuilder
│       │   │   ├── _condition_list_data.json.jbuilder
│       │   │   ├── _conditions.json.jbuilder
│       │   │   ├── _enabled_conditions.json.jbuilder
│       │   │   ├── achievements/
│       │   │   │   └── _achievement.json.jbuilder
│       │   │   ├── assessments/
│       │   │   │   ├── _assessment.json.jbuilder
│       │   │   │   ├── _assessment_condition.json.jbuilder
│       │   │   │   └── available_assessments.json.jbuilder
│       │   │   ├── levels/
│       │   │   │   └── _level.json.jbuilder
│       │   │   ├── scholaistic_assessments/
│       │   │   │   ├── _scholaistic_assessment.json.jbuilder
│       │   │   │   └── available_scholaistic_assessments.json.jbuilder
│       │   │   └── surveys/
│       │   │       ├── _survey.json.jbuilder
│       │   │       └── available_surveys.json.jbuilder
│       │   ├── courses/
│       │   │   ├── _course_data.json.jbuilder
│       │   │   ├── _course_list_data.json.jbuilder
│       │   │   ├── _course_user_progress.json.jbuilder
│       │   │   ├── _sidebar_items.json.jbuilder
│       │   │   ├── index.json.jbuilder
│       │   │   ├── show.json.jbuilder
│       │   │   └── sidebar.json.jbuilder
│       │   ├── discussion/
│       │   │   ├── posts/
│       │   │   │   └── _post.json.jbuilder
│       │   │   └── topics/
│       │   │       ├── _discussion_topic_programming_file_annotation.jbuilder
│       │   │       ├── _discussion_topic_submission_question.json.jbuilder
│       │   │       ├── _discussion_topic_video.json.jbuilder
│       │   │       ├── _tabs.json.jbuilder
│       │   │       ├── _topic.json.jbuilder
│       │   │       ├── discussion_topic_list_data.jbuilder
│       │   │       └── index.json.jbuilder
│       │   ├── enrol_requests/
│       │   │   ├── _enrol_request_list_data.json.jbuilder
│       │   │   └── index.json.jbuilder
│       │   ├── experience_points/
│       │   │   ├── disbursement/
│       │   │   │   └── new.json.jbuilder
│       │   │   └── forum_disbursement/
│       │   │       └── new.json.jbuilder
│       │   ├── experience_points_records/
│       │   │   ├── _experience_points_record.json.jbuilder
│       │   │   ├── index.jbuilder
│       │   │   └── show.jbuilder
│       │   ├── forum/
│       │   │   ├── forums/
│       │   │   │   ├── _forum_list_data.json.jbuilder
│       │   │   │   ├── all_posts.json.jbuilder
│       │   │   │   ├── index.json.jbuilder
│       │   │   │   ├── search.json.jbuilder
│       │   │   │   └── show.json.jbuilder
│       │   │   ├── posts/
│       │   │   │   ├── _post_creator_data.json.jbuilder
│       │   │   │   ├── _post_list_data.json.jbuilder
│       │   │   │   ├── _post_publish_data.json.jbuilder
│       │   │   │   └── create.json.jbuilder
│       │   │   └── topics/
│       │   │       ├── _topic_list_data.json.jbuilder
│       │   │       └── show.json.jbuilder
│       │   ├── group/
│       │   │   ├── _group.json.jbuilder
│       │   │   ├── group_categories/
│       │   │   │   ├── create_groups.json.jbuilder
│       │   │   │   ├── index.json.jbuilder
│       │   │   │   ├── show_info.json.jbuilder
│       │   │   │   └── show_users.json.jbuilder
│       │   │   └── groups/
│       │   │       └── update.json.jbuilder
│       │   ├── leaderboards/
│       │   │   ├── _leaderboard_achievement_list_data.json.jbuilder
│       │   │   ├── _leaderboard_group_list_data.json.jbuilder
│       │   │   ├── _leaderboard_list_data.json.jbuilder
│       │   │   └── index.json.jbuilder
│       │   ├── learning_map/
│       │   │   └── index.json.jbuilder
│       │   ├── lesson_plan/
│       │   │   ├── events/
│       │   │   │   └── _event_lesson_plan_item.json.jbuilder
│       │   │   ├── items/
│       │   │   │   ├── _item.json.jbuilder
│       │   │   │   ├── _personal_or_ref_time.json.jbuilder
│       │   │   │   └── index.json.jbuilder
│       │   │   ├── milestones/
│       │   │   │   └── _milestone.json.jbuilder
│       │   │   └── todos/
│       │   │       └── _todo.json.jbuilder
│       │   ├── levels/
│       │   │   └── index.json.jbuilder
│       │   ├── mailer/
│       │   │   ├── assessment_closing_reminder_email.html.slim
│       │   │   ├── assessment_closing_reminder_email.text.erb
│       │   │   ├── assessment_closing_summary_email.html.slim
│       │   │   ├── assessment_closing_summary_email.text.erb
│       │   │   ├── course_duplicate_failed_email.html.slim
│       │   │   ├── course_duplicate_failed_email.text.erb
│       │   │   ├── course_duplicated_email.html.slim
│       │   │   ├── course_duplicated_email.text.erb
│       │   │   ├── course_user_deletion_failed_email.html.slim
│       │   │   ├── course_user_deletion_failed_email.text.erb
│       │   │   ├── submission_graded_email.html.slim
│       │   │   ├── submission_graded_email.text.erb
│       │   │   ├── survey_closing_reminder_email.html.slim
│       │   │   ├── survey_closing_reminder_email.text.erb
│       │   │   ├── survey_closing_summary_email.html.slim
│       │   │   ├── survey_closing_summary_email.text.erb
│       │   │   ├── user_added_email.html.slim
│       │   │   ├── user_added_email.text.erb
│       │   │   ├── user_enrol_request_received_email.html.slim
│       │   │   ├── user_enrol_request_received_email.text.erb
│       │   │   ├── user_enrol_requested_email.html.slim
│       │   │   ├── user_enrol_requested_email.text.erb
│       │   │   ├── user_invitation_email.html.slim
│       │   │   ├── user_invitation_email.text.erb
│       │   │   ├── user_rejected_email.html.slim
│       │   │   ├── user_rejected_email.text.erb
│       │   │   ├── user_suspended_email.html.slim
│       │   │   ├── user_suspended_email.text.erb
│       │   │   ├── user_unsuspended_email.html.slim
│       │   │   ├── user_unsuspended_email.text.erb
│       │   │   ├── video_closing_reminder_email.html.slim
│       │   │   └── video_closing_reminder_email.text.erb
│       │   ├── material/
│       │   │   ├── _material.json.jbuilder
│       │   │   └── folders/
│       │   │       ├── breadcrumbs.json.jbuilder
│       │   │       ├── show.json.jbuilder
│       │   │       └── upload_materials.json.jbuilder
│       │   ├── object_duplications/
│       │   │   ├── _course_duplication_data.json.jbuilder
│       │   │   └── new.json.jbuilder
│       │   ├── personal_times/
│       │   │   ├── _personal_time_list_data.json.jbuilder
│       │   │   └── index.json.jbuilder
│       │   ├── plagiarism/
│       │   │   └── assessments/
│       │   │       ├── _plagiarism_check.json.jbuilder
│       │   │       ├── _plagiarism_checks.json.jbuilder
│       │   │       ├── index.json.jbuilder
│       │   │       ├── linked_and_unlinked_assessments.json.jbuilder
│       │   │       └── plagiarism_data.json.jbuilder
│       │   ├── question_assessments/
│       │   │   └── _question_assessment.json.jbuilder
│       │   ├── reference_timelines/
│       │   │   ├── _reference_timeline.json.jbuilder
│       │   │   └── index.json.jbuilder
│       │   ├── rubrics/
│       │   │   ├── _answer_evaluation.json.jbuilder
│       │   │   ├── _mock_answer_evaluation.json.jbuilder
│       │   │   ├── _rubric.json.jbuilder
│       │   │   └── index.json.jbuilder
│       │   ├── scholaistic/
│       │   │   ├── assistants/
│       │   │   │   ├── index.json.jbuilder
│       │   │   │   └── show.json.jbuilder
│       │   │   ├── scholaistic_assessments/
│       │   │   │   ├── edit.json.jbuilder
│       │   │   │   ├── index.json.jbuilder
│       │   │   │   ├── new.json.jbuilder
│       │   │   │   └── show.json.jbuilder
│       │   │   └── submissions/
│       │   │       ├── index.json.jbuilder
│       │   │       └── show.json.jbuilder
│       │   ├── statistics/
│       │   │   ├── aggregate/
│       │   │   │   ├── activity_get_help.json.jbuilder
│       │   │   │   ├── all_assessments.json.jbuilder
│       │   │   │   ├── all_staff.json.jbuilder
│       │   │   │   ├── all_students.json.jbuilder
│       │   │   │   ├── course_performance.json.jbuilder
│       │   │   │   └── course_progression.json.jbuilder
│       │   │   ├── assessments/
│       │   │   │   ├── _answer.json.jbuilder
│       │   │   │   ├── _assessment.json.jbuilder
│       │   │   │   ├── _attempt_status.json.jbuilder
│       │   │   │   ├── _course_user.json.jbuilder
│       │   │   │   ├── _live_feedback_history_details.json.jbuilder
│       │   │   │   ├── _submission.json.jbuilder
│       │   │   │   ├── ancestor_info.json.jbuilder
│       │   │   │   ├── ancestor_statistics.json.jbuilder
│       │   │   │   ├── assessment_statistics.json.jbuilder
│       │   │   │   ├── live_feedback_history.json.jbuilder
│       │   │   │   ├── live_feedback_statistics.json.jbuilder
│       │   │   │   └── submission_statistics.json.jbuilder
│       │   │   ├── statistics/
│       │   │   │   └── index.json.jbuilder
│       │   │   └── users/
│       │   │       └── learning_rate_records.json.jbuilder
│       │   ├── survey/
│       │   │   ├── questions/
│       │   │   │   ├── _option.json.jbuilder
│       │   │   │   └── _question.json.jbuilder
│       │   │   ├── responses/
│       │   │   │   ├── _response.json.jbuilder
│       │   │   │   ├── _see_other.json.jbuilder
│       │   │   │   └── index.json.jbuilder
│       │   │   ├── sections/
│       │   │   │   └── _section.json.jbuilder
│       │   │   └── surveys/
│       │   │       ├── _survey.json.jbuilder
│       │   │       ├── _survey_with_questions.json.jbuilder
│       │   │       ├── index.json.jbuilder
│       │   │       └── results.json.jbuilder
│       │   ├── surveys/
│       │   │   └── _survey_lesson_plan_item.json.jbuilder
│       │   ├── user_email_subscriptions/
│       │   │   └── _subscription_setting.json.jbuilder
│       │   ├── user_invitations/
│       │   │   ├── _course_user_invitation_list.json.jbuilder
│       │   │   ├── _course_user_invitation_list_data.json.jbuilder
│       │   │   ├── _invitation_result_data.json.jbuilder
│       │   │   ├── index.json.jbuilder
│       │   │   └── new.json.jbuilder
│       │   ├── user_registrations/
│       │   │   └── _registration.json.jbuilder
│       │   ├── users/
│       │   │   ├── _permissions_data.json.jbuilder
│       │   │   ├── _tabs_data.json.jbuilder
│       │   │   ├── _upgrade_to_staff_results.json.jbuilder
│       │   │   ├── _user.json.jbuilder
│       │   │   ├── _user_data.json.jbuilder
│       │   │   ├── _user_list_data.json.jbuilder
│       │   │   ├── index.json.jbuilder
│       │   │   ├── show.json.jbuilder
│       │   │   ├── staff.json.jbuilder
│       │   │   └── students.json.jbuilder
│       │   ├── video/
│       │   │   ├── sessions/
│       │   │   │   └── _session.json.jbuilder
│       │   │   ├── submission/
│       │   │   │   ├── sessions/
│       │   │   │   │   └── create.json.jbuilder
│       │   │   │   └── submissions/
│       │   │   │       ├── _watch_next_video_url.json.jbuilder
│       │   │   │       ├── edit.json.jbuilder
│       │   │   │       ├── index.json.jbuilder
│       │   │   │       └── show.json.jbuilder
│       │   │   ├── topics/
│       │   │   │   ├── _post.json.jbuilder
│       │   │   │   ├── _posts.json.jbuilder
│       │   │   │   ├── _topic.json.jbuilder
│       │   │   │   ├── _topics.json.jbuilder
│       │   │   │   ├── create.json.jbuilder
│       │   │   │   ├── index.json.jbuilder
│       │   │   │   └── show.json.jbuilder
│       │   │   └── videos/
│       │   │       ├── _video.json.jbuilder
│       │   │       ├── _video_data.json.jbuilder
│       │   │       ├── _video_lesson_plan_item.json.jbuilder
│       │   │       ├── _video_list_data.json.jbuilder
│       │   │       ├── _video_statistics.json.jbuilder
│       │   │       ├── index.json.jbuilder
│       │   │       └── show.json.jbuilder
│       │   └── video_submissions/
│       │       └── index.json.jbuilder
│       ├── instance/
│       │   └── mailer/
│       │       ├── user_added_email.html.slim
│       │       ├── user_added_email.text.erb
│       │       ├── user_invitation_email.html.slim
│       │       └── user_invitation_email.text.erb
│       ├── instance_user_role_request_mailer/
│       │   ├── new_role_request.html.slim
│       │   ├── new_role_request.text.erb
│       │   ├── role_request_approved.html.slim
│       │   ├── role_request_approved.text.erb
│       │   ├── role_request_rejected.html.slim
│       │   └── role_request_rejected.text.erb
│       ├── instance_user_role_requests/
│       │   ├── _instance_user_role_request_list_data.json.jbuilder
│       │   └── index.json.jbuilder
│       ├── jobs/
│       │   ├── _completed.json.jbuilder
│       │   ├── _errored.json.jbuilder
│       │   ├── _submitted.json.jbuilder
│       │   └── show.json.jbuilder
│       ├── layouts/
│       │   ├── _manage_email_subscription.html.slim
│       │   ├── _manage_email_subscription.text.erb
│       │   ├── _materials.json.jbuilder
│       │   ├── mailer.html.slim
│       │   ├── mailer.text.erb
│       │   ├── no_greeting_mailer.html.slim
│       │   └── no_greeting_mailer.text.erb
│       ├── notifiers/
│       │   └── course/
│       │       ├── achievement_notifier/
│       │       │   └── gained/
│       │       │       ├── course_notifications/
│       │       │       │   └── _feed.json.jbuilder
│       │       │       └── user_notifications/
│       │       │           └── popup.json.jbuilder
│       │       ├── announcement_notifier/
│       │       │   └── new/
│       │       │       └── course_notifications/
│       │       │           └── email.html.slim
│       │       ├── assessment/
│       │       │   ├── answer/
│       │       │   │   └── comment_notifier/
│       │       │   │       └── annotated/
│       │       │   │           └── user_notifications/
│       │       │   │               └── email.html.slim
│       │       │   └── submission_question/
│       │       │       └── comment_notifier/
│       │       │           └── replied/
│       │       │               └── user_notifications/
│       │       │                   └── email.html.slim
│       │       ├── assessment_notifier/
│       │       │   ├── attempted/
│       │       │   │   └── course_notifications/
│       │       │   │       └── _feed.json.jbuilder
│       │       │   ├── opening/
│       │       │   │   └── course_notifications/
│       │       │   │       └── email.html.slim
│       │       │   └── submitted/
│       │       │       └── user_notifications/
│       │       │           └── email.html.slim
│       │       ├── consolidated_opening_reminder_notifier/
│       │       │   └── opening_reminder/
│       │       │       └── course_notifications/
│       │       │           ├── course/
│       │       │           │   ├── _assessment.html.slim
│       │       │           │   ├── _survey.html.slim
│       │       │           │   └── _video.html.slim
│       │       │           └── email.html.slim
│       │       ├── forum/
│       │       │   ├── post_notifier/
│       │       │   │   ├── replied/
│       │       │   │   │   ├── course_notifications/
│       │       │   │   │   │   └── _feed.json.jbuilder
│       │       │   │   │   └── user_notifications/
│       │       │   │   │       └── email.html.slim
│       │       │   │   └── voted/
│       │       │   │       └── course_notifications/
│       │       │   │           └── _feed.json.jbuilder
│       │       │   └── topic_notifier/
│       │       │       └── created/
│       │       │           ├── course_notifications/
│       │       │           │   └── _feed.json.jbuilder
│       │       │           └── user_notifications/
│       │       │               └── email.html.slim
│       │       ├── level_notifier/
│       │       │   └── reached/
│       │       │       ├── course_notifications/
│       │       │       │   └── _feed.json.jbuilder
│       │       │       └── user_notifications/
│       │       │           └── popup.json.jbuilder
│       │       └── video_notifier/
│       │           ├── attempted/
│       │           │   └── course_notifications/
│       │           │       └── _feed.json.jbuilder
│       │           ├── closing/
│       │           │   └── user_notifications/
│       │           │       └── email.html.slim
│       │           └── opening/
│       │               └── course_notifications/
│       │                   └── email.html.slim
│       ├── system/
│       │   └── admin/
│       │       ├── announcements/
│       │       │   └── index.json.jbuilder
│       │       ├── courses/
│       │       │   ├── _course_list_data.json.jbuilder
│       │       │   └── index.json.jbuilder
│       │       ├── get_help/
│       │       │   └── index.json.jbuilder
│       │       ├── instance/
│       │       │   ├── admin/
│       │       │   │   └── index.json.jbuilder
│       │       │   ├── announcements/
│       │       │   │   └── index.json.jbuilder
│       │       │   ├── components/
│       │       │   │   └── index.json.jbuilder
│       │       │   ├── courses/
│       │       │   │   └── index.json.jbuilder
│       │       │   ├── get_help/
│       │       │   │   └── index.json.jbuilder
│       │       │   ├── user_invitations/
│       │       │   │   ├── _instance_user_invitation_list_data.json.jbuilder
│       │       │   │   ├── _invitation_result_data.json.jbuilder
│       │       │   │   └── index.json.jbuilder
│       │       │   └── users/
│       │       │       ├── _user_list_data.json.jbuilder
│       │       │       └── index.json.jbuilder
│       │       ├── instances/
│       │       │   ├── _instance_list_data.json.jbuilder
│       │       │   └── index.json.jbuilder
│       │       └── users/
│       │           ├── _user_list_data.json.jbuilder
│       │           └── index.json.jbuilder
│       ├── user/
│       │   ├── emails/
│       │   │   ├── _email_list_data.json.jbuilder
│       │   │   └── index.json.jbuilder
│       │   ├── profiles/
│       │   │   ├── edit.json.jbuilder
│       │   │   └── show.json.jbuilder
│       │   └── registrations/
│       │       └── create.json.jbuilder
│       └── users/
│           ├── _course_list_data.json.jbuilder
│           ├── _instance_list_data.json.jbuilder
│           └── show.json.jbuilder
├── authentication/
│   ├── Dockerfile
│   ├── README.md
│   ├── docker-compose.yml
│   ├── env
│   ├── import/
│   │   └── coursemology_realm.json
│   ├── script/
│   │   └── cm_db_federation.sql
│   └── theme/
│       └── coursemology-keycloakify-keycloak-theme-6.1.7.jar
├── bin/
│   ├── bundle
│   ├── rails
│   ├── rake
│   ├── setup
│   ├── spring
│   └── update
├── client/
│   ├── .babelrc
│   ├── .eslintignore
│   ├── .eslintrc.js
│   ├── .prettierignore
│   ├── .prettierrc.js
│   ├── .yarn-integrity
│   ├── CONTRIBUTING.md
│   ├── README.md
│   ├── app/
│   │   ├── App.tsx
│   │   ├── __test__/
│   │   │   ├── mocks/
│   │   │   │   ├── ResizeObserver.js
│   │   │   │   ├── axiosMock.js
│   │   │   │   ├── fileMock.js
│   │   │   │   ├── matchMedia.js
│   │   │   │   ├── requestAnimationFrame.js
│   │   │   │   └── svgMock.js
│   │   │   ├── setup.js
│   │   │   └── utils/
│   │   │       ├── __test__/
│   │   │       │   └── shallowUntil.test.js
│   │   │       └── shallowUntil.js
│   │   ├── api/
│   │   │   ├── Announcements.ts
│   │   │   ├── Attachments.ts
│   │   │   ├── Base.ts
│   │   │   ├── ErrorHandling.ts
│   │   │   ├── Home.ts
│   │   │   ├── Jobs.ts
│   │   │   ├── Users.ts
│   │   │   ├── course/
│   │   │   │   ├── Achievements.ts
│   │   │   │   ├── Admin/
│   │   │   │   │   ├── Announcements.ts
│   │   │   │   │   ├── Assessments.ts
│   │   │   │   │   ├── Base.ts
│   │   │   │   │   ├── Codaveri.ts
│   │   │   │   │   ├── Comments.ts
│   │   │   │   │   ├── Components.ts
│   │   │   │   │   ├── Course.ts
│   │   │   │   │   ├── Forums.ts
│   │   │   │   │   ├── Leaderboard.ts
│   │   │   │   │   ├── LessonPlan.ts
│   │   │   │   │   ├── Materials.ts
│   │   │   │   │   ├── Notifications.ts
│   │   │   │   │   ├── RagWise.ts
│   │   │   │   │   ├── Scholaistic.ts
│   │   │   │   │   ├── Sidebar.ts
│   │   │   │   │   ├── Stories.ts
│   │   │   │   │   ├── Videos.ts
│   │   │   │   │   └── index.ts
│   │   │   │   ├── Announcements.ts
│   │   │   │   ├── Assessment/
│   │   │   │   │   ├── AllAnswers.ts
│   │   │   │   │   ├── Assessments.js
│   │   │   │   │   ├── Base.js
│   │   │   │   │   ├── Categories.js
│   │   │   │   │   ├── Question/
│   │   │   │   │   │   ├── ForumPostResponse.ts
│   │   │   │   │   │   ├── McqMrq.ts
│   │   │   │   │   │   ├── MockAnswers.ts
│   │   │   │   │   │   ├── Programming.ts
│   │   │   │   │   │   ├── Questions.ts
│   │   │   │   │   │   ├── RubricBasedResponse.ts
│   │   │   │   │   │   ├── Rubrics.ts
│   │   │   │   │   │   ├── Scribing.js
│   │   │   │   │   │   ├── TextResponse.ts
│   │   │   │   │   │   ├── VoiceResponse.ts
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── Sessions.ts
│   │   │   │   │   ├── Skills.ts
│   │   │   │   │   ├── Submission/
│   │   │   │   │   │   ├── Answer/
│   │   │   │   │   │   │   ├── Answer.ts
│   │   │   │   │   │   │   ├── ForumPostResponse.js
│   │   │   │   │   │   │   ├── Programming.js
│   │   │   │   │   │   │   ├── Scribing.js
│   │   │   │   │   │   │   ├── TextResponse.ts
│   │   │   │   │   │   │   └── index.js
│   │   │   │   │   │   └── Logs/
│   │   │   │   │   │       └── Logs.ts
│   │   │   │   │   ├── SubmissionQuestions.js
│   │   │   │   │   ├── Submissions/
│   │   │   │   │   │   └── Submissions.ts
│   │   │   │   │   ├── Submissions.js
│   │   │   │   │   └── index.ts
│   │   │   │   ├── Base.js
│   │   │   │   ├── Comments.ts
│   │   │   │   ├── Conditions.ts
│   │   │   │   ├── Courses.ts
│   │   │   │   ├── Disbursement.ts
│   │   │   │   ├── Duplication.js
│   │   │   │   ├── EnrolRequests.ts
│   │   │   │   ├── ExperiencePointsRecord.ts
│   │   │   │   ├── Forum/
│   │   │   │   │   ├── Forums.ts
│   │   │   │   │   ├── Posts.ts
│   │   │   │   │   ├── Topics.ts
│   │   │   │   │   └── index.ts
│   │   │   │   ├── Groups.js
│   │   │   │   ├── Leaderboard.ts
│   │   │   │   ├── LearningMap.js
│   │   │   │   ├── LessonPlan.js
│   │   │   │   ├── Level.ts
│   │   │   │   ├── Material/
│   │   │   │   │   └── Folders.ts
│   │   │   │   ├── MaterialFolders.js
│   │   │   │   ├── Materials.ts
│   │   │   │   ├── PersonalTimes.ts
│   │   │   │   ├── Plagiarism.ts
│   │   │   │   ├── Posts.js
│   │   │   │   ├── ReferenceTimelines.ts
│   │   │   │   ├── Rubrics.ts
│   │   │   │   ├── Scholaistic.ts
│   │   │   │   ├── Statistics/
│   │   │   │   │   ├── AnswerStatistics.ts
│   │   │   │   │   ├── AssessmentStatistics.ts
│   │   │   │   │   ├── CourseStatistics.ts
│   │   │   │   │   ├── UserStatistics.ts
│   │   │   │   │   └── index.ts
│   │   │   │   ├── Stories.ts
│   │   │   │   ├── Survey/
│   │   │   │   │   ├── Base.js
│   │   │   │   │   ├── Questions.js
│   │   │   │   │   ├── Responses.js
│   │   │   │   │   ├── Sections.js
│   │   │   │   │   ├── Surveys.js
│   │   │   │   │   └── index.js
│   │   │   │   ├── UserEmailSubscriptions.js
│   │   │   │   ├── UserInvitations.ts
│   │   │   │   ├── UserNotifications.ts
│   │   │   │   ├── Users.ts
│   │   │   │   ├── Video/
│   │   │   │   │   ├── Base.js
│   │   │   │   │   ├── Sessions.js
│   │   │   │   │   ├── Submissions.ts
│   │   │   │   │   ├── Topics.js
│   │   │   │   │   ├── Videos.ts
│   │   │   │   │   └── index.js
│   │   │   │   ├── VideoSubmissions.ts
│   │   │   │   └── index.js
│   │   │   ├── index.ts
│   │   │   ├── system/
│   │   │   │   ├── Admin.ts
│   │   │   │   ├── Base.ts
│   │   │   │   ├── InstanceAdmin.ts
│   │   │   │   └── index.js
│   │   │   └── types.ts
│   │   ├── assets/
│   │   │   └── templates/
│   │   │       └── course-user-invitation-template.csv
│   │   ├── bundles/
│   │   │   ├── announcements/
│   │   │   │   ├── GlobalAnnouncementIndex.tsx
│   │   │   │   ├── operations.ts
│   │   │   │   ├── selectors.ts
│   │   │   │   ├── store.ts
│   │   │   │   └── types.ts
│   │   │   ├── authentication/
│   │   │   │   └── pages/
│   │   │   │       └── AuthenticationRedirection/
│   │   │   │           └── index.tsx
│   │   │   ├── common/
│   │   │   │   ├── DashboardPage.tsx
│   │   │   │   ├── ErrorPage.tsx
│   │   │   │   ├── LandingPage.tsx
│   │   │   │   ├── PrivacyPolicyPage/
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   └── privacy-policy.md
│   │   │   │   ├── TermsOfServicePage/
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   └── terms-of-service.md
│   │   │   │   ├── components/
│   │   │   │   │   └── NewCourseButton.tsx
│   │   │   │   └── store.ts
│   │   │   ├── course/
│   │   │   │   ├── achievement/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── buttons/
│   │   │   │   │   │   │   ├── AchievementManagementButtons.tsx
│   │   │   │   │   │   │   └── AwardButton.tsx
│   │   │   │   │   │   ├── forms/
│   │   │   │   │   │   │   └── AchievementForm.tsx
│   │   │   │   │   │   ├── misc/
│   │   │   │   │   │   │   └── AchievementReordering.tsx
│   │   │   │   │   │   └── tables/
│   │   │   │   │   │       └── AchievementTable.tsx
│   │   │   │   │   ├── handles.ts
│   │   │   │   │   ├── operations.ts
│   │   │   │   │   ├── pages/
│   │   │   │   │   │   ├── AchievementAward/
│   │   │   │   │   │   │   ├── AchievementAwardManager.tsx
│   │   │   │   │   │   │   ├── AchievementAwardSummary.tsx
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── AchievementEdit/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── AchievementNew/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── AchievementShow/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   └── AchievementsIndex/
│   │   │   │   │   │       └── index.tsx
│   │   │   │   │   ├── selectors.ts
│   │   │   │   │   ├── store.ts
│   │   │   │   │   └── types.ts
│   │   │   │   ├── admin/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   └── SettingsNavigation.tsx
│   │   │   │   │   ├── pages/
│   │   │   │   │   │   ├── AnnouncementsSettings/
│   │   │   │   │   │   │   ├── AnnouncementsSettingsForm.tsx
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   │   └── translations.ts
│   │   │   │   │   │   ├── AssessmentSettings/
│   │   │   │   │   │   │   ├── AssessmentCategoriesManager/
│   │   │   │   │   │   │   │   ├── Category.tsx
│   │   │   │   │   │   │   │   ├── MoveAssessmentsMenu.tsx
│   │   │   │   │   │   │   │   ├── MoveTabsMenu.tsx
│   │   │   │   │   │   │   │   ├── Tab.tsx
│   │   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   │   └── utils.ts
│   │   │   │   │   │   │   ├── AssessmentSettingsContext.ts
│   │   │   │   │   │   │   ├── AssessmentSettingsForm.tsx
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   │   └── translations.ts
│   │   │   │   │   │   ├── CodaveriSettings/
│   │   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   │   ├── AssessmentCategory.tsx
│   │   │   │   │   │   │   │   ├── AssessmentList.tsx
│   │   │   │   │   │   │   │   ├── AssessmentListItem.tsx
│   │   │   │   │   │   │   │   ├── AssessmentProgrammingQnList.tsx
│   │   │   │   │   │   │   │   ├── AssessmentTab.tsx
│   │   │   │   │   │   │   │   ├── CodaveriSettingsChip.tsx
│   │   │   │   │   │   │   │   ├── buttons/
│   │   │   │   │   │   │   │   │   ├── CodaveriEvaluatorToggleButton.tsx
│   │   │   │   │   │   │   │   │   ├── CodaveriToggleButtons.tsx
│   │   │   │   │   │   │   │   │   ├── ExpandAllSwitch.tsx
│   │   │   │   │   │   │   │   │   └── LiveFeedbackToggleButton.tsx
│   │   │   │   │   │   │   │   ├── forms/
│   │   │   │   │   │   │   │   │   └── CodaveriSettingsForm.tsx
│   │   │   │   │   │   │   │   └── lists/
│   │   │   │   │   │   │   │       └── CollapsibleList.tsx
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   │   ├── selectors.ts
│   │   │   │   │   │   │   └── translations.ts
│   │   │   │   │   │   ├── CommentsSettings/
│   │   │   │   │   │   │   ├── CommentsSettingsForm.tsx
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   │   └── translations.ts
│   │   │   │   │   │   ├── ComponentSettings/
│   │   │   │   │   │   │   ├── ComponentSettingsForm.tsx
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   │   └── translations.ts
│   │   │   │   │   │   ├── CourseSettings/
│   │   │   │   │   │   │   ├── CourseSettingsForm.tsx
│   │   │   │   │   │   │   ├── DeleteCoursePrompt.tsx
│   │   │   │   │   │   │   ├── OffsetTimesPrompt.tsx
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   │   ├── translations.ts
│   │   │   │   │   │   │   └── validationSchema.ts
│   │   │   │   │   │   ├── ForumsSettings/
│   │   │   │   │   │   │   ├── ForumsSettingsForm.tsx
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   │   └── translations.ts
│   │   │   │   │   │   ├── LeaderboardSettings/
│   │   │   │   │   │   │   ├── LeaderboardSettingsForm.tsx
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   │   └── translations.ts
│   │   │   │   │   │   ├── LessonPlanSettings/
│   │   │   │   │   │   │   ├── MilestoneGroupSettings.jsx
│   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   └── index.test.tsx
│   │   │   │   │   │   │   ├── index.jsx
│   │   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   │   └── translations.intl.js
│   │   │   │   │   │   ├── MaterialsSettings/
│   │   │   │   │   │   │   ├── MaterialsSettingsForm.tsx
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   │   └── translations.ts
│   │   │   │   │   │   ├── NotificationSettings/
│   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   └── index.test.tsx
│   │   │   │   │   │   │   ├── index.jsx
│   │   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   │   └── translations.intl.js
│   │   │   │   │   │   ├── RagWiseSettings/
│   │   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   │   ├── CourseTab.tsx
│   │   │   │   │   │   │   │   ├── FolderTab.tsx
│   │   │   │   │   │   │   │   ├── ForumItem.tsx
│   │   │   │   │   │   │   │   ├── ForumList.tsx
│   │   │   │   │   │   │   │   ├── MaterialItem.tsx
│   │   │   │   │   │   │   │   ├── MaterialList.tsx
│   │   │   │   │   │   │   │   ├── buttons/
│   │   │   │   │   │   │   │   │   ├── ExpandAllSwitch.tsx
│   │   │   │   │   │   │   │   │   ├── ForumKnowledgeBaseSwitch.tsx
│   │   │   │   │   │   │   │   │   └── MaterialKnowledgeBaseSwitch.tsx
│   │   │   │   │   │   │   │   ├── forms/
│   │   │   │   │   │   │   │   │   └── RagWiseSettingsForm.tsx
│   │   │   │   │   │   │   │   └── lists/
│   │   │   │   │   │   │   │       └── CollapsibleList.tsx
│   │   │   │   │   │   │   ├── constants.ts
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   │   ├── selectors.ts
│   │   │   │   │   │   │   └── translations.ts
│   │   │   │   │   │   ├── ScholaisticSettings/
│   │   │   │   │   │   │   ├── PingResultAlert.tsx
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   ├── loader.ts
│   │   │   │   │   │   │   └── operations.ts
│   │   │   │   │   │   ├── SidebarSettings/
│   │   │   │   │   │   │   ├── SidebarSettingsForm.tsx
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   │   └── translations.ts
│   │   │   │   │   │   ├── StoriesSettings/
│   │   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   │   └── Introduction.tsx
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   └── operations.ts
│   │   │   │   │   │   └── VideosSettings/
│   │   │   │   │   │       ├── VideosSettingsForm.tsx
│   │   │   │   │   │       ├── VideosTabsManager/
│   │   │   │   │   │       │   ├── Tab.tsx
│   │   │   │   │   │       │   └── index.tsx
│   │   │   │   │   │       ├── index.tsx
│   │   │   │   │   │       ├── operations.ts
│   │   │   │   │   │       └── translations.ts
│   │   │   │   │   ├── reducers/
│   │   │   │   │   │   ├── codaveriSettings.ts
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   ├── lessonPlanSettings.ts
│   │   │   │   │   │   ├── notificationSettings.ts
│   │   │   │   │   │   └── ragWiseSettings.ts
│   │   │   │   │   └── translations.ts
│   │   │   │   ├── announcements/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── buttons/
│   │   │   │   │   │   │   └── NewAnnouncementButton.tsx
│   │   │   │   │   │   ├── forms/
│   │   │   │   │   │   │   └── AnnouncementForm.tsx
│   │   │   │   │   │   └── misc/
│   │   │   │   │   │       ├── AnnouncementCard.tsx
│   │   │   │   │   │       └── AnnouncementsDisplay.tsx
│   │   │   │   │   ├── handles.ts
│   │   │   │   │   ├── operations.ts
│   │   │   │   │   ├── pages/
│   │   │   │   │   │   ├── AnnouncementEdit/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── AnnouncementNew/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   └── AnnouncementsIndex/
│   │   │   │   │   │       └── index.tsx
│   │   │   │   │   ├── selectors.ts
│   │   │   │   │   ├── store.ts
│   │   │   │   │   └── types.ts
│   │   │   │   ├── assessment/
│   │   │   │   │   ├── attemptLoader.ts
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── AssessmentForm/
│   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   └── index.test.tsx
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   │   ├── translations.ts
│   │   │   │   │   │   │   ├── types.ts
│   │   │   │   │   │   │   └── useFormValidation.tsx
│   │   │   │   │   │   ├── ConvertMcqMrqButton/
│   │   │   │   │   │   │   ├── ConvertMcqMrqPrompt.tsx
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── FileManager/
│   │   │   │   │   │   │   ├── Toolbar.tsx
│   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   └── index.test.tsx
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   └── translations.intl.js
│   │   │   │   │   │   ├── Koditsu/
│   │   │   │   │   │   │   ├── KoditsuChip.tsx
│   │   │   │   │   │   │   └── KoditsuChipButton.tsx
│   │   │   │   │   │   └── monitoring/
│   │   │   │   │   │       ├── BlocksInvalidBrowserFormField.tsx
│   │   │   │   │   │       ├── BrowserAuthorizationMethodOptionsFormFields/
│   │   │   │   │   │       │   ├── SebConfigKeyOptionsFormFields.tsx
│   │   │   │   │   │       │   ├── UserAgentOptionsFormFields.tsx
│   │   │   │   │   │       │   ├── common.ts
│   │   │   │   │   │       │   └── index.tsx
│   │   │   │   │   │       ├── BrowserAuthorizationOptionsFormFields.tsx
│   │   │   │   │   │       ├── EnableMonitoringFormField.tsx
│   │   │   │   │   │       ├── MonitoringIntervalsFormFields.tsx
│   │   │   │   │   │       ├── MonitoringOptionsFormFields.tsx
│   │   │   │   │   │       └── translations.ts
│   │   │   │   │   ├── constants.js
│   │   │   │   │   ├── handles.ts
│   │   │   │   │   ├── operations/
│   │   │   │   │   │   ├── assessments.ts
│   │   │   │   │   │   ├── history.ts
│   │   │   │   │   │   ├── liveFeedback.ts
│   │   │   │   │   │   ├── monitoring.ts
│   │   │   │   │   │   ├── plagiarism.ts
│   │   │   │   │   │   ├── questions.ts
│   │   │   │   │   │   └── statistics.ts
│   │   │   │   │   ├── pages/
│   │   │   │   │   │   ├── AssessmentAuthenticate/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── AssessmentBlockedByMonitorPage.tsx
│   │   │   │   │   │   ├── AssessmentEdit/
│   │   │   │   │   │   │   ├── AssessmentEditPage.jsx
│   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   └── index.test.tsx
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── AssessmentGenerate/
│   │   │   │   │   │   │   ├── GenerateTabs.tsx
│   │   │   │   │   │   │   ├── LockableSection.tsx
│   │   │   │   │   │   │   ├── MultipleResponse/
│   │   │   │   │   │   │   │   ├── GenerateMcqMrqConversation.tsx
│   │   │   │   │   │   │   │   ├── GenerateMcqMrqExportDialog.tsx
│   │   │   │   │   │   │   │   ├── GenerateMcqMrqPrototypeForm.tsx
│   │   │   │   │   │   │   │   └── GenerateMcqMrqQuestionPage.tsx
│   │   │   │   │   │   │   ├── Programming/
│   │   │   │   │   │   │   │   ├── GenerateProgrammingConversation.tsx
│   │   │   │   │   │   │   │   ├── GenerateProgrammingExportDialog.tsx
│   │   │   │   │   │   │   │   ├── GenerateProgrammingPrototypeForm.tsx
│   │   │   │   │   │   │   │   ├── GenerateProgrammingQuestionPage.tsx
│   │   │   │   │   │   │   │   └── TestCasesManager.tsx
│   │   │   │   │   │   │   ├── constants.ts
│   │   │   │   │   │   │   ├── selectors.ts
│   │   │   │   │   │   │   ├── types.ts
│   │   │   │   │   │   │   └── utils.ts
│   │   │   │   │   │   ├── AssessmentMonitoring/
│   │   │   │   │   │   │   ├── PulseGrid.tsx
│   │   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   │   ├── ActiveSessionBlob.tsx
│   │   │   │   │   │   │   │   ├── ActivityCenter.tsx
│   │   │   │   │   │   │   │   ├── ConnectionStatus.tsx
│   │   │   │   │   │   │   │   ├── FilterAutocomplete.tsx
│   │   │   │   │   │   │   │   ├── HeartbeatDetailCard.tsx
│   │   │   │   │   │   │   │   ├── HeartbeatsTimeline.tsx
│   │   │   │   │   │   │   │   ├── HeartbeatsTimelineChart.tsx
│   │   │   │   │   │   │   │   ├── SebPayloadDetail.tsx
│   │   │   │   │   │   │   │   ├── Session.tsx
│   │   │   │   │   │   │   │   ├── SessionBlob.tsx
│   │   │   │   │   │   │   │   ├── SessionBlobLegend.tsx
│   │   │   │   │   │   │   │   ├── SessionDetailsPopup.tsx
│   │   │   │   │   │   │   │   ├── SessionsGrid.tsx
│   │   │   │   │   │   │   │   ├── UserAgentDetail.tsx
│   │   │   │   │   │   │   │   └── ValidChip.tsx
│   │   │   │   │   │   │   ├── hooks/
│   │   │   │   │   │   │   │   ├── liveMonitoringChannel.ts
│   │   │   │   │   │   │   │   ├── useLiveMonitoringChannel.ts
│   │   │   │   │   │   │   │   ├── useMonitoring.ts
│   │   │   │   │   │   │   │   └── usePresence.ts
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   ├── selectors.ts
│   │   │   │   │   │   │   ├── types.ts
│   │   │   │   │   │   │   └── utils.ts
│   │   │   │   │   │   ├── AssessmentPlagiarism/
│   │   │   │   │   │   │   ├── AssessmentPlagiarismPage.tsx
│   │   │   │   │   │   │   ├── PlagiarismCheckStatus.tsx
│   │   │   │   │   │   │   ├── PlagiarismResultsTable.tsx
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   └── selectors.ts
│   │   │   │   │   │   ├── AssessmentShow/
│   │   │   │   │   │   │   ├── AssessmentDetails.tsx
│   │   │   │   │   │   │   ├── AssessmentShowHeader.tsx
│   │   │   │   │   │   │   ├── AssessmentShowPage.tsx
│   │   │   │   │   │   │   ├── GenerateQuestionMenu.tsx
│   │   │   │   │   │   │   ├── McqWidget.tsx
│   │   │   │   │   │   │   ├── NewQuestionMenu.tsx
│   │   │   │   │   │   │   ├── Question.tsx
│   │   │   │   │   │   │   ├── QuestionsManager.tsx
│   │   │   │   │   │   │   ├── UnavailableAlert.tsx
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   └── prompts/
│   │   │   │   │   │   │       ├── DeleteQuestionButtonPrompt.tsx
│   │   │   │   │   │   │       └── DuplicationPrompt.tsx
│   │   │   │   │   │   ├── AssessmentStatistics/
│   │   │   │   │   │   │   ├── AncestorOptions.tsx
│   │   │   │   │   │   │   ├── AncestorStatistics.tsx
│   │   │   │   │   │   │   ├── AnswerDisplay/
│   │   │   │   │   │   │   │   └── LastAttempt.tsx
│   │   │   │   │   │   │   ├── AssessmentStatisticsPage.tsx
│   │   │   │   │   │   │   ├── DuplicationHistoryStatistics.tsx
│   │   │   │   │   │   │   ├── GradeDistribution/
│   │   │   │   │   │   │   │   ├── AncestorGradesChart.tsx
│   │   │   │   │   │   │   │   ├── GradesChart.tsx
│   │   │   │   │   │   │   │   └── MainGradesChart.tsx
│   │   │   │   │   │   │   ├── LiveFeedbackHistory/
│   │   │   │   │   │   │   │   ├── GetHelpSlider.tsx
│   │   │   │   │   │   │   │   ├── LiveFeedbackConversation.tsx
│   │   │   │   │   │   │   │   ├── LiveFeedbackDetails.tsx
│   │   │   │   │   │   │   │   ├── LiveFeedbackFiles.tsx
│   │   │   │   │   │   │   │   ├── LiveFeedbackHistoryTimelineView.tsx
│   │   │   │   │   │   │   │   ├── LiveFeedbackMessageHistory.tsx
│   │   │   │   │   │   │   │   ├── LiveFeedbackMessageOptionHistory.tsx
│   │   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   │   ├── LiveFeedbackStatistics.tsx
│   │   │   │   │   │   │   ├── LiveFeedbackStatisticsTable.tsx
│   │   │   │   │   │   │   ├── StatisticsCharts.tsx
│   │   │   │   │   │   │   ├── StudentAttemptCountTable.tsx
│   │   │   │   │   │   │   ├── StudentGradesPerQuestionTable.tsx
│   │   │   │   │   │   │   ├── SubmissionStatus/
│   │   │   │   │   │   │   │   ├── AncestorSubmissionChart.tsx
│   │   │   │   │   │   │   │   ├── MainSubmissionChart.tsx
│   │   │   │   │   │   │   │   └── SubmissionStatusChart.tsx
│   │   │   │   │   │   │   ├── SubmissionTimeAndGradeStatistics/
│   │   │   │   │   │   │   │   ├── AncestorSubmissionTimeAndGradeStatistics.tsx
│   │   │   │   │   │   │   │   ├── MainSubmissionTimeAndGradeStatistics.tsx
│   │   │   │   │   │   │   │   └── SubmissionTimeAndGradeChart.tsx
│   │   │   │   │   │   │   ├── classNameUtils.ts
│   │   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   │   └── LiveFeedbackMetricsSelector.tsx
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   ├── selectors.ts
│   │   │   │   │   │   │   ├── translations.ts
│   │   │   │   │   │   │   └── utils.js
│   │   │   │   │   │   └── AssessmentsIndex/
│   │   │   │   │   │       ├── ActionButtons.tsx
│   │   │   │   │   │       ├── AssessmentsTable.tsx
│   │   │   │   │   │       ├── NewAssessmentFormButton.jsx
│   │   │   │   │   │       ├── StatusBadges.tsx
│   │   │   │   │   │       ├── UnavailableMessage.tsx
│   │   │   │   │   │       ├── __test__/
│   │   │   │   │   │       │   └── index.test.jsx
│   │   │   │   │   │       └── index.tsx
│   │   │   │   │   ├── question/
│   │   │   │   │   │   ├── commons/
│   │   │   │   │   │   │   ├── useDirty.ts
│   │   │   │   │   │   │   └── utils.ts
│   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   ├── AIGradingPlaygroundAlert.tsx
│   │   │   │   │   │   │   ├── CommonQuestionFields.tsx
│   │   │   │   │   │   │   ├── QuestionFormOutlet.tsx
│   │   │   │   │   │   │   └── SkillsAutocomplete.tsx
│   │   │   │   │   │   ├── forum-post-responses/
│   │   │   │   │   │   │   ├── EditForumPostResponsePage.tsx
│   │   │   │   │   │   │   ├── NewForumPostResponsePage.tsx
│   │   │   │   │   │   │   ├── commons/
│   │   │   │   │   │   │   │   └── validations.ts
│   │   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   │   └── ForumPostResponseForm.tsx
│   │   │   │   │   │   │   └── operation.ts
│   │   │   │   │   │   ├── multiple-responses/
│   │   │   │   │   │   │   ├── EditMcqMrqPage.tsx
│   │   │   │   │   │   │   ├── NewMcqMrqPage.tsx
│   │   │   │   │   │   │   ├── commons/
│   │   │   │   │   │   │   │   ├── translationAdapter.tsx
│   │   │   │   │   │   │   │   └── validations.ts
│   │   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   │   ├── AdaptedForm.tsx
│   │   │   │   │   │   │   │   ├── ConvertMcqMrqIllustration/
│   │   │   │   │   │   │   │   │   ├── McqIllustration.tsx
│   │   │   │   │   │   │   │   │   ├── MrqIllustration.tsx
│   │   │   │   │   │   │   │   │   ├── OptionSkeleton.tsx
│   │   │   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   │   │   ├── McqMrqForm.tsx
│   │   │   │   │   │   │   │   ├── Option.tsx
│   │   │   │   │   │   │   │   └── OptionsManager.tsx
│   │   │   │   │   │   │   └── operations.ts
│   │   │   │   │   │   ├── programming/
│   │   │   │   │   │   │   ├── EditProgrammingQuestionPage.tsx
│   │   │   │   │   │   │   ├── NewProgrammingQuestionPage.tsx
│   │   │   │   │   │   │   ├── ProgrammingForm.tsx
│   │   │   │   │   │   │   ├── commons/
│   │   │   │   │   │   │   │   ├── builder.ts
│   │   │   │   │   │   │   │   └── validation.ts
│   │   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   │   ├── ReorderableTestCasesManager.tsx
│   │   │   │   │   │   │   │   ├── common/
│   │   │   │   │   │   │   │   │   ├── ControlledEditor.tsx
│   │   │   │   │   │   │   │   │   ├── DataFileRow.tsx
│   │   │   │   │   │   │   │   │   ├── DataFilesAccordion.tsx
│   │   │   │   │   │   │   │   │   ├── DataFilesManager.tsx
│   │   │   │   │   │   │   │   │   ├── EditorAccordion.tsx
│   │   │   │   │   │   │   │   │   ├── ExpressionField.tsx
│   │   │   │   │   │   │   │   │   ├── ImportResult.tsx
│   │   │   │   │   │   │   │   │   ├── InstalledDependenciesPrompt.tsx
│   │   │   │   │   │   │   │   │   ├── InstalledDependenciesTable.tsx
│   │   │   │   │   │   │   │   │   ├── PackageInfo.tsx
│   │   │   │   │   │   │   │   │   ├── PackageUploader.tsx
│   │   │   │   │   │   │   │   │   ├── ReorderableJavaTestCase.tsx
│   │   │   │   │   │   │   │   │   ├── ReorderableTestCase.tsx
│   │   │   │   │   │   │   │   │   ├── ReorderableTestCases.tsx
│   │   │   │   │   │   │   │   │   ├── StaticTestCase.tsx
│   │   │   │   │   │   │   │   │   ├── StaticTestCases.tsx
│   │   │   │   │   │   │   │   │   ├── StaticTestCasesTable.tsx
│   │   │   │   │   │   │   │   │   ├── TestCaseCell.tsx
│   │   │   │   │   │   │   │   │   └── TestCaseRow.tsx
│   │   │   │   │   │   │   │   ├── package/
│   │   │   │   │   │   │   │   │   ├── BasicPackageEditor.tsx
│   │   │   │   │   │   │   │   │   ├── CppPackageEditor.tsx
│   │   │   │   │   │   │   │   │   ├── CsharpPackageEditor.tsx
│   │   │   │   │   │   │   │   │   ├── GoPackageEditor.tsx
│   │   │   │   │   │   │   │   │   ├── JavaPackageEditor.tsx
│   │   │   │   │   │   │   │   │   ├── JavascriptPackageEditor.tsx
│   │   │   │   │   │   │   │   │   ├── PackageDetails.tsx
│   │   │   │   │   │   │   │   │   ├── PackageEditor.tsx
│   │   │   │   │   │   │   │   │   ├── PolyglotEditor.tsx
│   │   │   │   │   │   │   │   │   ├── PythonPackageEditor.tsx
│   │   │   │   │   │   │   │   │   ├── RPackageEditor.tsx
│   │   │   │   │   │   │   │   │   ├── RustPackageEditor.tsx
│   │   │   │   │   │   │   │   │   └── TypescriptPackageEditor.tsx
│   │   │   │   │   │   │   │   └── sections/
│   │   │   │   │   │   │   │       ├── BuildLog.tsx
│   │   │   │   │   │   │   │       ├── EvaluatorFields.tsx
│   │   │   │   │   │   │   │       ├── FeedbackFields.tsx
│   │   │   │   │   │   │   │       ├── LanguageFields.tsx
│   │   │   │   │   │   │   │       ├── PackageFields.tsx
│   │   │   │   │   │   │   │       ├── QuestionFields.tsx
│   │   │   │   │   │   │   │       └── SubmitWarningDialog.tsx
│   │   │   │   │   │   │   ├── hooks/
│   │   │   │   │   │   │   │   ├── ProgrammingFormDataContext.tsx
│   │   │   │   │   │   │   │   └── useLanguageMode.tsx
│   │   │   │   │   │   │   └── operations.ts
│   │   │   │   │   │   ├── reducers/
│   │   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   │   └── rubrics.ts
│   │   │   │   │   │   ├── rubric-based-responses/
│   │   │   │   │   │   │   ├── EditRubricBasedResponsePage.tsx
│   │   │   │   │   │   │   ├── NewRubricBasedResponsePage.tsx
│   │   │   │   │   │   │   ├── commons/
│   │   │   │   │   │   │   │   └── validation.ts
│   │   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   │   ├── AIGradingFields.tsx
│   │   │   │   │   │   │   │   ├── CategoryManager.tsx
│   │   │   │   │   │   │   │   ├── QuestionFields.tsx
│   │   │   │   │   │   │   │   └── RubricBasedResponseForm.tsx
│   │   │   │   │   │   │   ├── hooks/
│   │   │   │   │   │   │   │   └── RubricBasedResponseFormDataContext.tsx
│   │   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   │   └── utils.ts
│   │   │   │   │   │   ├── rubric-playground/
│   │   │   │   │   │   │   ├── AddAnswersPrompt.tsx
│   │   │   │   │   │   │   ├── AnswerEvaluationsTable/
│   │   │   │   │   │   │   │   ├── CategoryGradeCell.tsx
│   │   │   │   │   │   │   │   ├── PopoverContentCell.tsx
│   │   │   │   │   │   │   │   ├── TotalGradeCell.tsx
│   │   │   │   │   │   │   │   ├── UnevaluatedCell.tsx
│   │   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   │   ├── types.ts
│   │   │   │   │   │   │   │   └── utils.ts
│   │   │   │   │   │   │   ├── AnswerEvaluationsTableHeader.tsx
│   │   │   │   │   │   │   ├── RubricEditForm/
│   │   │   │   │   │   │   │   ├── PlaygroundCategoryManager.tsx
│   │   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   │   ├── RubricHeader/
│   │   │   │   │   │   │   │   ├── HeaderButton.tsx
│   │   │   │   │   │   │   │   ├── VersionSlider.tsx
│   │   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   │   ├── RubricPlaygroundPage.tsx
│   │   │   │   │   │   │   ├── operations/
│   │   │   │   │   │   │   │   ├── answers.ts
│   │   │   │   │   │   │   │   ├── mockAnswers.ts
│   │   │   │   │   │   │   │   ├── rowEvaluation.ts
│   │   │   │   │   │   │   │   └── rubric.ts
│   │   │   │   │   │   │   ├── translations.ts
│   │   │   │   │   │   │   ├── types.ts
│   │   │   │   │   │   │   └── utils.ts
│   │   │   │   │   │   ├── scribing/
│   │   │   │   │   │   │   ├── ScribingQuestion.tsx
│   │   │   │   │   │   │   ├── ScribingQuestionForm/
│   │   │   │   │   │   │   │   ├── ScribingQuestionForm.scss
│   │   │   │   │   │   │   │   ├── index.jsx
│   │   │   │   │   │   │   │   └── translations.ts
│   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   ├── index.test.tsx
│   │   │   │   │   │   │   │   └── responses.test.ts
│   │   │   │   │   │   │   ├── constants.js
│   │   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   │   ├── propTypes.js
│   │   │   │   │   │   │   ├── store.ts
│   │   │   │   │   │   │   ├── types.ts
│   │   │   │   │   │   │   └── utils.js
│   │   │   │   │   │   ├── selectors/
│   │   │   │   │   │   │   └── rubrics.ts
│   │   │   │   │   │   ├── text-responses/
│   │   │   │   │   │   │   ├── EditTextResponsePage.tsx
│   │   │   │   │   │   │   ├── NewTextResponsePage.tsx
│   │   │   │   │   │   │   ├── commons/
│   │   │   │   │   │   │   │   └── validations.ts
│   │   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   │   ├── FileUploadManager.tsx
│   │   │   │   │   │   │   │   ├── Solution.tsx
│   │   │   │   │   │   │   │   ├── SolutionsManager.tsx
│   │   │   │   │   │   │   │   └── TextResponseForm.tsx
│   │   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   │   └── utils.tsx
│   │   │   │   │   │   └── voice-responses/
│   │   │   │   │   │       ├── EditVoicePage.tsx
│   │   │   │   │   │       ├── NewVoicePage.tsx
│   │   │   │   │   │       ├── components/
│   │   │   │   │   │       │   └── VoiceForm.tsx
│   │   │   │   │   │       └── operations.ts
│   │   │   │   │   ├── reducers/
│   │   │   │   │   │   ├── editPage.js
│   │   │   │   │   │   ├── formDialog.js
│   │   │   │   │   │   ├── generation.ts
│   │   │   │   │   │   ├── liveFeedback.ts
│   │   │   │   │   │   ├── monitoring.ts
│   │   │   │   │   │   ├── plagiarism.ts
│   │   │   │   │   │   └── statistics.ts
│   │   │   │   │   ├── sessions/
│   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   └── pages/
│   │   │   │   │   │       └── AssessmentSessionNew/
│   │   │   │   │   │           └── index.tsx
│   │   │   │   │   ├── skills/
│   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   ├── buttons/
│   │   │   │   │   │   │   │   └── SkillManagementButtons.tsx
│   │   │   │   │   │   │   ├── dialogs/
│   │   │   │   │   │   │   │   └── SkillDialog.tsx
│   │   │   │   │   │   │   ├── forms/
│   │   │   │   │   │   │   │   └── SkillForm.tsx
│   │   │   │   │   │   │   └── tables/
│   │   │   │   │   │   │       └── SkillsTable.tsx
│   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   ├── pages/
│   │   │   │   │   │   │   └── SkillsIndex/
│   │   │   │   │   │   │       └── index.tsx
│   │   │   │   │   │   ├── selectors.ts
│   │   │   │   │   │   ├── store.ts
│   │   │   │   │   │   └── types.ts
│   │   │   │   │   ├── store.ts
│   │   │   │   │   ├── submission/
│   │   │   │   │   │   ├── actions/
│   │   │   │   │   │   │   ├── annotations.js
│   │   │   │   │   │   │   ├── answers/
│   │   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   │   └── scribing.test.ts
│   │   │   │   │   │   │   │   ├── index.js
│   │   │   │   │   │   │   │   ├── programming.js
│   │   │   │   │   │   │   │   ├── scribing.ts
│   │   │   │   │   │   │   │   ├── textResponse.js
│   │   │   │   │   │   │   │   └── voiceResponse.js
│   │   │   │   │   │   │   ├── comments.js
│   │   │   │   │   │   │   ├── index.js
│   │   │   │   │   │   │   ├── live_feedback.ts
│   │   │   │   │   │   │   ├── logs.ts
│   │   │   │   │   │   │   ├── submissions.js
│   │   │   │   │   │   │   └── utils.js
│   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   ├── AllAttempts/
│   │   │   │   │   │   │   │   ├── AllAttemptsQuestion.tsx
│   │   │   │   │   │   │   │   ├── AllAttemptsSequenceView.tsx
│   │   │   │   │   │   │   │   ├── AllAttemptsTimelineView.tsx
│   │   │   │   │   │   │   │   ├── Comment.tsx
│   │   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   │   ├── AnswerDetails/
│   │   │   │   │   │   │   │   ├── AnswerDetails.tsx
│   │   │   │   │   │   │   │   ├── AttachmentDetails.tsx
│   │   │   │   │   │   │   │   ├── FileUploadDetails.tsx
│   │   │   │   │   │   │   │   ├── ForumPostResponseComponent/
│   │   │   │   │   │   │   │   │   ├── ParentPostPack.tsx
│   │   │   │   │   │   │   │   │   ├── PostContent.tsx
│   │   │   │   │   │   │   │   │   └── PostPack.tsx
│   │   │   │   │   │   │   │   ├── ForumPostResponseDetails.tsx
│   │   │   │   │   │   │   │   ├── MultipleChoiceDetails.tsx
│   │   │   │   │   │   │   │   ├── MultipleResponseDetails.tsx
│   │   │   │   │   │   │   │   ├── ProgrammingAnswerDetails.tsx
│   │   │   │   │   │   │   │   ├── ProgrammingComponent/
│   │   │   │   │   │   │   │   │   ├── CodaveriFeedbackStatus.tsx
│   │   │   │   │   │   │   │   │   ├── FileContent.tsx
│   │   │   │   │   │   │   │   │   ├── TestCaseRow.tsx
│   │   │   │   │   │   │   │   │   └── TestCases.tsx
│   │   │   │   │   │   │   │   ├── RubricBasedResponseDetails.tsx
│   │   │   │   │   │   │   │   └── TextResponseDetails.tsx
│   │   │   │   │   │   │   ├── DropzoneErrorComponent.tsx
│   │   │   │   │   │   │   ├── Editor.jsx
│   │   │   │   │   │   │   ├── EvaluatorErrorPanel.tsx
│   │   │   │   │   │   │   ├── FileInput.jsx
│   │   │   │   │   │   │   ├── GetHelpChatPage/
│   │   │   │   │   │   │   │   ├── ChatInputArea.tsx
│   │   │   │   │   │   │   │   ├── ChipButton.tsx
│   │   │   │   │   │   │   │   ├── ConversationArea.tsx
│   │   │   │   │   │   │   │   ├── Header.tsx
│   │   │   │   │   │   │   │   ├── SuggestionChips.tsx
│   │   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   │   └── utils.ts
│   │   │   │   │   │   │   ├── MarkdownText.tsx
│   │   │   │   │   │   │   ├── ProgressPanel.tsx
│   │   │   │   │   │   │   ├── ReadOnlyEditor/
│   │   │   │   │   │   │   │   ├── AddCommentIcon.jsx
│   │   │   │   │   │   │   │   ├── Checkbox.jsx
│   │   │   │   │   │   │   │   ├── NarrowEditor.jsx
│   │   │   │   │   │   │   │   ├── WideComments.jsx
│   │   │   │   │   │   │   │   ├── WideEditor.jsx
│   │   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   │   ├── ScribingView/
│   │   │   │   │   │   │   │   ├── LayersComponent.tsx
│   │   │   │   │   │   │   │   ├── ScribingCanvas.tsx
│   │   │   │   │   │   │   │   ├── ScribingToolbar.tsx
│   │   │   │   │   │   │   │   ├── ScribingView.scss
│   │   │   │   │   │   │   │   ├── ToolDropdown.jsx
│   │   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   │   ├── ScribingToolbar.test.tsx
│   │   │   │   │   │   │   │   │   └── index.test.tsx
│   │   │   │   │   │   │   │   ├── fields/
│   │   │   │   │   │   │   │   │   ├── ColorPickerField.jsx
│   │   │   │   │   │   │   │   │   ├── FontFamilyField.jsx
│   │   │   │   │   │   │   │   │   ├── FontSizeField.jsx
│   │   │   │   │   │   │   │   │   ├── LineStyleField.jsx
│   │   │   │   │   │   │   │   │   ├── LineThicknessField.jsx
│   │   │   │   │   │   │   │   │   ├── ShapeField.tsx
│   │   │   │   │   │   │   │   │   └── __test__/
│   │   │   │   │   │   │   │   │       └── ColorPickerField.test.js
│   │   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   │   └── popovers/
│   │   │   │   │   │   │   │       ├── DrawPopover.jsx
│   │   │   │   │   │   │   │       ├── LinePopover.jsx
│   │   │   │   │   │   │   │       ├── ShapePopover.jsx
│   │   │   │   │   │   │   │       └── TypePopover.jsx
│   │   │   │   │   │   │   ├── SubmissionWorkflowState.tsx
│   │   │   │   │   │   │   ├── TextResponseSolutions.jsx
│   │   │   │   │   │   │   ├── WarningDialog.tsx
│   │   │   │   │   │   │   ├── answers/
│   │   │   │   │   │   │   │   ├── Answer.tsx
│   │   │   │   │   │   │   │   ├── AnswerHeader.tsx
│   │   │   │   │   │   │   │   ├── AnswerNotImplemented.tsx
│   │   │   │   │   │   │   │   ├── FileUpload/
│   │   │   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   │   │   ├── ForumPostResponse/
│   │   │   │   │   │   │   │   │   ├── CardTitle.jsx
│   │   │   │   │   │   │   │   │   ├── Error.jsx
│   │   │   │   │   │   │   │   │   ├── ForumCard.jsx
│   │   │   │   │   │   │   │   │   ├── ForumPost.jsx
│   │   │   │   │   │   │   │   │   ├── ForumPostOption.jsx
│   │   │   │   │   │   │   │   │   ├── ForumPostSelect.jsx
│   │   │   │   │   │   │   │   │   ├── ForumPostSelectDialog.jsx
│   │   │   │   │   │   │   │   │   ├── Labels.jsx
│   │   │   │   │   │   │   │   │   ├── ParentPost.jsx
│   │   │   │   │   │   │   │   │   ├── SelectedPostCard.jsx
│   │   │   │   │   │   │   │   │   ├── TopicCard.jsx
│   │   │   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   │   │   ├── MultipleChoice/
│   │   │   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   │   │   ├── MultipleResponse/
│   │   │   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   │   │   ├── Programming/
│   │   │   │   │   │   │   │   │   ├── ProgrammingFile.tsx
│   │   │   │   │   │   │   │   │   ├── ProgrammingFileDownloadChip.tsx
│   │   │   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   │   │   └── ProgrammingFile.test.tsx
│   │   │   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   │   │   ├── RubricBasedResponse/
│   │   │   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   │   │   ├── TextResponse/
│   │   │   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   │   │   ├── adapters/
│   │   │   │   │   │   │   │   │   ├── FileUploadAdapter.tsx
│   │   │   │   │   │   │   │   │   ├── ForumPostResponseAdapter.tsx
│   │   │   │   │   │   │   │   │   ├── MultipleChoiceAdapter.tsx
│   │   │   │   │   │   │   │   │   ├── MultipleResponseAdapter.tsx
│   │   │   │   │   │   │   │   │   ├── ProgrammingAdapter.tsx
│   │   │   │   │   │   │   │   │   ├── RubricBasedResponseAdapter.tsx
│   │   │   │   │   │   │   │   │   ├── ScribingAdapter.tsx
│   │   │   │   │   │   │   │   │   ├── TextResponseAdapter.tsx
│   │   │   │   │   │   │   │   │   └── VoiceResponseAdapter.tsx
│   │   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   │   ├── types.ts
│   │   │   │   │   │   │   │   └── utils.tsx
│   │   │   │   │   │   │   └── comment/
│   │   │   │   │   │   │       ├── CodaveriCommentCard.jsx
│   │   │   │   │   │   │       ├── CommentCard.jsx
│   │   │   │   │   │   │       └── CommentField.jsx
│   │   │   │   │   │   ├── constants.ts
│   │   │   │   │   │   ├── containers/
│   │   │   │   │   │   │   ├── Annotations.jsx
│   │   │   │   │   │   │   ├── CodaveriFeedbackStatus.jsx
│   │   │   │   │   │   │   ├── Comments.jsx
│   │   │   │   │   │   │   ├── GradingPanel.jsx
│   │   │   │   │   │   │   ├── PostPreview.tsx
│   │   │   │   │   │   │   ├── ProgrammingImport/
│   │   │   │   │   │   │   │   ├── ImportedFileView.jsx
│   │   │   │   │   │   │   │   ├── ProgrammingImportEditor.jsx
│   │   │   │   │   │   │   │   └── ProgrammingImportHistoryView.jsx
│   │   │   │   │   │   │   ├── QuestionGrade.tsx
│   │   │   │   │   │   │   ├── ReadOnlyEditor.jsx
│   │   │   │   │   │   │   ├── RubricExplanation.tsx
│   │   │   │   │   │   │   ├── RubricGrade.tsx
│   │   │   │   │   │   │   ├── RubricPanel.tsx
│   │   │   │   │   │   │   ├── RubricPanelRow.tsx
│   │   │   │   │   │   │   ├── ScribingView.jsx
│   │   │   │   │   │   │   ├── TestCaseView/
│   │   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   │   └── index.test.js
│   │   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   │   ├── UploadedFileView.jsx
│   │   │   │   │   │   │   └── VoiceResponseAnswer.jsx
│   │   │   │   │   │   ├── localStorage/
│   │   │   │   │   │   │   └── liveFeedbackChat/
│   │   │   │   │   │   │       └── operations.ts
│   │   │   │   │   │   ├── pages/
│   │   │   │   │   │   │   ├── LogsIndex/
│   │   │   │   │   │   │   │   ├── LogsContent.tsx
│   │   │   │   │   │   │   │   ├── LogsHead.tsx
│   │   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   │   └── translations.ts
│   │   │   │   │   │   │   ├── SubmissionEditIndex/
│   │   │   │   │   │   │   │   ├── BlockedSubmission.tsx
│   │   │   │   │   │   │   │   ├── ErrorHelper.tsx
│   │   │   │   │   │   │   │   ├── SubmissionEmptyForm.tsx
│   │   │   │   │   │   │   │   ├── SubmissionForm.tsx
│   │   │   │   │   │   │   │   ├── TimeLimitBanner.tsx
│   │   │   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   │   │   ├── ActionButtonsRow.tsx
│   │   │   │   │   │   │   │   │   ├── AutogradingErrorPanel.tsx
│   │   │   │   │   │   │   │   │   ├── ErrorMessages.tsx
│   │   │   │   │   │   │   │   │   ├── ExplanationPanel.tsx
│   │   │   │   │   │   │   │   │   ├── QuestionContent.tsx
│   │   │   │   │   │   │   │   │   ├── SinglePageQuestions.tsx
│   │   │   │   │   │   │   │   │   ├── TabbedViewQuestions.tsx
│   │   │   │   │   │   │   │   │   └── button/
│   │   │   │   │   │   │   │   │       ├── AutogradeSubmissionButton.tsx
│   │   │   │   │   │   │   │   │       ├── ContinueButton.tsx
│   │   │   │   │   │   │   │   │       ├── FinaliseButton.tsx
│   │   │   │   │   │   │   │   │       ├── LiveFeedbackButton.tsx
│   │   │   │   │   │   │   │   │       ├── MarkButton.tsx
│   │   │   │   │   │   │   │   │       ├── PublishButton.tsx
│   │   │   │   │   │   │   │   │       ├── ReevaluateButton.tsx
│   │   │   │   │   │   │   │   │       ├── ResetAnswerButton.tsx
│   │   │   │   │   │   │   │   │       ├── SaveDraftButton.tsx
│   │   │   │   │   │   │   │   │       ├── SaveGradeButton.tsx
│   │   │   │   │   │   │   │   │       ├── StepperButton.tsx
│   │   │   │   │   │   │   │   │       ├── SubmitButton.tsx
│   │   │   │   │   │   │   │   │       ├── SubmitEmptyFormButton.tsx
│   │   │   │   │   │   │   │   │       ├── UnmarkButton.tsx
│   │   │   │   │   │   │   │   │       └── UnsubmitButton.tsx
│   │   │   │   │   │   │   │   ├── index.jsx
│   │   │   │   │   │   │   │   ├── useErrorTranslation.ts
│   │   │   │   │   │   │   │   └── validations/
│   │   │   │   │   │   │   │       ├── AllValidation.tsx
│   │   │   │   │   │   │   │       ├── AttachmentValidation.tsx
│   │   │   │   │   │   │   │       └── types.ts
│   │   │   │   │   │   │   └── SubmissionsIndex/
│   │   │   │   │   │   │       ├── SubmissionsTable.jsx
│   │   │   │   │   │   │       ├── SubmissionsTableRow.jsx
│   │   │   │   │   │   │       ├── __test__/
│   │   │   │   │   │   │       │   └── submissionsTable.test.jsx
│   │   │   │   │   │   │       ├── index.tsx
│   │   │   │   │   │   │       └── translations.js
│   │   │   │   │   │   ├── propTypes.js
│   │   │   │   │   │   ├── reducers/
│   │   │   │   │   │   │   ├── annotations.js
│   │   │   │   │   │   │   ├── answerFlags/
│   │   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   │   ├── answers.js
│   │   │   │   │   │   │   ├── assessment.js
│   │   │   │   │   │   │   ├── attachments.js
│   │   │   │   │   │   │   ├── codaveriFeedbackStatus.js
│   │   │   │   │   │   │   ├── commentForms.js
│   │   │   │   │   │   │   ├── explanations.js
│   │   │   │   │   │   │   ├── grading/
│   │   │   │   │   │   │   │   ├── index.js
│   │   │   │   │   │   │   │   └── types.ts
│   │   │   │   │   │   │   ├── history/
│   │   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   │   ├── index.js
│   │   │   │   │   │   │   ├── liveFeedbackChats/
│   │   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   │   ├── posts.js
│   │   │   │   │   │   │   ├── questions.js
│   │   │   │   │   │   │   ├── questionsFlags.js
│   │   │   │   │   │   │   ├── recorder.js
│   │   │   │   │   │   │   ├── scribing/
│   │   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   │   ├── submission.js
│   │   │   │   │   │   │   ├── submissionFlags.js
│   │   │   │   │   │   │   ├── submissions.js
│   │   │   │   │   │   │   ├── testCases.js
│   │   │   │   │   │   │   └── topics.js
│   │   │   │   │   │   ├── selectors/
│   │   │   │   │   │   │   ├── answerFlags.ts
│   │   │   │   │   │   │   ├── answers.ts
│   │   │   │   │   │   │   ├── assessments.ts
│   │   │   │   │   │   │   ├── attachments.ts
│   │   │   │   │   │   │   ├── codaveriFeedbackStatus.ts
│   │   │   │   │   │   │   ├── comments.ts
│   │   │   │   │   │   │   ├── explanations.ts
│   │   │   │   │   │   │   ├── grading.ts
│   │   │   │   │   │   │   ├── history.ts
│   │   │   │   │   │   │   ├── liveFeedbackChats.ts
│   │   │   │   │   │   │   ├── questionFlags.ts
│   │   │   │   │   │   │   ├── questions.ts
│   │   │   │   │   │   │   ├── submissionFlags.ts
│   │   │   │   │   │   │   ├── submissions.ts
│   │   │   │   │   │   │   └── topics.ts
│   │   │   │   │   │   ├── suggestionTranslations.ts
│   │   │   │   │   │   ├── translations.ts
│   │   │   │   │   │   ├── types.ts
│   │   │   │   │   │   └── utils/
│   │   │   │   │   │       ├── answers.ts
│   │   │   │   │   │       ├── rubrics.ts
│   │   │   │   │   │       └── timer.ts
│   │   │   │   │   ├── submissions/
│   │   │   │   │   │   ├── SubmissionsIndex.tsx
│   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   ├── buttons/
│   │   │   │   │   │   │   │   └── SubmissionsTableButton.tsx
│   │   │   │   │   │   │   ├── misc/
│   │   │   │   │   │   │   │   ├── SubmissionFilter.tsx
│   │   │   │   │   │   │   │   └── SubmissionTabs.tsx
│   │   │   │   │   │   │   └── tables/
│   │   │   │   │   │   │       └── SubmissionsTable.tsx
│   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   ├── selectors.ts
│   │   │   │   │   │   ├── store.ts
│   │   │   │   │   │   └── types.ts
│   │   │   │   │   ├── translations.ts
│   │   │   │   │   └── utils/
│   │   │   │   │       ├── __test__/
│   │   │   │   │       │   └── index.test.js
│   │   │   │   │       ├── index.js
│   │   │   │   │       └── recorderHelper.js
│   │   │   │   ├── container/
│   │   │   │   │   ├── Breadcrumbs/
│   │   │   │   │   │   ├── Breadcrumbs.tsx
│   │   │   │   │   │   ├── Crumb.tsx
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   └── sliders.tsx
│   │   │   │   │   ├── CourseContainer.tsx
│   │   │   │   │   ├── CourseLoader.ts
│   │   │   │   │   ├── Sidebar/
│   │   │   │   │   │   ├── CourseItem.tsx
│   │   │   │   │   │   ├── CourseUserItem.tsx
│   │   │   │   │   │   ├── CourseUserProgress.tsx
│   │   │   │   │   │   ├── LevelRing.tsx
│   │   │   │   │   │   ├── PinSidebarButton.tsx
│   │   │   │   │   │   ├── Sidebar.tsx
│   │   │   │   │   │   ├── SidebarAccordion.tsx
│   │   │   │   │   │   ├── SidebarContainer.tsx
│   │   │   │   │   │   ├── SidebarItem.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   └── unread.ts
│   │   │   │   ├── courses/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── buttons/
│   │   │   │   │   │   │   ├── TodoAccessButton.tsx
│   │   │   │   │   │   │   └── TodoIgnoreButton.tsx
│   │   │   │   │   │   ├── forms/
│   │   │   │   │   │   │   ├── CourseInvitationCodeForm.tsx
│   │   │   │   │   │   │   └── NewCourseForm.tsx
│   │   │   │   │   │   ├── misc/
│   │   │   │   │   │   │   ├── CourseAnnouncements.tsx
│   │   │   │   │   │   │   ├── CourseDisplay.tsx
│   │   │   │   │   │   │   ├── CourseEnrolOptions.tsx
│   │   │   │   │   │   │   ├── CourseInfoBox.tsx
│   │   │   │   │   │   │   ├── CourseNotifications.tsx
│   │   │   │   │   │   │   ├── CourseSuspendedAlert.tsx
│   │   │   │   │   │   │   └── NotificationCard.tsx
│   │   │   │   │   │   └── tables/
│   │   │   │   │   │       └── PendingTodosTable.tsx
│   │   │   │   │   ├── operations.ts
│   │   │   │   │   ├── pages/
│   │   │   │   │   │   ├── CourseShow/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── CoursesIndex/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   └── CoursesNew/
│   │   │   │   │   │       └── index.tsx
│   │   │   │   │   ├── selectors.ts
│   │   │   │   │   ├── store.ts
│   │   │   │   │   └── types.ts
│   │   │   │   ├── discussion/
│   │   │   │   │   └── topics/
│   │   │   │   │       ├── components/
│   │   │   │   │       │   ├── cards/
│   │   │   │   │       │   │   ├── CodaveriCommentCard.tsx
│   │   │   │   │       │   │   ├── CommentCard.tsx
│   │   │   │   │       │   │   └── TopicCard.tsx
│   │   │   │   │       │   ├── fields/
│   │   │   │   │       │   │   └── CommentField.tsx
│   │   │   │   │       │   └── lists/
│   │   │   │   │       │       └── TopicList.tsx
│   │   │   │   │       ├── handles.ts
│   │   │   │   │       ├── operations.ts
│   │   │   │   │       ├── pages/
│   │   │   │   │       │   └── CommentIndex/
│   │   │   │   │       │       └── index.tsx
│   │   │   │   │       ├── selectors.ts
│   │   │   │   │       ├── store.ts
│   │   │   │   │       └── types.ts
│   │   │   │   ├── duplication/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── BulkSelectors.jsx
│   │   │   │   │   │   ├── CourseDropdownMenu.jsx
│   │   │   │   │   │   ├── IndentedCheckbox.jsx
│   │   │   │   │   │   ├── TypeBadge/
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   └── UnpublishedIcon.jsx
│   │   │   │   │   ├── constants.js
│   │   │   │   │   ├── operations.js
│   │   │   │   │   ├── pages/
│   │   │   │   │   │   └── Duplication/
│   │   │   │   │   │       ├── DestinationCourseSelector/
│   │   │   │   │   │       │   ├── InstanceDropdown.tsx
│   │   │   │   │   │       │   ├── NewCourseForm.jsx
│   │   │   │   │   │       │   └── index.jsx
│   │   │   │   │   │       ├── DuplicateAllButton.jsx
│   │   │   │   │   │       ├── DuplicateButton.jsx
│   │   │   │   │   │       ├── DuplicateItemsConfirmation/
│   │   │   │   │   │       │   ├── AchievementsListing.jsx
│   │   │   │   │   │       │   ├── AssessmentsListing.jsx
│   │   │   │   │   │       │   ├── MaterialsListing.jsx
│   │   │   │   │   │       │   ├── SurveyListing.jsx
│   │   │   │   │   │       │   ├── VideosListing.jsx
│   │   │   │   │   │       │   └── index.jsx
│   │   │   │   │   │       ├── ItemsSelector/
│   │   │   │   │   │       │   ├── AchievementsSelector.jsx
│   │   │   │   │   │       │   ├── AssessmentsSelector.jsx
│   │   │   │   │   │       │   ├── MaterialsSelector.jsx
│   │   │   │   │   │       │   ├── SurveysSelector.jsx
│   │   │   │   │   │       │   ├── VideosSelector.jsx
│   │   │   │   │   │       │   └── index.jsx
│   │   │   │   │   │       ├── ItemsSelectorMenu/
│   │   │   │   │   │       │   └── index.jsx
│   │   │   │   │   │       ├── __test__/
│   │   │   │   │   │       │   ├── DuplicateButton.test.tsx
│   │   │   │   │   │       │   └── ObjectDuplication.test.jsx
│   │   │   │   │   │       └── index.jsx
│   │   │   │   │   ├── propTypes.js
│   │   │   │   │   ├── selectors/
│   │   │   │   │   │   ├── destinationCourse.js
│   │   │   │   │   │   └── destinationInstance.ts
│   │   │   │   │   ├── store.js
│   │   │   │   │   └── utils.js
│   │   │   │   ├── enrol-requests/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── buttons/
│   │   │   │   │   │   │   └── PendingEnrolRequestsButtons.tsx
│   │   │   │   │   │   └── tables/
│   │   │   │   │   │       └── EnrolRequestsTable.tsx
│   │   │   │   │   ├── operations.ts
│   │   │   │   │   ├── pages/
│   │   │   │   │   │   └── UserRequests/
│   │   │   │   │   │       └── index.tsx
│   │   │   │   │   ├── selectors.ts
│   │   │   │   │   ├── store.ts
│   │   │   │   │   └── types.ts
│   │   │   │   ├── experience-points/
│   │   │   │   │   ├── ExperiencePointsDetails.tsx
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── ExperiencePointsDownload.tsx
│   │   │   │   │   │   ├── ExperiencePointsFiltering.tsx
│   │   │   │   │   │   ├── ExperiencePointsNumberField.tsx
│   │   │   │   │   │   ├── ExperiencePointsReasonField.tsx
│   │   │   │   │   │   ├── ExperiencePointsTable.tsx
│   │   │   │   │   │   └── ExperiencePointsTableRow.tsx
│   │   │   │   │   ├── disbursement/
│   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   ├── buttons/
│   │   │   │   │   │   │   │   ├── DuplicateButton.tsx
│   │   │   │   │   │   │   │   └── RemoveAllButton.tsx
│   │   │   │   │   │   │   ├── fields/
│   │   │   │   │   │   │   │   └── PointField.tsx
│   │   │   │   │   │   │   ├── forms/
│   │   │   │   │   │   │   │   ├── DisbursementForm.tsx
│   │   │   │   │   │   │   │   ├── FilterForm.tsx
│   │   │   │   │   │   │   │   └── ForumDisbursementForm.tsx
│   │   │   │   │   │   │   └── tables/
│   │   │   │   │   │   │       ├── DisbursementTable.tsx
│   │   │   │   │   │   │       ├── ForumDisbursementTable.tsx
│   │   │   │   │   │   │       └── ForumPostTable.tsx
│   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   ├── pages/
│   │   │   │   │   │   │   ├── ForumDisbursement/
│   │   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   │   └── GeneralDisbursement/
│   │   │   │   │   │   │       └── index.tsx
│   │   │   │   │   │   ├── selectors.ts
│   │   │   │   │   │   ├── store.ts
│   │   │   │   │   │   └── types.ts
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   ├── operations.ts
│   │   │   │   │   ├── selectors.ts
│   │   │   │   │   └── store.ts
│   │   │   │   ├── forum/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── buttons/
│   │   │   │   │   │   │   ├── ForumManagementButtons.tsx
│   │   │   │   │   │   │   ├── ForumTopicManagementButtons.tsx
│   │   │   │   │   │   │   ├── ForumTopicPostEditActionButtons.tsx
│   │   │   │   │   │   │   ├── ForumTopicPostManagementButtons.tsx
│   │   │   │   │   │   │   ├── GenerateReplyButton.tsx
│   │   │   │   │   │   │   ├── HideButton.tsx
│   │   │   │   │   │   │   ├── LockButton.tsx
│   │   │   │   │   │   │   ├── MarkAllAsReadButton.tsx
│   │   │   │   │   │   │   ├── MarkAnswerAndPublishButton.tsx
│   │   │   │   │   │   │   ├── MarkAnswerButton.tsx
│   │   │   │   │   │   │   ├── NextUnreadButton.tsx
│   │   │   │   │   │   │   ├── ReplyButton.tsx
│   │   │   │   │   │   │   ├── SubscribeButton.tsx
│   │   │   │   │   │   │   └── VotePostButton.tsx
│   │   │   │   │   │   ├── cards/
│   │   │   │   │   │   │   ├── PostCard.tsx
│   │   │   │   │   │   │   └── ReplyCard.tsx
│   │   │   │   │   │   ├── forms/
│   │   │   │   │   │   │   ├── ForumForm.tsx
│   │   │   │   │   │   │   ├── ForumTopicForm.tsx
│   │   │   │   │   │   │   └── ForumTopicPostForm.tsx
│   │   │   │   │   │   ├── misc/
│   │   │   │   │   │   │   └── PostCreatorObject.tsx
│   │   │   │   │   │   └── tables/
│   │   │   │   │   │       ├── ForumTable.tsx
│   │   │   │   │   │       └── ForumTopicTable.tsx
│   │   │   │   │   ├── handles.ts
│   │   │   │   │   ├── operations.ts
│   │   │   │   │   ├── pages/
│   │   │   │   │   │   ├── ForumEdit/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── ForumNew/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── ForumShow/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── ForumTopicEdit/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── ForumTopicNew/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── ForumTopicPostNew/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── ForumTopicShow/
│   │   │   │   │   │   │   ├── TopicPostTrees.tsx
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   └── ForumsIndex/
│   │   │   │   │   │       └── index.tsx
│   │   │   │   │   ├── selectors.ts
│   │   │   │   │   ├── store.ts
│   │   │   │   │   ├── translations.ts
│   │   │   │   │   └── types.ts
│   │   │   │   ├── group/
│   │   │   │   │   ├── actions/
│   │   │   │   │   │   ├── categories.js
│   │   │   │   │   │   ├── general.js
│   │   │   │   │   │   ├── groups.js
│   │   │   │   │   │   └── index.js
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── GroupCard.tsx
│   │   │   │   │   │   └── GroupRoleChip.tsx
│   │   │   │   │   ├── constants.js
│   │   │   │   │   ├── forms/
│   │   │   │   │   │   ├── GroupCreationForm.jsx
│   │   │   │   │   │   ├── GroupFormDialog.jsx
│   │   │   │   │   │   └── NameDescriptionForm.jsx
│   │   │   │   │   ├── pages/
│   │   │   │   │   │   ├── GroupIndex/
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── GroupNew/
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   └── GroupShow/
│   │   │   │   │   │       ├── CategoryCard.tsx
│   │   │   │   │   │       ├── GroupManager/
│   │   │   │   │   │       │   ├── ChangeSummaryTable.jsx
│   │   │   │   │   │       │   ├── GroupManager.jsx
│   │   │   │   │   │       │   ├── GroupUserManager.jsx
│   │   │   │   │   │       │   ├── GroupUserManagerList.jsx
│   │   │   │   │   │       │   └── index.js
│   │   │   │   │   │       ├── GroupTableCard.tsx
│   │   │   │   │   │       └── index.jsx
│   │   │   │   │   ├── propTypes.js
│   │   │   │   │   ├── reducers/
│   │   │   │   │   │   ├── groupsDialog.js
│   │   │   │   │   │   ├── groupsFetch.js
│   │   │   │   │   │   └── groupsManage.js
│   │   │   │   │   ├── store.ts
│   │   │   │   │   ├── types.ts
│   │   │   │   │   └── utils/
│   │   │   │   │       ├── groups.js
│   │   │   │   │       └── sort.js
│   │   │   │   ├── helper/
│   │   │   │   │   ├── achievements.ts
│   │   │   │   │   └── index.ts
│   │   │   │   ├── leaderboard/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   └── tables/
│   │   │   │   │   │       └── LeaderboardTable.tsx
│   │   │   │   │   ├── handles.ts
│   │   │   │   │   ├── operations.ts
│   │   │   │   │   ├── pages/
│   │   │   │   │   │   └── LeaderboardIndex/
│   │   │   │   │   │       └── index.tsx
│   │   │   │   │   ├── selectors.ts
│   │   │   │   │   ├── store.ts
│   │   │   │   │   └── types.ts
│   │   │   │   ├── learning-map/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── ConnectionPoint/
│   │   │   │   │   │   │   ├── ConnectionPoint.scss
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── Gate/
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── Node/
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── NodeMenu/
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── UnlockRateDisplay/
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   └── ZoomActionElements/
│   │   │   │   │   │       └── index.jsx
│   │   │   │   │   ├── constants.js
│   │   │   │   │   ├── containers/
│   │   │   │   │   │   ├── ArrowOverlay/
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── Canvas/
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── Dashboard/
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── GateToNodeArrows/
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── LearningMap/
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── Levels/
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   └── NodeToGateArrows/
│   │   │   │   │   │       └── index.jsx
│   │   │   │   │   ├── operations.ts
│   │   │   │   │   ├── propTypes.js
│   │   │   │   │   ├── store.ts
│   │   │   │   │   ├── translations.ts
│   │   │   │   │   └── types.ts
│   │   │   │   ├── lesson-plan/
│   │   │   │   │   ├── constants.js
│   │   │   │   │   ├── containers/
│   │   │   │   │   │   ├── ColumnVisibilityDropdown/
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── EventFormDialog/
│   │   │   │   │   │   │   ├── EventForm.jsx
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── LessonPlanFilter/
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── LessonPlanLayout/
│   │   │   │   │   │   │   ├── EnterEditModeButton.jsx
│   │   │   │   │   │   │   ├── NewEventButton.jsx
│   │   │   │   │   │   │   ├── NewMilestoneButton.jsx
│   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   ├── NewEventButton.test.jsx
│   │   │   │   │   │   │   │   ├── NewMilestoneButton.test.jsx
│   │   │   │   │   │   │   │   └── index.test.jsx
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── LessonPlanNav/
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── MilestoneFormDialog/
│   │   │   │   │   │   │   ├── MilestoneForm.jsx
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   └── TranslatedItemType.tsx
│   │   │   │   │   ├── operations.ts
│   │   │   │   │   ├── pages/
│   │   │   │   │   │   ├── LessonPlanEdit/
│   │   │   │   │   │   │   ├── ItemRow/
│   │   │   │   │   │   │   │   ├── DateCell.jsx
│   │   │   │   │   │   │   │   ├── PublishedCell.jsx
│   │   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   │   ├── MilestoneRow.jsx
│   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   ├── ItemRow.test.jsx
│   │   │   │   │   │   │   │   ├── MilestoneRow.test.jsx
│   │   │   │   │   │   │   │   └── index.test.jsx
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   └── LessonPlanShow/
│   │   │   │   │   │       ├── LessonPlanGroup.jsx
│   │   │   │   │   │       ├── LessonPlanItem/
│   │   │   │   │   │       │   ├── AdminTools.jsx
│   │   │   │   │   │       │   ├── Details/
│   │   │   │   │   │       │   │   ├── Chips.jsx
│   │   │   │   │   │       │   │   └── index.jsx
│   │   │   │   │   │       │   ├── Material.jsx
│   │   │   │   │   │       │   ├── __test__/
│   │   │   │   │   │       │   │   └── AdminTools.test.jsx
│   │   │   │   │   │       │   └── index.jsx
│   │   │   │   │   │       ├── MilestoneAdminTools.jsx
│   │   │   │   │   │       ├── __test__/
│   │   │   │   │   │       │   ├── LessonPlanShow.test.jsx
│   │   │   │   │   │       │   └── MilestoneAdminTools.test.jsx
│   │   │   │   │   │       └── index.jsx
│   │   │   │   │   ├── reducers/
│   │   │   │   │   │   ├── eventForm.js
│   │   │   │   │   │   ├── flags.js
│   │   │   │   │   │   ├── lessonPlan.js
│   │   │   │   │   │   ├── milestoneForm.js
│   │   │   │   │   │   └── utils.js
│   │   │   │   │   ├── store.ts
│   │   │   │   │   └── translations.ts
│   │   │   │   ├── level/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── LevelsTable.tsx
│   │   │   │   │   │   └── LevelsTableRow.tsx
│   │   │   │   │   ├── operations.ts
│   │   │   │   │   ├── pages/
│   │   │   │   │   │   └── LevelsIndex/
│   │   │   │   │   │       ├── LevelsManager.tsx
│   │   │   │   │   │       └── index.tsx
│   │   │   │   │   ├── selector.ts
│   │   │   │   │   ├── store.ts
│   │   │   │   │   └── types.ts
│   │   │   │   ├── material/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   └── MaterialStatusPage.tsx
│   │   │   │   │   ├── files/
│   │   │   │   │   │   ├── DownloadingFilePage.tsx
│   │   │   │   │   │   └── ErrorRetrievingFilePage.tsx
│   │   │   │   │   ├── folders/
│   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   ├── buttons/
│   │   │   │   │   │   │   │   ├── DownloadFolderButton.tsx
│   │   │   │   │   │   │   │   ├── KnowledgeBaseSwitch.tsx
│   │   │   │   │   │   │   │   ├── NewSubfolderButton.tsx
│   │   │   │   │   │   │   │   ├── UploadFilesButton.tsx
│   │   │   │   │   │   │   │   └── WorkbinTableButtons.tsx
│   │   │   │   │   │   │   ├── forms/
│   │   │   │   │   │   │   │   ├── FolderForm.tsx
│   │   │   │   │   │   │   │   ├── MaterialForm.tsx
│   │   │   │   │   │   │   │   └── MaterialUploadForm.tsx
│   │   │   │   │   │   │   ├── misc/
│   │   │   │   │   │   │   │   ├── MaterialEdit.tsx
│   │   │   │   │   │   │   │   ├── MaterialUpload.tsx
│   │   │   │   │   │   │   │   └── MultipleFileInput.tsx
│   │   │   │   │   │   │   └── tables/
│   │   │   │   │   │   │       ├── TableMaterialRow.tsx
│   │   │   │   │   │   │       ├── TableSubfolderRow.tsx
│   │   │   │   │   │   │       └── WorkbinTable.tsx
│   │   │   │   │   │   ├── handles.ts
│   │   │   │   │   │   ├── operations.ts
│   │   │   │   │   │   ├── pages/
│   │   │   │   │   │   │   ├── ErrorRetrievingFolderPage.tsx
│   │   │   │   │   │   │   ├── FolderEdit/
│   │   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   │   ├── FolderNew/
│   │   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   │   └── FolderShow/
│   │   │   │   │   │   │       └── index.tsx
│   │   │   │   │   │   ├── selectors.ts
│   │   │   │   │   │   ├── store.ts
│   │   │   │   │   │   └── types.ts
│   │   │   │   │   └── materialLoader.ts
│   │   │   │   ├── plagiarism/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── AssessmentLinkDialog.tsx
│   │   │   │   │   │   └── AssessmentLinkList.tsx
│   │   │   │   │   ├── constants.ts
│   │   │   │   │   ├── operations.ts
│   │   │   │   │   ├── pages/
│   │   │   │   │   │   └── PlagiarismIndex/
│   │   │   │   │   │       ├── assessments/
│   │   │   │   │   │       │   └── AssessmentsPlagiarismTable.tsx
│   │   │   │   │   │       └── index.tsx
│   │   │   │   │   ├── reducers/
│   │   │   │   │   │   └── assessments.ts
│   │   │   │   │   ├── selectors.ts
│   │   │   │   │   └── store.ts
│   │   │   │   ├── reference-timelines/
│   │   │   │   │   ├── TimelineDesigner.tsx
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── CreateRenameTimelinePrompt.tsx
│   │   │   │   │   │   ├── DayCalendar/
│   │   │   │   │   │   │   ├── DayCalendar.tsx
│   │   │   │   │   │   │   ├── DayColumn.tsx
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   ├── DeleteTimelinePrompt.tsx
│   │   │   │   │   │   ├── HorizontallyDraggable.tsx
│   │   │   │   │   │   ├── HorizontallyResizable.tsx
│   │   │   │   │   │   ├── SeriouslyAnchoredPopup.tsx
│   │   │   │   │   │   ├── SubmitIndicator.tsx
│   │   │   │   │   │   ├── TimeBar/
│   │   │   │   │   │   │   ├── DurationBar.tsx
│   │   │   │   │   │   │   ├── TimeBar.tsx
│   │   │   │   │   │   │   ├── TimeBarHandle.tsx
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   ├── TimePopup/
│   │   │   │   │   │   │   ├── TimePopup.tsx
│   │   │   │   │   │   │   ├── TimePopupForm.tsx
│   │   │   │   │   │   │   ├── TimePopupTopBar.tsx
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   ├── TimelinesOverview/
│   │   │   │   │   │   │   ├── TimelinesOverview.tsx
│   │   │   │   │   │   │   ├── TimelinesOverviewItem.tsx
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   └── TimelinesStack/
│   │   │   │   │   │       ├── AssignableTimeline.tsx
│   │   │   │   │   │       ├── AssignedTimeline.tsx
│   │   │   │   │   │       ├── Timeline.tsx
│   │   │   │   │   │       ├── TimelinesStack.tsx
│   │   │   │   │   │       └── index.ts
│   │   │   │   │   ├── contexts/
│   │   │   │   │   │   ├── LastSavedContext.tsx
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── operations.ts
│   │   │   │   │   ├── selectors.ts
│   │   │   │   │   ├── store.ts
│   │   │   │   │   ├── translations.ts
│   │   │   │   │   ├── types.ts
│   │   │   │   │   ├── utils.ts
│   │   │   │   │   └── views/
│   │   │   │   │       └── DayView/
│   │   │   │   │           ├── DayView.tsx
│   │   │   │   │           ├── ItemsSidebar.tsx
│   │   │   │   │           ├── TimelineSidebarItem.tsx
│   │   │   │   │           └── index.ts
│   │   │   │   ├── scholaistic/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── ScholaisticAsyncContainer.tsx
│   │   │   │   │   │   ├── ScholaisticErrorPage.tsx
│   │   │   │   │   │   └── ScholaisticFramePage.tsx
│   │   │   │   │   ├── handles.ts
│   │   │   │   │   └── pages/
│   │   │   │   │       ├── ScholaisticAssessmentEdit/
│   │   │   │   │       │   ├── index.tsx
│   │   │   │   │       │   ├── loader.ts
│   │   │   │   │       │   └── operations.ts
│   │   │   │   │       ├── ScholaisticAssessmentNew/
│   │   │   │   │       │   ├── index.tsx
│   │   │   │   │       │   └── loader.ts
│   │   │   │   │       ├── ScholaisticAssessmentSubmissionEdit/
│   │   │   │   │       │   ├── index.tsx
│   │   │   │   │       │   └── loader.ts
│   │   │   │   │       ├── ScholaisticAssessmentSubmissionsIndex/
│   │   │   │   │       │   ├── index.tsx
│   │   │   │   │       │   └── loader.ts
│   │   │   │   │       ├── ScholaisticAssessmentView/
│   │   │   │   │       │   ├── index.tsx
│   │   │   │   │       │   └── loader.ts
│   │   │   │   │       ├── ScholaisticAssessmentsIndex/
│   │   │   │   │       │   ├── ActionButtons.tsx
│   │   │   │   │       │   ├── index.tsx
│   │   │   │   │       │   └── loader.ts
│   │   │   │   │       ├── ScholaisticAssistantEdit/
│   │   │   │   │       │   ├── index.tsx
│   │   │   │   │       │   └── loader.ts
│   │   │   │   │       └── ScholaisticAssistantsIndex/
│   │   │   │   │           ├── index.tsx
│   │   │   │   │           └── loader.ts
│   │   │   │   ├── statistics/
│   │   │   │   │   ├── handles.ts
│   │   │   │   │   ├── operations.ts
│   │   │   │   │   ├── pages/
│   │   │   │   │   │   └── StatisticsIndex/
│   │   │   │   │   │       ├── assessments/
│   │   │   │   │   │       │   ├── AssessmentsScoreSummaryDownload.tsx
│   │   │   │   │   │       │   ├── AssessmentsStatistics.tsx
│   │   │   │   │   │       │   └── AssessmentsStatisticsTable.tsx
│   │   │   │   │   │       ├── course/
│   │   │   │   │   │       │   ├── CourseStatistics.tsx
│   │   │   │   │   │       │   ├── StudentPerformanceTable.tsx
│   │   │   │   │   │       │   ├── StudentProgressionChart.tsx
│   │   │   │   │   │       │   └── utils.js
│   │   │   │   │   │       ├── get_help/
│   │   │   │   │   │       │   ├── CourseGetHelpFilter.tsx
│   │   │   │   │   │       │   ├── CourseGetHelpStatistics.tsx
│   │   │   │   │   │       │   └── CourseGetHelpStatisticsTable.tsx
│   │   │   │   │   │       ├── index.tsx
│   │   │   │   │   │       ├── staff/
│   │   │   │   │   │       │   ├── StaffStatistics.tsx
│   │   │   │   │   │       │   └── StaffStatisticsTable.tsx
│   │   │   │   │   │       └── students/
│   │   │   │   │   │           ├── StudentStatisticsTable.tsx
│   │   │   │   │   │           └── StudentsStatistics.tsx
│   │   │   │   │   ├── types.ts
│   │   │   │   │   └── utils/
│   │   │   │   │       ├── parseCourseResponse.js
│   │   │   │   │       ├── parseStaffResponse.js
│   │   │   │   │       └── parseStudentsResponse.js
│   │   │   │   ├── stories/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── CikgoChatsPage.tsx
│   │   │   │   │   │   ├── CikgoErrorPage.tsx
│   │   │   │   │   │   ├── CikgoFramePage.tsx
│   │   │   │   │   │   ├── CikgoSidebarItems.tsx
│   │   │   │   │   │   └── LearnRedirect.tsx
│   │   │   │   │   └── pages/
│   │   │   │   │       ├── LearnPage.tsx
│   │   │   │   │       └── MissionControlPage.tsx
│   │   │   │   ├── survey/
│   │   │   │   │   ├── __test__/
│   │   │   │   │   │   └── index.test.tsx
│   │   │   │   │   ├── actions/
│   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   └── responses.test.ts
│   │   │   │   │   │   ├── questions.js
│   │   │   │   │   │   ├── responses.js
│   │   │   │   │   │   ├── sections.js
│   │   │   │   │   │   └── surveys.js
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── Dialogs.jsx
│   │   │   │   │   │   └── OptionsListItem.jsx
│   │   │   │   │   ├── constants.js
│   │   │   │   │   ├── containers/
│   │   │   │   │   │   ├── QuestionFormDialogue/
│   │   │   │   │   │   │   ├── QuestionForm.jsx
│   │   │   │   │   │   │   ├── QuestionFormDeletedOptions.jsx
│   │   │   │   │   │   │   ├── QuestionFormOption.jsx
│   │   │   │   │   │   │   ├── QuestionFormOptions.jsx
│   │   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   │   └── ImageField.jsx
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── RespondButton/
│   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   └── index.test.jsx
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── ResponseForm/
│   │   │   │   │   │   │   ├── ResponseAnswer.jsx
│   │   │   │   │   │   │   ├── ResponseSection.jsx
│   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   └── index.test.jsx
│   │   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   │   ├── MultipleChoiceOptionsField.jsx
│   │   │   │   │   │   │   │   └── MultipleResponseOptionsField.jsx
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── SectionFormDialogue/
│   │   │   │   │   │   │   ├── SectionForm.jsx
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── SurveyFormDialogue/
│   │   │   │   │   │   │   ├── SurveyForm.jsx
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── SurveyLayout/
│   │   │   │   │   │   │   ├── AdminMenu.jsx
│   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   ├── AdminMenu.test.jsx
│   │   │   │   │   │   │   │   └── index.test.jsx
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   └── UnsubmitButton.jsx
│   │   │   │   │   ├── handles.ts
│   │   │   │   │   ├── pages/
│   │   │   │   │   │   ├── ResponseEdit/
│   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   └── index.test.jsx
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── ResponseIndex/
│   │   │   │   │   │   │   ├── RemindButton.jsx
│   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   ├── RemindButton.test.tsx
│   │   │   │   │   │   │   │   └── index.test.jsx
│   │   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   │   └── translations.js
│   │   │   │   │   │   ├── ResponseShow/
│   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   └── index.test.jsx
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── SurveyIndex/
│   │   │   │   │   │   │   ├── NewSurveyButton.jsx
│   │   │   │   │   │   │   ├── SurveyBadges.jsx
│   │   │   │   │   │   │   ├── SurveysTable.jsx
│   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   └── NewSurveyButton.test.jsx
│   │   │   │   │   │   │   └── index.jsx
│   │   │   │   │   │   ├── SurveyResults/
│   │   │   │   │   │   │   ├── OptionsQuestionResults.jsx
│   │   │   │   │   │   │   ├── ResultsQuestion.jsx
│   │   │   │   │   │   │   ├── ResultsSection.jsx
│   │   │   │   │   │   │   ├── TextResponseResults.jsx
│   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   ├── ResultsQuestion.test.tsx
│   │   │   │   │   │   │   │   └── index.test.jsx
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   └── SurveyShow/
│   │   │   │   │   │       ├── DownloadResponsesButton.jsx
│   │   │   │   │   │       ├── NewSectionButton.jsx
│   │   │   │   │   │       ├── Section/
│   │   │   │   │   │       │   ├── DeleteSectionButton.jsx
│   │   │   │   │   │       │   ├── EditSectionButton.jsx
│   │   │   │   │   │       │   ├── MoveDownButton.jsx
│   │   │   │   │   │       │   ├── MoveUpButton.jsx
│   │   │   │   │   │       │   ├── NewQuestionButton.jsx
│   │   │   │   │   │       │   ├── Question.jsx
│   │   │   │   │   │       │   ├── QuestionCard.jsx
│   │   │   │   │   │       │   ├── __test__/
│   │   │   │   │   │       │   │   ├── DeleteSectionButton.test.tsx
│   │   │   │   │   │       │   │   ├── EditSectionButton.test.jsx
│   │   │   │   │   │       │   │   ├── MoveDownButton.test.tsx
│   │   │   │   │   │       │   │   ├── MoveUpButton.test.jsx
│   │   │   │   │   │       │   │   └── NewQuestionButton.test.jsx
│   │   │   │   │   │       │   └── index.jsx
│   │   │   │   │   │       ├── SurveyDetails.jsx
│   │   │   │   │   │       ├── __test__/
│   │   │   │   │   │       │   ├── DownloadResponsesButton.test.tsx
│   │   │   │   │   │       │   └── NewSectionButton.test.jsx
│   │   │   │   │   │       └── index.jsx
│   │   │   │   │   ├── propTypes.js
│   │   │   │   │   ├── reducers/
│   │   │   │   │   │   ├── questionForm.js
│   │   │   │   │   │   ├── responseForm.js
│   │   │   │   │   │   ├── responses.js
│   │   │   │   │   │   ├── results.js
│   │   │   │   │   │   ├── section.js
│   │   │   │   │   │   ├── sectionForm.js
│   │   │   │   │   │   ├── survey.js
│   │   │   │   │   │   ├── surveyForm.js
│   │   │   │   │   │   ├── surveys.js
│   │   │   │   │   │   └── surveysFlags.js
│   │   │   │   │   ├── store.ts
│   │   │   │   │   ├── translations.js
│   │   │   │   │   └── utils/
│   │   │   │   │       ├── __test__/
│   │   │   │   │       │   └── index.test.js
│   │   │   │   │       └── index.js
│   │   │   │   ├── translations.ts
│   │   │   │   ├── user-email-subscriptions/
│   │   │   │   │   ├── UserEmailSubscriptions.tsx
│   │   │   │   │   ├── UserEmailSubscriptionsTable.jsx
│   │   │   │   │   ├── __test__/
│   │   │   │   │   │   └── index.test.jsx
│   │   │   │   │   ├── constants.js
│   │   │   │   │   ├── operations.ts
│   │   │   │   │   ├── store.ts
│   │   │   │   │   ├── translations.ts
│   │   │   │   │   └── types.ts
│   │   │   │   ├── user-invitations/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── buttons/
│   │   │   │   │   │   │   ├── InvitationActionButtons.tsx
│   │   │   │   │   │   │   ├── RegistrationCodeButton.tsx
│   │   │   │   │   │   │   ├── ResendAllInvitationsButton.tsx
│   │   │   │   │   │   │   └── UploadFileButton.tsx
│   │   │   │   │   │   ├── forms/
│   │   │   │   │   │   │   ├── IndividualInvitation.tsx
│   │   │   │   │   │   │   ├── IndividualInvitations.tsx
│   │   │   │   │   │   │   ├── IndividualInviteForm.tsx
│   │   │   │   │   │   │   └── InviteUsersFileUploadForm.tsx
│   │   │   │   │   │   ├── misc/
│   │   │   │   │   │   │   ├── InvitationResultDialog.tsx
│   │   │   │   │   │   │   └── InvitationsBarChart.tsx
│   │   │   │   │   │   └── tables/
│   │   │   │   │   │       ├── InvitationResultInvitationsTable.tsx
│   │   │   │   │   │       ├── InvitationResultUsersTable.tsx
│   │   │   │   │   │       └── UserInvitationsTable.tsx
│   │   │   │   │   ├── operations.ts
│   │   │   │   │   ├── pages/
│   │   │   │   │   │   ├── InvitationsIndex/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── InviteUsers/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── InviteUsersFileUpload/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   └── InviteUsersRegistrationCode/
│   │   │   │   │   │       └── index.tsx
│   │   │   │   │   ├── selectors.ts
│   │   │   │   │   ├── store.ts
│   │   │   │   │   ├── translations.ts
│   │   │   │   │   └── types.ts
│   │   │   │   ├── user-notification/
│   │   │   │   │   ├── PopupNotifier.tsx
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── AchievementGainedPopup.tsx
│   │   │   │   │   │   ├── LevelReachedPopup.tsx
│   │   │   │   │   │   ├── PopupDialog.tsx
│   │   │   │   │   │   └── __test__/
│   │   │   │   │   │       └── LevelReachedPopup.test.tsx
│   │   │   │   │   ├── operations.ts
│   │   │   │   │   └── translations.ts
│   │   │   │   ├── users/
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── buttons/
│   │   │   │   │   │   │   ├── PointManagementButtons.tsx
│   │   │   │   │   │   │   └── UserManagementButtons.tsx
│   │   │   │   │   │   ├── misc/
│   │   │   │   │   │   │   ├── PersonalTimeEditor.tsx
│   │   │   │   │   │   │   ├── SelectCourseUser.tsx
│   │   │   │   │   │   │   ├── UpgradeToStaff.tsx
│   │   │   │   │   │   │   ├── UserProfileAchievements.tsx
│   │   │   │   │   │   │   ├── UserProfileCard.scss
│   │   │   │   │   │   │   ├── UserProfileCard.tsx
│   │   │   │   │   │   │   ├── UserProfileCardStats.tsx
│   │   │   │   │   │   │   ├── UserProfileSkills.tsx
│   │   │   │   │   │   │   └── __test__/
│   │   │   │   │   │   │       └── UserProfileCard.test.tsx
│   │   │   │   │   │   ├── navigation/
│   │   │   │   │   │   │   └── UserManagementTabs.tsx
│   │   │   │   │   │   └── tables/
│   │   │   │   │   │       ├── ManageUsersTable/
│   │   │   │   │   │       │   ├── ActiveTableToolbar.tsx
│   │   │   │   │   │       │   ├── AlgorithmMenu.tsx
│   │   │   │   │   │       │   ├── BulkActionsButton.tsx
│   │   │   │   │   │       │   ├── BulkAssignTimelineMenu.tsx
│   │   │   │   │   │       │   ├── PhantomSwitch.tsx
│   │   │   │   │   │       │   ├── RoleMenu.tsx
│   │   │   │   │   │       │   ├── TimelineMenu.tsx
│   │   │   │   │   │       │   ├── UserNameField.tsx
│   │   │   │   │   │       │   └── index.tsx
│   │   │   │   │   │       └── PersonalTimesTable.tsx
│   │   │   │   │   ├── handles.ts
│   │   │   │   │   ├── operations.ts
│   │   │   │   │   ├── pages/
│   │   │   │   │   │   ├── ExperiencePointsRecords/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── ManageStaff/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── ManageStudents/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── PersonalTimes/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── PersonalTimesShow/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── UserShow/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── UserStatistics/
│   │   │   │   │   │   │   ├── LearningRateRecords/
│   │   │   │   │   │   │   │   ├── LearningRateRecordsChart.tsx
│   │   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   └── UsersIndex/
│   │   │   │   │   │       └── index.tsx
│   │   │   │   │   ├── selectors.ts
│   │   │   │   │   ├── store.ts
│   │   │   │   │   ├── translations.ts
│   │   │   │   │   └── types.ts
│   │   │   │   ├── video/
│   │   │   │   │   ├── attemptLoader.ts
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── buttons/
│   │   │   │   │   │   │   ├── VideoManagementButtons.tsx
│   │   │   │   │   │   │   └── WatchVideoButton.tsx
│   │   │   │   │   │   ├── forms/
│   │   │   │   │   │   │   └── VideoForm.tsx
│   │   │   │   │   │   ├── misc/
│   │   │   │   │   │   │   ├── VideoBadges.tsx
│   │   │   │   │   │   │   └── VideoTabs.tsx
│   │   │   │   │   │   └── tables/
│   │   │   │   │   │       └── VideoTable.tsx
│   │   │   │   │   ├── handles.ts
│   │   │   │   │   ├── operations.ts
│   │   │   │   │   ├── pages/
│   │   │   │   │   │   ├── VideoEdit/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── VideoNew/
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   ├── VideoShow/
│   │   │   │   │   │   │   ├── VideoDetails.tsx
│   │   │   │   │   │   │   ├── VideoPlayerWithStore.jsx
│   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   └── VideosIndex/
│   │   │   │   │   │       └── index.tsx
│   │   │   │   │   ├── selectors.ts
│   │   │   │   │   ├── store.ts
│   │   │   │   │   ├── submission/
│   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   └── store.test.js
│   │   │   │   │   │   ├── actions/
│   │   │   │   │   │   │   ├── __test__/
│   │   │   │   │   │   │   │   └── video.test.js
│   │   │   │   │   │   │   ├── discussion.js
│   │   │   │   │   │   │   └── video.js
│   │   │   │   │   │   ├── components/
│   │   │   │   │   │   │   └── tables/
│   │   │   │   │   │   │       └── VideoSubmissionsTable.tsx
│   │   │   │   │   │   ├── containers/
│   │   │   │   │   │   │   ├── Charts/
│   │   │   │   │   │   │   │   ├── HeatMap.jsx
│   │   │   │   │   │   │   │   └── ProgressGraph.jsx
│   │   │   │   │   │   │   ├── Discussion.jsx
│   │   │   │   │   │   │   ├── Discussion.scss
│   │   │   │   │   │   │   ├── DiscussionElements/
│   │   │   │   │   │   │   │   ├── Controls.jsx
│   │   │   │   │   │   │   │   ├── EditPostContainer.jsx
│   │   │   │   │   │   │   │   ├── Editor.jsx
│   │   │   │   │   │   │   │   ├── NewPostContainer.jsx
│   │   │   │   │   │   │   │   ├── NewReplyContainer.jsx
│   │   │   │   │   │   │   │   ├── PostContainer.jsx
│   │   │   │   │   │   │   │   ├── PostMenu.jsx
│   │   │   │   │   │   │   │   ├── PostPresentation.jsx
│   │   │   │   │   │   │   │   ├── Reply.jsx
│   │   │   │   │   │   │   │   └── Topic.jsx
│   │   │   │   │   │   │   ├── Statistics.jsx
│   │   │   │   │   │   │   ├── Statistics.scss
│   │   │   │   │   │   │   ├── Submission.jsx
│   │   │   │   │   │   │   ├── VideoControls/
│   │   │   │   │   │   │   │   ├── CaptionsButton.jsx
│   │   │   │   │   │   │   │   ├── NextVideoButton.jsx
│   │   │   │   │   │   │   │   ├── PlayBackRateSelector.jsx
│   │   │   │   │   │   │   │   ├── PlayButton.jsx
│   │   │   │   │   │   │   │   ├── VideoPlayerSlider.jsx
│   │   │   │   │   │   │   │   ├── VideoTimestamp.jsx
│   │   │   │   │   │   │   │   ├── VolumeButton.jsx
│   │   │   │   │   │   │   │   ├── VolumeSlider.jsx
│   │   │   │   │   │   │   │   └── index.js
│   │   │   │   │   │   │   ├── VideoPlayer.jsx
│   │   │   │   │   │   │   └── VideoPlayer.scss
│   │   │   │   │   │   ├── pages/
│   │   │   │   │   │   │   ├── VideoSubmissionEdit/
│   │   │   │   │   │   │   │   ├── SubmissionEditWithStore.jsx
│   │   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   │   ├── VideoSubmissionShow/
│   │   │   │   │   │   │   │   ├── StatisticsWithStore.jsx
│   │   │   │   │   │   │   │   └── index.tsx
│   │   │   │   │   │   │   └── VideoSubmissionsIndex/
│   │   │   │   │   │   │       └── index.tsx
│   │   │   │   │   │   ├── reducers/
│   │   │   │   │   │   │   ├── discussion.js
│   │   │   │   │   │   │   ├── index.js
│   │   │   │   │   │   │   ├── oldSessions.js
│   │   │   │   │   │   │   └── video.js
│   │   │   │   │   │   ├── selectors/
│   │   │   │   │   │   │   └── discussion.js
│   │   │   │   │   │   ├── store.js
│   │   │   │   │   │   └── translations.js
│   │   │   │   │   └── types.ts
│   │   │   │   └── video-submissions/
│   │   │   │       ├── components/
│   │   │   │       │   └── tables/
│   │   │   │       │       └── UserVideoSubmissionTable.tsx
│   │   │   │       ├── operations.ts
│   │   │   │       └── pages/
│   │   │   │           └── UserVideoSubmissionsIndex/
│   │   │   │               └── index.tsx
│   │   │   ├── system/
│   │   │   │   └── admin/
│   │   │   │       ├── admin/
│   │   │   │       │   ├── AdminNavigator.tsx
│   │   │   │       │   ├── components/
│   │   │   │       │   │   ├── buttons/
│   │   │   │       │   │   │   ├── CoursesButtons.tsx
│   │   │   │       │   │   │   ├── InstancesButtons.tsx
│   │   │   │       │   │   │   └── UsersButtons.tsx
│   │   │   │       │   │   ├── forms/
│   │   │   │       │   │   │   └── InstanceForm.tsx
│   │   │   │       │   │   ├── misc/
│   │   │   │       │   │   │   └── SystemGetHelpFilter.tsx
│   │   │   │       │   │   └── tables/
│   │   │   │       │   │       ├── CoursesTable.tsx
│   │   │   │       │   │       ├── InstancesTable/
│   │   │   │       │   │       │   ├── InstanceField.tsx
│   │   │   │       │   │       │   └── index.tsx
│   │   │   │       │   │       ├── SystemGetHelpActivityTable.tsx
│   │   │   │       │   │       └── UsersTable.tsx
│   │   │   │       │   ├── operations.ts
│   │   │   │       │   ├── pages/
│   │   │   │       │   │   ├── AnnouncementsIndex.tsx
│   │   │   │       │   │   ├── CoursesIndex.tsx
│   │   │   │       │   │   ├── InstanceNew.tsx
│   │   │   │       │   │   ├── InstancesIndex.tsx
│   │   │   │       │   │   ├── SystemGetHelpActivityIndex.tsx
│   │   │   │       │   │   └── UsersIndex.tsx
│   │   │   │       │   ├── selectors.ts
│   │   │   │       │   ├── store.ts
│   │   │   │       │   └── types.ts
│   │   │   │       ├── components/
│   │   │   │       │   └── AdminNavigablePage.tsx
│   │   │   │       └── instance/
│   │   │   │           └── instance/
│   │   │   │               ├── InstanceAdminNavigator.tsx
│   │   │   │               ├── components/
│   │   │   │               │   ├── buttons/
│   │   │   │               │   │   ├── InvitationActionButtons.tsx
│   │   │   │               │   │   ├── PendingRoleRequestsButtons.tsx
│   │   │   │               │   │   ├── ResendAllInvitationsButton.tsx
│   │   │   │               │   │   └── UsersButtons.tsx
│   │   │   │               │   ├── forms/
│   │   │   │               │   │   ├── IndividualInvitation.tsx
│   │   │   │               │   │   ├── IndividualInvitations.tsx
│   │   │   │               │   │   ├── IndividualInviteForm.tsx
│   │   │   │               │   │   ├── InstanceUserRoleRequestForm.tsx
│   │   │   │               │   │   └── RejectWithMessageForm.tsx
│   │   │   │               │   ├── misc/
│   │   │   │               │   │   ├── InstanceGetHelpFilter.tsx
│   │   │   │               │   │   └── InvitationResultDialog.tsx
│   │   │   │               │   ├── navigation/
│   │   │   │               │   │   └── InstanceUsersTabs.tsx
│   │   │   │               │   └── tables/
│   │   │   │               │       ├── InstanceGetHelpActivityTable.tsx
│   │   │   │               │       ├── InstanceUserRoleRequestsTable.tsx
│   │   │   │               │       ├── InvitationResultInvitationsTable.tsx
│   │   │   │               │       ├── InvitationResultUsersTable.tsx
│   │   │   │               │       ├── UserInvitationsTable.tsx
│   │   │   │               │       ├── UsersTable.tsx
│   │   │   │               │       └── __test__/
│   │   │   │               │           └── InstanceUserRoleRequestsTable.test.tsx
│   │   │   │               ├── operations.ts
│   │   │   │               ├── pages/
│   │   │   │               │   ├── InstanceAnnouncementsIndex.tsx
│   │   │   │               │   ├── InstanceComponentsIndex.tsx
│   │   │   │               │   ├── InstanceCoursesIndex.tsx
│   │   │   │               │   ├── InstanceGetHelpActivityIndex.tsx
│   │   │   │               │   ├── InstanceUserRoleRequestsIndex.tsx
│   │   │   │               │   ├── InstanceUsersIndex.tsx
│   │   │   │               │   ├── InstanceUsersInvitations.tsx
│   │   │   │               │   └── InstanceUsersInvite.tsx
│   │   │   │               ├── selectors.ts
│   │   │   │               ├── store.ts
│   │   │   │               └── types.ts
│   │   │   ├── user/
│   │   │   │   ├── AccountSettings/
│   │   │   │   │   ├── AccountSettingsForm.tsx
│   │   │   │   │   └── index.tsx
│   │   │   │   ├── components/
│   │   │   │   │   ├── AddEmailSubsection.tsx
│   │   │   │   │   └── EmailsList.tsx
│   │   │   │   ├── operations.ts
│   │   │   │   └── translations.ts
│   │   │   └── users/
│   │   │       ├── components/
│   │   │       │   ├── Widget.tsx
│   │   │       │   └── tables/
│   │   │       │       ├── CoursesTable.tsx
│   │   │       │       ├── InstancesTable.tsx
│   │   │       │       └── __test__/
│   │   │       │           └── InstancesTable.test.tsx
│   │   │       ├── operations.ts
│   │   │       ├── pages/
│   │   │       │   ├── ConfirmEmailPage.tsx
│   │   │       │   ├── ForgotPasswordLandingPage.tsx
│   │   │       │   ├── ForgotPasswordPage.tsx
│   │   │       │   ├── ResendConfirmationEmailLandingPage.tsx
│   │   │       │   ├── ResendConfirmationEmailPage.tsx
│   │   │       │   ├── ResetPasswordPage.tsx
│   │   │       │   ├── SignUpLandingPage.tsx
│   │   │       │   ├── SignUpPage.tsx
│   │   │       │   ├── UserShow.tsx
│   │   │       │   └── __test__/
│   │   │       │       └── UserShow.test.tsx
│   │   │       ├── selectors.ts
│   │   │       ├── store.ts
│   │   │       ├── translations.ts
│   │   │       ├── types.ts
│   │   │       └── validations.ts
│   │   ├── declaration.d.ts
│   │   ├── index.tsx
│   │   ├── lib/
│   │   │   ├── actions/
│   │   │   │   └── index.js
│   │   │   ├── components/
│   │   │   │   ├── core/
│   │   │   │   │   ├── AvatarSelector.tsx
│   │   │   │   │   ├── AvatarWithLabel.tsx
│   │   │   │   │   ├── BarChart.jsx
│   │   │   │   │   ├── BetaChip.tsx
│   │   │   │   │   ├── CourseUserTypeFragment.tsx
│   │   │   │   │   ├── CourseUserTypeTabs.tsx
│   │   │   │   │   ├── CustomTooltip.tsx
│   │   │   │   │   ├── DescriptionCard.tsx
│   │   │   │   │   ├── ErrorText.jsx
│   │   │   │   │   ├── Expandable.tsx
│   │   │   │   │   ├── ExpandableCode.tsx
│   │   │   │   │   ├── ExperimentalChip.tsx
│   │   │   │   │   ├── Hint.tsx
│   │   │   │   │   ├── ImageCropper/
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   └── utils.ts
│   │   │   │   │   ├── InfoLabel.tsx
│   │   │   │   │   ├── LinearProgressWithLabel.tsx
│   │   │   │   │   ├── Link.tsx
│   │   │   │   │   ├── LoadingEllipsis.tsx
│   │   │   │   │   ├── LoadingIndicator.tsx
│   │   │   │   │   ├── LoadingOverlay.tsx
│   │   │   │   │   ├── Note.tsx
│   │   │   │   │   ├── NotificationBar.jsx
│   │   │   │   │   ├── PopupMenu.tsx
│   │   │   │   │   ├── Thumbnail.jsx
│   │   │   │   │   ├── UserHTMLText.tsx
│   │   │   │   │   ├── __test__/
│   │   │   │   │   │   ├── ErrorText.test.tsx
│   │   │   │   │   │   ├── LoadingIndicator.test.tsx
│   │   │   │   │   │   └── __snapshots__/
│   │   │   │   │   │       ├── ErrorText.test.tsx.snap
│   │   │   │   │   │       └── LoadingIndicator.test.tsx.snap
│   │   │   │   │   ├── buttons/
│   │   │   │   │   │   ├── AcceptButton.tsx
│   │   │   │   │   │   ├── AddButton.tsx
│   │   │   │   │   │   ├── Checkbox.tsx
│   │   │   │   │   │   ├── DeleteButton.tsx
│   │   │   │   │   │   ├── DownloadButton.tsx
│   │   │   │   │   │   ├── EditButton.tsx
│   │   │   │   │   │   ├── EmailButton.tsx
│   │   │   │   │   │   ├── IconRadio.tsx
│   │   │   │   │   │   ├── RadioButton.tsx
│   │   │   │   │   │   ├── SaveButton.tsx
│   │   │   │   │   │   └── __test__/
│   │   │   │   │   │       ├── DeleteButton.test.tsx
│   │   │   │   │   │       ├── EditButton.test.tsx
│   │   │   │   │   │       └── __snapshots__/
│   │   │   │   │   │           ├── DeleteButton.test.tsx.snap
│   │   │   │   │   │           └── EditButton.test.tsx.snap
│   │   │   │   │   ├── charts/
│   │   │   │   │   │   ├── GeneralChart.tsx
│   │   │   │   │   │   ├── LineChart.tsx
│   │   │   │   │   │   └── emptyChartPlugin.ts
│   │   │   │   │   ├── dialogs/
│   │   │   │   │   │   ├── ConfirmationDialog.jsx
│   │   │   │   │   │   ├── ImageCropDialog.tsx
│   │   │   │   │   │   ├── Prompt.tsx
│   │   │   │   │   │   └── RailsConfirmationDialog.jsx
│   │   │   │   │   ├── fields/
│   │   │   │   │   │   ├── AceEditor.css
│   │   │   │   │   │   ├── CAPTCHAField.tsx
│   │   │   │   │   │   ├── CKEditor.css
│   │   │   │   │   │   ├── CKEditorField.tsx
│   │   │   │   │   │   ├── CKEditorRichText.tsx
│   │   │   │   │   │   ├── DateTimePicker.jsx
│   │   │   │   │   │   ├── EditorField.tsx
│   │   │   │   │   │   ├── NumberTextField.tsx
│   │   │   │   │   │   ├── PasswordTextField.tsx
│   │   │   │   │   │   ├── SearchField.tsx
│   │   │   │   │   │   ├── SwitchableTextField.tsx
│   │   │   │   │   │   └── TextField.tsx
│   │   │   │   │   ├── indicators/
│   │   │   │   │   │   └── SavingIndicator/
│   │   │   │   │   │       └── index.tsx
│   │   │   │   │   └── layouts/
│   │   │   │   │       ├── Accordion.tsx
│   │   │   │   │       ├── BackendPagination.tsx
│   │   │   │   │       ├── Banner.tsx
│   │   │   │   │       ├── ContactableErrorAlert.tsx
│   │   │   │   │       ├── ContextualErrorPage.tsx
│   │   │   │   │       ├── DataTable.jsx
│   │   │   │   │       ├── Footer.tsx
│   │   │   │   │       ├── MarkdownPage.tsx
│   │   │   │   │       ├── Page.tsx
│   │   │   │   │       ├── Pagination.tsx
│   │   │   │   │       ├── Section.tsx
│   │   │   │   │       ├── Subsection.tsx
│   │   │   │   │       ├── SummaryCard.tsx
│   │   │   │   │       ├── TableContainer.tsx
│   │   │   │   │       └── layout.scss
│   │   │   │   ├── extensions/
│   │   │   │   │   ├── CustomBadge.tsx
│   │   │   │   │   ├── CustomSlider.tsx
│   │   │   │   │   ├── PersonalStartEndTime.tsx
│   │   │   │   │   ├── PersonalTimeBooleanIcon.tsx
│   │   │   │   │   ├── StackedBadges.tsx
│   │   │   │   │   └── conditions/
│   │   │   │   │       ├── AnyCondition.ts
│   │   │   │   │       ├── ConditionRow.tsx
│   │   │   │   │       ├── ConditionsManager.tsx
│   │   │   │   │       ├── conditions/
│   │   │   │   │       │   ├── AchievementCondition.tsx
│   │   │   │   │       │   ├── AssessmentCondition.tsx
│   │   │   │   │       │   ├── LevelCondition.tsx
│   │   │   │   │       │   ├── ScholaisticAssessmentCondition.tsx
│   │   │   │   │       │   └── SurveyCondition.tsx
│   │   │   │   │       ├── operations.ts
│   │   │   │   │       ├── specifiers.ts
│   │   │   │   │       └── translations.ts
│   │   │   │   ├── form/
│   │   │   │   │   ├── Form.tsx
│   │   │   │   │   ├── FormDialogue.jsx
│   │   │   │   │   ├── dialog/
│   │   │   │   │   │   └── FormDialog.tsx
│   │   │   │   │   └── fields/
│   │   │   │   │       ├── AutoCompleteField.jsx
│   │   │   │   │       ├── CheckboxField.tsx
│   │   │   │   │       ├── DataTableInlineEditable/
│   │   │   │   │       │   └── TextField.tsx
│   │   │   │   │       ├── DateTimePickerField.jsx
│   │   │   │   │       ├── EditorField.jsx
│   │   │   │   │       ├── MultiSelectField.jsx
│   │   │   │   │       ├── RichTextField.jsx
│   │   │   │   │       ├── SelectField.jsx
│   │   │   │   │       ├── SingleFileInput/
│   │   │   │   │       │   ├── BadgePreview.jsx
│   │   │   │   │       │   ├── DeleteButton.jsx
│   │   │   │   │       │   ├── FilePreview.jsx
│   │   │   │   │       │   ├── ImagePreview.jsx
│   │   │   │   │       │   ├── __test__/
│   │   │   │   │       │   │   ├── BadgePreview.test.js
│   │   │   │   │       │   │   ├── ImagePreview.test.js
│   │   │   │   │       │   │   └── index.test.js
│   │   │   │   │       │   ├── index.jsx
│   │   │   │   │       │   └── translations.js
│   │   │   │   │       ├── TextField.tsx
│   │   │   │   │       ├── ToggleField.jsx
│   │   │   │   │       └── utils/
│   │   │   │   │           ├── mapError.js
│   │   │   │   │           └── propsAreEqual.js
│   │   │   │   ├── icons/
│   │   │   │   │   ├── GhostIcon.tsx
│   │   │   │   │   └── PointerIcon.tsx
│   │   │   │   ├── navigation/
│   │   │   │   │   ├── AdminPopupMenuList.tsx
│   │   │   │   │   ├── BrandingHead.tsx
│   │   │   │   │   ├── CourseSwitcherPopupMenu.tsx
│   │   │   │   │   ├── UserPopupMenuList.tsx
│   │   │   │   │   └── withRouter.jsx
│   │   │   │   ├── table/
│   │   │   │   │   ├── MuiTableAdapter/
│   │   │   │   │   │   ├── MuiFilterMenu.tsx
│   │   │   │   │   │   ├── MuiFilterMenuItem.tsx
│   │   │   │   │   │   ├── MuiTable.tsx
│   │   │   │   │   │   ├── MuiTableBody.tsx
│   │   │   │   │   │   ├── MuiTableHeader.tsx
│   │   │   │   │   │   ├── MuiTablePagination.tsx
│   │   │   │   │   │   ├── MuiTableRow.tsx
│   │   │   │   │   │   ├── MuiTableRowSelector.tsx
│   │   │   │   │   │   ├── MuiTableToolbar.tsx
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   └── translations.ts
│   │   │   │   │   ├── Table.tsx
│   │   │   │   │   ├── TanStackTableBuilder/
│   │   │   │   │   │   ├── columnsBuilder.ts
│   │   │   │   │   │   ├── csvGenerator.ts
│   │   │   │   │   │   ├── customFlexRender.ts
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   └── useTanStackTableBuilder.tsx
│   │   │   │   │   ├── adapters/
│   │   │   │   │   │   ├── Body.ts
│   │   │   │   │   │   ├── Filter.ts
│   │   │   │   │   │   ├── Handlers.ts
│   │   │   │   │   │   ├── Header.ts
│   │   │   │   │   │   ├── Pagination.ts
│   │   │   │   │   │   ├── RowSelector.ts
│   │   │   │   │   │   ├── Sort.ts
│   │   │   │   │   │   ├── Table.ts
│   │   │   │   │   │   ├── Toolbar.ts
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── builder/
│   │   │   │   │   │   ├── ColumnTemplate.ts
│   │   │   │   │   │   ├── TableTemplate.ts
│   │   │   │   │   │   ├── buildColumns.ts
│   │   │   │   │   │   ├── featureTemplates.ts
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   └── utils.ts
│   │   │   │   └── wrappers/
│   │   │   │       ├── AttributionsProvider.tsx
│   │   │   │       ├── AuthProvider.tsx
│   │   │   │       ├── ErrorBoundary.tsx
│   │   │   │       ├── FooterProvider.tsx
│   │   │   │       ├── I18nProvider.tsx
│   │   │   │       ├── Preload.tsx
│   │   │   │       ├── Providers.tsx
│   │   │   │       ├── RollbarWrapper.tsx
│   │   │   │       ├── StoreProvider.tsx
│   │   │   │       ├── ThemeProvider.tsx
│   │   │   │       └── ToastProvider.tsx
│   │   │   ├── constants/
│   │   │   │   ├── icons.ts
│   │   │   │   ├── index.js
│   │   │   │   ├── sharedConstants.ts
│   │   │   │   └── videoConstants.js
│   │   │   ├── containers/
│   │   │   │   ├── AppContainer/
│   │   │   │   │   ├── AppContainer.tsx
│   │   │   │   │   ├── AppLoader.ts
│   │   │   │   │   ├── GlobalAnnouncements.tsx
│   │   │   │   │   ├── ServerUnreachableBanner.tsx
│   │   │   │   │   └── index.ts
│   │   │   │   ├── AuthPagesContainer.tsx
│   │   │   │   ├── CourselessContainer.tsx
│   │   │   │   ├── DeleteConfirmation/
│   │   │   │   │   └── index.jsx
│   │   │   │   ├── NotificationPopup/
│   │   │   │   │   └── index.jsx
│   │   │   │   └── TableLegends.tsx
│   │   │   ├── helpers/
│   │   │   │   ├── __test__/
│   │   │   │   │   └── htmlFormatHelpers.test.js
│   │   │   │   ├── htmlFormatHelpers.js
│   │   │   │   ├── jobHelpers.ts
│   │   │   │   ├── mui-datatables-helpers.ts
│   │   │   │   ├── react-hook-form-helper.js
│   │   │   │   ├── reducer-helpers.js
│   │   │   │   ├── url-builders.js
│   │   │   │   ├── url-helpers.ts
│   │   │   │   └── videoHelpers.js
│   │   │   ├── history.js
│   │   │   ├── hooks/
│   │   │   │   ├── items/
│   │   │   │   │   ├── useItems.ts
│   │   │   │   │   ├── usePaginate.ts
│   │   │   │   │   ├── useSearch.ts
│   │   │   │   │   └── useSort.ts
│   │   │   │   ├── router/
│   │   │   │   │   ├── dynamicNest.ts
│   │   │   │   │   ├── redirect.tsx
│   │   │   │   │   └── usePrompt.tsx
│   │   │   │   ├── session.ts
│   │   │   │   ├── store.ts
│   │   │   │   ├── toast/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── loadingToast.ts
│   │   │   │   │   └── toast.tsx
│   │   │   │   ├── unread.ts
│   │   │   │   ├── useDebounce.ts
│   │   │   │   ├── useEffectOnce.ts
│   │   │   │   ├── useMedia.ts
│   │   │   │   └── useTranslation.ts
│   │   │   ├── moment.ts
│   │   │   ├── reducers/
│   │   │   │   ├── deleteConfirmation.js
│   │   │   │   └── notificationPopup.js
│   │   │   ├── translations/
│   │   │   │   ├── course/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── users/
│   │   │   │   │       ├── index.ts
│   │   │   │   │       └── roles.ts
│   │   │   │   ├── form.ts
│   │   │   │   ├── getHelp.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── messages.ts
│   │   │   │   └── table.ts
│   │   │   └── types.js
│   │   ├── routers/
│   │   │   ├── AuthenticatableApp.tsx
│   │   │   ├── AuthenticatedApp.tsx
│   │   │   ├── UnauthenticatedApp.tsx
│   │   │   ├── course/
│   │   │   │   ├── achievements.tsx
│   │   │   │   ├── admin.tsx
│   │   │   │   ├── assessments/
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   ├── questions.tsx
│   │   │   │   │   └── submissions.tsx
│   │   │   │   ├── forums.tsx
│   │   │   │   ├── groups.tsx
│   │   │   │   ├── index.tsx
│   │   │   │   ├── lessonPlan.tsx
│   │   │   │   ├── materials.tsx
│   │   │   │   ├── plagiarism.tsx
│   │   │   │   ├── scholaistic.tsx
│   │   │   │   ├── statistics.tsx
│   │   │   │   ├── surveys.tsx
│   │   │   │   ├── users.tsx
│   │   │   │   └── videos.tsx
│   │   │   ├── courseless/
│   │   │   │   ├── index.tsx
│   │   │   │   ├── instanceAdmin.tsx
│   │   │   │   ├── systemAdmin.tsx
│   │   │   │   └── users.tsx
│   │   │   ├── index.ts
│   │   │   ├── redirects.tsx
│   │   │   └── router.tsx
│   │   ├── store.ts
│   │   ├── theme/
│   │   │   ├── bouncing-dot.css
│   │   │   ├── colors.js
│   │   │   ├── github.css
│   │   │   ├── index.css
│   │   │   ├── mui-style.ts
│   │   │   ├── palette.js
│   │   │   ├── sidebar.css
│   │   │   └── syntax-highlighting.css
│   │   ├── types/
│   │   │   ├── channels/
│   │   │   │   ├── heartbeat.ts
│   │   │   │   └── liveMonitoring.ts
│   │   │   ├── components/
│   │   │   │   └── DataTable.ts
│   │   │   ├── course/
│   │   │   │   ├── achievements.ts
│   │   │   │   ├── admin/
│   │   │   │   │   ├── announcements.ts
│   │   │   │   │   ├── assessments.ts
│   │   │   │   │   ├── codaveri.ts
│   │   │   │   │   ├── comments.ts
│   │   │   │   │   ├── components.ts
│   │   │   │   │   ├── course.ts
│   │   │   │   │   ├── forums.ts
│   │   │   │   │   ├── leaderboard.ts
│   │   │   │   │   ├── lessonPlan.ts
│   │   │   │   │   ├── materials.ts
│   │   │   │   │   ├── notifications.ts
│   │   │   │   │   ├── ragWise.ts
│   │   │   │   │   ├── scholaistic.ts
│   │   │   │   │   ├── sidebar.ts
│   │   │   │   │   ├── stories.ts
│   │   │   │   │   └── videos.ts
│   │   │   │   ├── announcements.ts
│   │   │   │   ├── assessment/
│   │   │   │   │   ├── assessments.ts
│   │   │   │   │   ├── monitoring.ts
│   │   │   │   │   ├── question/
│   │   │   │   │   │   ├── forum-post-responses.ts
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   ├── multiple-responses.ts
│   │   │   │   │   │   ├── programming.ts
│   │   │   │   │   │   ├── rubric-based-responses.ts
│   │   │   │   │   │   ├── scribing.ts
│   │   │   │   │   │   ├── text-responses.ts
│   │   │   │   │   │   └── voice-responses.ts
│   │   │   │   │   ├── question-generation.ts
│   │   │   │   │   ├── questions.ts
│   │   │   │   │   ├── sessions.ts
│   │   │   │   │   ├── skills/
│   │   │   │   │   │   ├── skills.ts
│   │   │   │   │   │   └── userSkills.ts
│   │   │   │   │   ├── submission/
│   │   │   │   │   │   ├── annotations.ts
│   │   │   │   │   │   ├── answer/
│   │   │   │   │   │   │   ├── answer.ts
│   │   │   │   │   │   │   ├── forumPostResponse.ts
│   │   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   │   ├── multipleResponse.ts
│   │   │   │   │   │   │   ├── programming.ts
│   │   │   │   │   │   │   ├── rubricBasedResponse.ts
│   │   │   │   │   │   │   ├── scribing.ts
│   │   │   │   │   │   │   ├── textResponse.ts
│   │   │   │   │   │   │   └── voiceResponse.ts
│   │   │   │   │   │   ├── liveFeedback.ts
│   │   │   │   │   │   ├── logs.ts
│   │   │   │   │   │   ├── question/
│   │   │   │   │   │   │   └── types.ts
│   │   │   │   │   │   ├── submission-question.ts
│   │   │   │   │   │   └── submission.ts
│   │   │   │   │   └── submissions.ts
│   │   │   │   ├── comments.ts
│   │   │   │   ├── conditions.ts
│   │   │   │   ├── courseUsers.ts
│   │   │   │   ├── courses.ts
│   │   │   │   ├── disbursement.ts
│   │   │   │   ├── duplication.ts
│   │   │   │   ├── enrolRequests.ts
│   │   │   │   ├── experiencePointsRecords.ts
│   │   │   │   ├── forums.ts
│   │   │   │   ├── leaderboard.ts
│   │   │   │   ├── learn.ts
│   │   │   │   ├── lesson-plan/
│   │   │   │   │   └── todos.ts
│   │   │   │   ├── material/
│   │   │   │   │   ├── files.ts
│   │   │   │   │   └── folders.ts
│   │   │   │   ├── notifications.ts
│   │   │   │   ├── personalTimes.ts
│   │   │   │   ├── plagiarism.ts
│   │   │   │   ├── referenceTimelines.ts
│   │   │   │   ├── rubrics.ts
│   │   │   │   ├── scholaistic.ts
│   │   │   │   ├── statistics/
│   │   │   │   │   ├── answer.ts
│   │   │   │   │   └── assessmentStatistics.ts
│   │   │   │   ├── subscriptions.ts
│   │   │   │   ├── userInvitations.ts
│   │   │   │   ├── userNotifications.ts
│   │   │   │   ├── video/
│   │   │   │   │   └── submissions.ts
│   │   │   │   ├── videoSubmissions.ts
│   │   │   │   └── videos.ts
│   │   │   ├── home.ts
│   │   │   ├── index.ts
│   │   │   ├── jobs.ts
│   │   │   ├── store.ts
│   │   │   ├── system/
│   │   │   │   ├── courses.ts
│   │   │   │   ├── instance/
│   │   │   │   │   ├── components.ts
│   │   │   │   │   ├── invitations.ts
│   │   │   │   │   ├── roleRequests.ts
│   │   │   │   │   └── users.ts
│   │   │   │   └── instances.ts
│   │   │   └── users.ts
│   │   ├── utilities/
│   │   │   ├── ResizeObserver.ts
│   │   │   ├── TestApp.tsx
│   │   │   ├── array.ts
│   │   │   ├── authentication.ts
│   │   │   ├── downloadFile.ts
│   │   │   ├── index.ts
│   │   │   ├── mirrorCreator.ts
│   │   │   ├── socket.ts
│   │   │   ├── store.ts
│   │   │   └── test-utils.tsx
│   │   └── workers/
│   │       ├── constructors.ts
│   │       ├── heartbeat.sharedworker.ts
│   │       ├── heartbeat.worker.ts
│   │       ├── heartbeatChannel.ts
│   │       ├── listeners.ts
│   │       ├── monitoringDatabase.ts
│   │       ├── types.ts
│   │       └── withHeartbeatWorker.tsx
│   ├── css-includes.json
│   ├── env
│   ├── env.test
│   ├── jest.config.js
│   ├── locales/
│   │   ├── en.json
│   │   ├── ko.json
│   │   └── zh.json
│   ├── package.json
│   ├── postcss.config.js
│   ├── public/
│   │   └── index.html
│   ├── tailwind.config.ts
│   ├── tsconfig.eslint.json
│   ├── tsconfig.json
│   ├── webpack.common.js
│   ├── webpack.dev.js
│   ├── webpack.prod.js
│   └── webpack.profile.js
├── config/
│   ├── application.rb
│   ├── boot.rb
│   ├── cable.yml
│   ├── credentials/
│   │   ├── README.md
│   │   ├── test.key
│   │   └── test.yml.enc
│   ├── database.yml
│   ├── environment.rb
│   ├── environments/
│   │   ├── development.rb
│   │   ├── production.rb
│   │   └── test.rb
│   ├── i18n-js.yml
│   ├── i18n-tasks.yml
│   ├── image_optim.yml
│   ├── initializers/
│   │   ├── action_cable_acts_as_tenant.rb
│   │   ├── acts_as_tenant.rb
│   │   ├── application_controller_renderer.rb
│   │   ├── argument_deserializer.rb
│   │   ├── aws.rb
│   │   ├── backtrace_silencers.rb
│   │   ├── bullet.rb
│   │   ├── carrier_wave.rb
│   │   ├── content_security_policy.rb
│   │   ├── cookies_serializer.rb
│   │   ├── coverage.rb
│   │   ├── devise.rb
│   │   ├── extensions.rb
│   │   ├── filter_parameter_logging.rb
│   │   ├── formats_filter.rb
│   │   ├── inflections.rb
│   │   ├── keycloak.rb
│   │   ├── llm_langchain.rb
│   │   ├── locale.rb
│   │   ├── lograge.rb
│   │   ├── mail_delivery_job.rb
│   │   ├── mime_types.rb
│   │   ├── oembed.rb
│   │   ├── rack_mini_profiler.rb
│   │   ├── recaptcha.rb
│   │   ├── redis.rb
│   │   ├── send_file.rb
│   │   ├── session_store.rb
│   │   ├── sidekiq.rb
│   │   ├── userstamp.rb
│   │   ├── worker_http_listener.rb
│   │   └── wrap_parameters.rb
│   ├── locales/
│   │   ├── en/
│   │   │   ├── activemodel/
│   │   │   │   └── course/
│   │   │   │       └── experience_points/
│   │   │   │           └── forum_disbursement.yml
│   │   │   ├── activerecord/
│   │   │   │   ├── attributes.yml
│   │   │   │   └── errors.yml
│   │   │   ├── course/
│   │   │   │   └── assessment/
│   │   │   │       ├── answer/
│   │   │   │       │   └── text_response_comprehension_auto_grading.yml
│   │   │   │       ├── assessments.yml
│   │   │   │       ├── question/
│   │   │   │       │   ├── forum_post_response.yml
│   │   │   │       │   ├── multiple_responses.yml
│   │   │   │       │   ├── programming.yml
│   │   │   │       │   ├── scribing.yml
│   │   │   │       │   └── voice_responses.yml
│   │   │   │       └── question_bundle_assignments.yml
│   │   │   ├── csv.yml
│   │   │   ├── devise.yml
│   │   │   ├── errors.yml
│   │   │   ├── jobs.yml
│   │   │   ├── mailers.yml
│   │   │   └── time.yml
│   │   ├── ko/
│   │   │   ├── activemodel/
│   │   │   │   └── course/
│   │   │   │       └── experience_points/
│   │   │   │           └── forum_disbursement.yml
│   │   │   ├── activerecord/
│   │   │   │   ├── attributes.yml
│   │   │   │   └── errors.yml
│   │   │   ├── course/
│   │   │   │   └── assessment/
│   │   │   │       ├── answer/
│   │   │   │       │   └── text_response_comprehension_auto_grading.yml
│   │   │   │       ├── assessments.yml
│   │   │   │       ├── question/
│   │   │   │       │   ├── forum_post_response.yml
│   │   │   │       │   ├── multiple_responses.yml
│   │   │   │       │   ├── programming.yml
│   │   │   │       │   ├── scribing.yml
│   │   │   │       │   └── voice_responses.yml
│   │   │   │       └── question_bundle_assignments.yml
│   │   │   ├── csv.yml
│   │   │   ├── devise.yml
│   │   │   ├── errors.yml
│   │   │   ├── instance_user_role_request_mailer.yml
│   │   │   ├── jobs.yml
│   │   │   ├── mailers.yml
│   │   │   └── time.yml
│   │   └── zh/
│   │       ├── activemodel/
│   │       │   └── course/
│   │       │       └── experience_points/
│   │       │           └── forum_disbursement.yml
│   │       ├── activerecord/
│   │       │   ├── attributes.yml
│   │       │   └── errors.yml
│   │       ├── course/
│   │       │   └── assessment/
│   │       │       ├── answer/
│   │       │       │   └── text_response_comprehension_auto_grading.yml
│   │       │       ├── assessments.yml
│   │       │       ├── question/
│   │       │       │   ├── forum_post_response.yml
│   │       │       │   ├── multiple_responses.yml
│   │       │       │   ├── programming.yml
│   │       │       │   ├── scribing.yml
│   │       │       │   └── voice_responses.yml
│   │       │       └── question_bundle_assignments.yml
│   │       ├── csv.yml
│   │       ├── devise.yml
│   │       ├── errors.yml
│   │       ├── instance_user_role_request_mailer.yml
│   │       ├── jobs.yml
│   │       ├── mailers.yml
│   │       └── time.yml
│   ├── puma.rb
│   ├── routes.rb
│   ├── schedule.yml
│   ├── spring.rb
│   └── storage.yml
├── config.ru
├── db/
│   ├── migrate/
│   │   ├── .rubocop.yml
│   │   ├── 20141203044211_create_instances.rb
│   │   ├── 20141204122534_devise_create_users.rb
│   │   ├── 20141204122851_create_user_emails.rb
│   │   ├── 20141205065248_create_instance_users.rb
│   │   ├── 20141210044557_add_role_to_users_and_instance_users.rb
│   │   ├── 20141210105742_create_courses.rb
│   │   ├── 20141210133147_create_course_users.rb
│   │   ├── 20141222074908_add_userstamps_to_courses.rb
│   │   ├── 20150106073750_add_name_to_instances.rb
│   │   ├── 20150114024350_create_course_announcements.rb
│   │   ├── 20150114025131_create_instance_announcements.rb
│   │   ├── 20150116102204_add_name_to_users.rb
│   │   ├── 20150126080047_add_sticky_to_course_announcements.rb
│   │   ├── 20150129040648_create_system_announcements.rb
│   │   ├── 20150204075501_create_course_achievements.rb
│   │   ├── 20150206020132_create_course_levels.rb
│   │   ├── 20150309030221_create_attachments.rb
│   │   ├── 20150314025251_add_logo_to_courses.rb
│   │   ├── 20150316080645_unread_migration.rb
│   │   ├── 20150411065243_create_course_lesson_plan_items.rb
│   │   ├── 20150413043822_add_settings_to_instances_and_courses.rb
│   │   ├── 20150415033008_create_course_experience_points_records.rb
│   │   ├── 20150422152756_create_course_condition_levels.rb
│   │   ├── 20150425030128_set_timestamps_nullity.rb
│   │   ├── 20150426062119_create_course_conditions.rb
│   │   ├── 20150426062133_create_course_conditions_achievements.rb
│   │   ├── 20150512014731_add_workflow_state_to_course_users.rb
│   │   ├── 20150512015621_add_userstamps_to_course_users.rb
│   │   ├── 20150513110737_create_course_groups.rb
│   │   ├── 20150513111716_create_course_group_users.rb
│   │   ├── 20150614024340_combine_instance_system_announcements.rb
│   │   ├── 20150615014716_create_course_invitations.rb
│   │   ├── 20150615073135_add_fields_to_course_lesson_plan_item.rb
│   │   ├── 20150615075515_create_course_events.rb
│   │   ├── 20150616120237_create_activities_and_notifications.rb
│   │   ├── 20150617021911_create_course_lesson_plan_milestones.rb
│   │   ├── 20150624230355_add_course_registration_key_to_course.rb
│   │   ├── 20150702122955_instance_users_change_user_id_unique.rb
│   │   ├── 20150713125423_create_assessments.rb
│   │   ├── 20150721051322_add_course_assessment_logic.rb
│   │   ├── 20150721055754_change_experience_points_record_points_null.rb
│   │   ├── 20150721070705_create_user_identities.rb
│   │   ├── 20150726062900_create_course_assessment_question_multiple_response.rb
│   │   ├── 20150726130555_set_achievement_condition_nullity.rb
│   │   ├── 20150726130922_set_conditional_nullity.rb
│   │   ├── 20150728020832_add_schema_nullity.rb
│   │   ├── 20150728022835_rename_published_to_draft.rb
│   │   ├── 20150729133128_rename_course_events_to_course_lesson_plan_events.rb
│   │   ├── 20150730074301_rename_start_end_time_to_start_end_at.rb
│   │   ├── 20150731010032_rename_valid_from_to_start_end_at.rb
│   │   ├── 20150803065430_change_multiple_response_question_option_option_explanation_column_type.rb
│   │   ├── 20150803065716_create_materials.rb
│   │   ├── 20150803080715_add_assessment_answer_workflow_state.rb
│   │   ├── 20150812024950_add_fields_to_course_material_folders.rb
│   │   ├── 20151011151130_create_course_user_achievements.rb
│   │   ├── 20151016094007_create_discussions_and_forums.rb
│   │   ├── 20151016094008_create_forums.rb
│   │   ├── 20151016151834_add_root_folder_to_courses.rb
│   │   ├── 20151018122902_add_grade_to_course_assessment_answer.rb
│   │   ├── 20151021014315_create_course_assessment_question_text_response.rb
│   │   ├── 20151022105653_add_unique_index_to_forum_and_topic.rb
│   │   ├── 20151027050627_add_submission_grading_statistics.rb
│   │   ├── 20151028151258_add_unique_index_to_materials.rb
│   │   ├── 20151030063045_add_unique_index_to_course_material_folders.rb
│   │   ├── 20151031044810_add_course_assessment_answer_auto_grading.rb
│   │   ├── 20151101050627_create_folder_for_categories_and_assessments.rb
│   │   ├── 20151114043545_create_jobs.rb
│   │   ├── 20151114093538_link_course_assessment_answer_auto_grading_to_jobs.rb
│   │   ├── 20151117141053_unread_polymorphic_reader_migration.rb
│   │   ├── 20151119020459_create_course_assessment_programming_questions.rb
│   │   ├── 20151121070719_create_polyglot_languages.rb
│   │   ├── 20151121082432_integrate_assessments_with_polyglot_framework.rb
│   │   ├── 20151122011709_create_course_assessment_programming_evaluations.rb
│   │   ├── 20151202030421_add_profile_photo_to_users.rb
│   │   ├── 20151210055839_create_course_condition_assessments.rb
│   │   ├── 20151212091754_normalise_programming_question_file_names.rb
│   │   ├── 20151212232827_add_token_authentication_to_user.rb
│   │   ├── 20151214080700_add_package_to_programming_evaluation.rb
│   │   ├── 20151214081508_add_unique_index_to_course_levels.rb
│   │   ├── 20151224034135_add_display_mode_to_assessments.rb
│   │   ├── 20151228030006_add_weight_to_questions.rb
│   │   ├── 20160119055307_add_correct_to_assessment_answers.rb
│   │   ├── 20160124054745_add_exit_code_to_programming_evaluation.rb
│   │   ├── 20160126094510_add_badge_to_course_achievements.rb
│   │   ├── 20160220081731_rename_assessment_tags_to_skills.rb
│   │   ├── 20160220092350_add_course_to_skill_and_skill_branch.rb
│   │   ├── 20160226013208_create_course_assessment_answer_programming_file_annotations.rb
│   │   ├── 20160229082515_create_attachment_references.rb
│   │   ├── 20160330031839_create_course_discussion_post_votes.rb
│   │   ├── 20160420005403_change_course_groups_from_user_to_course_user.rb
│   │   ├── 20160429135101_add_attributes_to_course_discussion_topics.rb
│   │   ├── 20160523093423_add_field_to_course_discussion_topics.rb
│   │   ├── 20160628052136_add_staff_only_comments_to_questions.rb
│   │   ├── 20160714053644_add_timestamps_to_course_assessment_answers.rb
│   │   ├── 20160716091234_add_autograded_to_course_assessments.rb
│   │   ├── 20160722020938_add_time_zone_to_users.rb
│   │   ├── 20160729022656_add_fields_to_course_assessment_question_programming_test_cases.rb
│   │   ├── 20160730044448_chang_attachment_references.rb
│   │   ├── 20160801084814_rename_question_type_to_grading_scheme.rb
│   │   ├── 20160808023535_change_course_assessment_questions_title_nullity.rb
│   │   ├── 20160811064336_change_test_cases_expected_type.rb
│   │   ├── 20160815141617_prevent_duplicate_submissions.rb
│   │   ├── 20160822092000_add_publisher_to_submissions.rb
│   │   ├── 20160823091240_add_unique_index_to_read_marks.rb
│   │   ├── 20160823094126_add_unique_index_to_multiple_response_answer_options.rb
│   │   ├── 20160830023835_alter_grade_type.rb
│   │   ├── 20160906091734_add_fields_to_course_assessment_answer_text_responses.rb
│   │   ├── 20160908100211_rename_programming_auto_grading_test_result_messages.rb
│   │   ├── 20160916101014_change_discussion_posts_title.rb
│   │   ├── 20160920101847_add_hide_text_to_course_assessment_question_text_responses.rb
│   │   ├── 20161003094742_create_lesson_plan_todos.rb
│   │   ├── 20161006063146_rename_assessments_display_mode.rb
│   │   ├── 20161007061116_add_fields_to_assessments.rb
│   │   ├── 20161013115452_migrate_graded_submissions_to_published.rb
│   │   ├── 20161020020353_add_todos_for_existing_lesson_plan_items.rb
│   │   ├── 20161027020646_add_package_type_to_course_assessment_question_programming.rb
│   │   ├── 20161027074807_add_session_id_to_submissions.rb
│   │   ├── 20161102022455_add_stdout_stderr_to_course_assessment_answer_programming_auto_grading.rb
│   │   ├── 20161107023238_add_attempt_limit_to_programming_questions.rb
│   │   ├── 20161108030759_add_gamified_to_courses.rb
│   │   ├── 20161116075305_add_tabbed_view_to_course_assessments.rb
│   │   ├── 20161202071856_add_skippable_to_assessments.rb
│   │   ├── 20161206101644_remove_mode_and_invert_draft.rb
│   │   ├── 20161207013914_create_course_survey_tables.rb
│   │   ├── 20161214050848_add_sent_at_to_course_user_invitations.rb
│   │   ├── 20161219105620_change_course_user_invitations.rb
│   │   ├── 20161223123359_create_course_enrol_requests.rb
│   │   ├── 20161227125455_remove_workflow_state_from_course_users.rb
│   │   ├── 20170102053335_create_course_video_tables.rb
│   │   ├── 20170103104020_create_course_lectures.rb
│   │   ├── 20170110022335_remove_extra_bonus_exp_from_lesson_plan.rb
│   │   ├── 20170115105609_add_delayed_grade_publication_to_course_assessments.rb
│   │   ├── 20170116103602_add_tokens_to_course_lesson_plan_items.rb
│   │   ├── 20170117145558_add_fields_to_courses.rb
│   │   ├── 20170117164747_add_awarded_at_and_draft_exp_to_course_experience_points_records.rb
│   │   ├── 20170120063357_change_default_value_of_assessment_questions_weight.rb
│   │   ├── 20170128041649_change_survey_tables.rb
│   │   ├── 20170203020915_add_weight_to_course_assessment_question_multiple_response_options.rb
│   │   ├── 20170210073247_add_selected_to_survey_answer_options.rb
│   │   ├── 20170214062036_add_index_for_survey_response_user.rb
│   │   ├── 20170217041431_add_survey_booleans.rb
│   │   ├── 20170220123952_remove_image_from_survey_question_option.rb
│   │   ├── 20170222101701_remove_default_from_groups.rb
│   │   ├── 20170302054635_add_submitted_at_to_submissions.rb
│   │   ├── 20170306051518_rename_lectures_to_virtual_classrooms.rb
│   │   ├── 20170307043218_add_instructor_id_to_virtual_classrooms.rb
│   │   ├── 20170307080839_add_timestamp_to_trackable_jobs.rb
│   │   ├── 20170307090147_add_time_limit_to_existing_programming_questions.rb
│   │   ├── 20170308044737_add_recorded_videos_to_virtual_classrooms.rb
│   │   ├── 20170308073855_create_course_assessment_submission_logs.rb
│   │   ├── 20170308074359_add_course_assessment_submission_question.rb
│   │   ├── 20170309094211_add_section_id_to_survey_questions.rb
│   │   ├── 20170407083553_add_reminded_at_and_allow_responsee_to_surveys.rb
│   │   ├── 20170420063829_remove_length_limit_of_expression.rb
│   │   ├── 20170426024809_remove_constraint_in_skills.rb
│   │   ├── 20170506010828_create_course_assessment_question_scribings.rb
│   │   ├── 20170510233359_remove_selected_from_survey_answer_options.rb
│   │   ├── 20170515061739_add_more_options_to_course_assessments.rb
│   │   ├── 20170522104534_regroup_course_settings.rb
│   │   ├── 20170528035408_create_course_assessment_question_voice_responses.rb
│   │   ├── 20170529035430_create_course_assessment_answer_voice_responses.rb
│   │   ├── 2017
Download .txt
Showing preview only (965K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (10175 symbols across 2444 files)

FILE: app/channels/application_cable/channel.rb
  class ApplicationCable::Channel (line 2) | class ApplicationCable::Channel < ActionCable::Channel::Base
    method request (line 7) | def request
    method session (line 11) | def session
    method ip_address_and_user_agent (line 15) | def ip_address_and_user_agent

FILE: app/channels/application_cable/connection.rb
  class ApplicationCable::Connection (line 2) | class ApplicationCable::Connection < ActionCable::Connection::Base
    method connect (line 7) | def connect

FILE: app/channels/concerns/application_cable_ability_concern.rb
  type ApplicationCableAbilityConcern (line 2) | module ApplicationCableAbilityConcern
    function current_ability (line 9) | def current_ability
    function can? (line 13) | def can?(*args)
    function cannot? (line 17) | def cannot?(*args)

FILE: app/channels/concerns/application_cable_authentication_concern.rb
  type ApplicationCableAuthenticationConcern (line 2) | module ApplicationCableAuthenticationConcern
    function current_user_from_token (line 3) | def current_user_from_token
    function retrieve_current_session_id (line 8) | def retrieve_current_session_id
    function current_decoded_token (line 12) | def current_decoded_token
    function authenticate_token (line 18) | def authenticate_token
    function token_from_request (line 28) | def token_from_request

FILE: app/channels/concerns/application_cable_component_concern.rb
  type ApplicationCableComponentConcern (line 2) | module ApplicationCableComponentConcern
    function current_component_host (line 10) | def current_component_host
    function component (line 18) | def component
    function check_component (line 23) | def check_component

FILE: app/channels/concerns/application_cable_course_concern.rb
  type ApplicationCableCourseConcern (line 2) | module ApplicationCableCourseConcern
    function find_course (line 9) | def find_course
    function current_course (line 14) | def current_course
    function current_course_user (line 18) | def current_course_user

FILE: app/channels/concerns/application_cable_multitenancy_concern.rb
  type ApplicationCableMultitenancyConcern (line 2) | module ApplicationCableMultitenancyConcern

FILE: app/channels/course/channel.rb
  class Course::Channel (line 17) | class Course::Channel < ApplicationCable::Channel

FILE: app/channels/course/monitoring/heartbeat_channel.rb
  class Course::Monitoring::HeartbeatChannel (line 2) | class Course::Monitoring::HeartbeatChannel < Course::Channel
    method subscribed (line 5) | def subscribed
    method pulse (line 14) | def pulse(data)
    method flush (line 42) | def flush(data)
    method broadcast_terminate (line 63) | def broadcast_terminate(session)
    method listening? (line 70) | def listening?
    method filter_and_sort_heartbeats (line 74) | def filter_and_sort_heartbeats(heartbeats)
    method time_from (line 81) | def time_from(milliseconds)
    method broadcast_pulse_to_live_monitoring (line 85) | def broadcast_pulse_to_live_monitoring(heartbeat)
    method broadcast_terminate_to_live_monitoring (line 95) | def broadcast_terminate_to_live_monitoring
    method broadcast_terminate (line 99) | def broadcast_terminate
    method broadcast_flushed (line 103) | def broadcast_flushed(first_timestamp, last_timestamp)
    method broadcast_next (line 111) | def broadcast_next(received_timestamp, next_timeout)
    method component (line 119) | def component
    method can_pulse? (line 123) | def can_pulse?
    method assessment_id (line 127) | def assessment_id
    method valid_heartbeat? (line 131) | def valid_heartbeat?(heartbeat)

FILE: app/channels/course/monitoring/live_monitoring_channel.rb
  class Course::Monitoring::LiveMonitoringChannel (line 2) | class Course::Monitoring::LiveMonitoringChannel < Course::Channel
    method subscribed (line 8) | def subscribed
    method broadcast_pulse_to (line 17) | def broadcast_pulse_to(monitor, session, snapshot)
    method broadcast_terminate (line 21) | def broadcast_terminate(monitor, session)
    method broadcast_from (line 25) | def broadcast_from(monitor, action, payload)
    method watch (line 30) | def watch
    method view (line 42) | def view(data)
    method active_sessions_snapshots (line 62) | def active_sessions_snapshots
    method groups (line 86) | def groups
    method broadcast (line 97) | def broadcast(action, payload)
    method broadcast_watch (line 101) | def broadcast_watch(users, snapshots, groups)
    method broadcast_viewed (line 115) | def broadcast_viewed(recent_heartbeats)
    method component (line 119) | def component
    method course_users_hash (line 123) | def course_users_hash
    method submission_ids_hash (line 127) | def submission_ids_hash

FILE: app/controllers/announcements_controller.rb
  class AnnouncementsController (line 2) | class AnnouncementsController < ApplicationController
    method index (line 5) | def index
    method mark_as_read (line 14) | def mark_as_read
    method publicly_accessible? (line 25) | def publicly_accessible?
    method requesting_unread? (line 31) | def requesting_unread?

FILE: app/controllers/application_controller.rb
  class ApplicationController (line 3) | class ApplicationController < ActionController::Base
    method index (line 22) | def index
    method without_bullet (line 32) | def without_bullet
    method handle_illegal_state_error (line 42) | def handle_illegal_state_error(exception)
    method handle_csrf_error (line 47) | def handle_csrf_error(exception)
    method handle_authentication_error (line 52) | def handle_authentication_error(exception)
    method append_info_to_payload (line 59) | def append_info_to_payload(payload)

FILE: app/controllers/attachment_references_controller.rb
  class AttachmentReferencesController (line 2) | class AttachmentReferencesController < ApplicationController
    method create (line 5) | def create
    method show (line 12) | def show
    method file_params (line 30) | def file_params

FILE: app/controllers/components/course/achievements_component.rb
  class Course::AchievementsComponent (line 2) | class Course::AchievementsComponent < SimpleDelegator
    method gamified? (line 5) | def self.gamified?
    method sidebar_items (line 9) | def sidebar_items

FILE: app/controllers/components/course/announcements_component.rb
  class Course::AnnouncementsComponent (line 2) | class Course::AnnouncementsComponent < SimpleDelegator
    method sidebar_items (line 6) | def sidebar_items
    method main_sidebar_items (line 12) | def main_sidebar_items
    method settings_sidebar_items (line 25) | def settings_sidebar_items

FILE: app/controllers/components/course/assessments_component.rb
  class Course::AssessmentsComponent (line 2) | class Course::AssessmentsComponent < SimpleDelegator
    method lesson_plan_item_actable_names (line 6) | def self.lesson_plan_item_actable_names
    method sidebar_items (line 10) | def sidebar_items
    method main_sidebar_items (line 16) | def main_sidebar_items
    method assessment_categories (line 20) | def assessment_categories
    method assessment_submissions (line 32) | def assessment_submissions
    method admin_sidebar_items (line 44) | def admin_sidebar_items
    method admin_settings_items (line 58) | def admin_settings_items

FILE: app/controllers/components/course/codaveri_component.rb
  class Course::CodaveriComponent (line 2) | class Course::CodaveriComponent < SimpleDelegator
    method sidebar_items (line 5) | def sidebar_items
    method settings_sidebar_items (line 11) | def settings_sidebar_items

FILE: app/controllers/components/course/controller_component_host.rb
  class Course::ControllerComponentHost (line 26) | class Course::ControllerComponentHost
    type Sidebar (line 29) | module Sidebar
      function sidebar_items (line 36) | def sidebar_items
    type Settings (line 41) | module Settings
      type ClassMethods (line 48) | module ClassMethods
        function enabled_by_default? (line 50) | def enabled_by_default?
        function key (line 57) | def key
        function display_name (line 65) | def display_name
        function gamified? (line 71) | def gamified?
        function can_be_disabled_for_course? (line 77) | def can_be_disabled_for_course?
        function settings_class (line 92) | def settings_class
        function lesson_plan_item_actable_names (line 101) | def lesson_plan_item_actable_names
      function settings (line 110) | def settings
    method initialize (line 129) | def initialize(context)
    method enabled_components (line 135) | def enabled_components
    method components (line 142) | def components
    method [] (line 151) | def [](component_key)
    method sidebar_items (line 176) | def sidebar_items
    method validate_component_key! (line 183) | def validate_component_key!(key)
    method component_key_set (line 187) | def component_key_set

FILE: app/controllers/components/course/discussion/topics_component.rb
  class Course::Discussion::TopicsComponent (line 2) | class Course::Discussion::TopicsComponent < SimpleDelegator
    method sidebar_items (line 6) | def sidebar_items
    method main_sidebar_items (line 12) | def main_sidebar_items
    method settings_sidebar_items (line 25) | def settings_sidebar_items

FILE: app/controllers/components/course/duplication_component.rb
  class Course::DuplicationComponent (line 2) | class Course::DuplicationComponent < SimpleDelegator
    method sidebar_items (line 5) | def sidebar_items

FILE: app/controllers/components/course/experience_points_component.rb
  class Course::ExperiencePointsComponent (line 2) | class Course::ExperiencePointsComponent < SimpleDelegator
    method gamified? (line 5) | def self.gamified?
    method sidebar_items (line 9) | def sidebar_items
    method can_create_experience_points_record? (line 25) | def can_create_experience_points_record?

FILE: app/controllers/components/course/forums_component.rb
  class Course::ForumsComponent (line 2) | class Course::ForumsComponent < SimpleDelegator
    method sidebar_items (line 6) | def sidebar_items
    method main_sidebar_items (line 12) | def main_sidebar_items
    method settings_sidebar_items (line 25) | def settings_sidebar_items

FILE: app/controllers/components/course/groups_component.rb
  class Course::GroupsComponent (line 2) | class Course::GroupsComponent < SimpleDelegator
    method sidebar_items (line 6) | def sidebar_items
    method group_category_url (line 22) | def group_category_url
    method show_group_sidebar_item? (line 31) | def show_group_sidebar_item?

FILE: app/controllers/components/course/koditsu_platform_component.rb
  class Course::KoditsuPlatformComponent (line 2) | class Course::KoditsuPlatformComponent < SimpleDelegator
    method enabled_by_default? (line 5) | def self.enabled_by_default?

FILE: app/controllers/components/course/leaderboard_component.rb
  class Course::LeaderboardComponent (line 2) | class Course::LeaderboardComponent < SimpleDelegator
    method gamified? (line 5) | def self.gamified?
    method sidebar_items (line 9) | def sidebar_items
    method main_sidebar_items (line 15) | def main_sidebar_items
    method settings_sidebar_items (line 27) | def settings_sidebar_items

FILE: app/controllers/components/course/learning_map_component.rb
  class Course::LearningMapComponent (line 2) | class Course::LearningMapComponent < SimpleDelegator
    method enabled_by_default? (line 5) | def self.enabled_by_default?
    method sidebar_items (line 9) | def sidebar_items

FILE: app/controllers/components/course/lesson_plan_component.rb
  class Course::LessonPlanComponent (line 2) | class Course::LessonPlanComponent < SimpleDelegator
    method lesson_plan_item_actable_names (line 5) | def self.lesson_plan_item_actable_names
    method sidebar_items (line 9) | def sidebar_items
    method main_sidebar_items (line 15) | def main_sidebar_items
    method settings_sidebar_items (line 26) | def settings_sidebar_items

FILE: app/controllers/components/course/levels_component.rb
  class Course::LevelsComponent (line 2) | class Course::LevelsComponent < SimpleDelegator
    method gamified? (line 5) | def self.gamified?
    method sidebar_items (line 9) | def sidebar_items

FILE: app/controllers/components/course/materials_component.rb
  class Course::MaterialsComponent (line 2) | class Course::MaterialsComponent < SimpleDelegator
    method sidebar_items (line 5) | def sidebar_items
    method main_sidebar_items (line 11) | def main_sidebar_items
    method settings_sidebar_items (line 23) | def settings_sidebar_items

FILE: app/controllers/components/course/monitoring_component.rb
  class Course::MonitoringComponent (line 2) | class Course::MonitoringComponent < SimpleDelegator
    method enabled_by_default? (line 5) | def self.enabled_by_default?

FILE: app/controllers/components/course/multiple_reference_timelines_component.rb
  class Course::MultipleReferenceTimelinesComponent (line 2) | class Course::MultipleReferenceTimelinesComponent < SimpleDelegator
    method enabled_by_default? (line 5) | def self.enabled_by_default?
    method sidebar_items (line 9) | def sidebar_items

FILE: app/controllers/components/course/plagiarism_component.rb
  class Course::PlagiarismComponent (line 2) | class Course::PlagiarismComponent < SimpleDelegator
    method enabled_by_default? (line 5) | def self.enabled_by_default?
    method sidebar_items (line 9) | def sidebar_items

FILE: app/controllers/components/course/rag_wise_component.rb
  class Course::RagWiseComponent (line 2) | class Course::RagWiseComponent < SimpleDelegator
    method enabled_by_default? (line 5) | def self.enabled_by_default?
    method sidebar_items (line 9) | def sidebar_items
    method settings_sidebar_items (line 15) | def settings_sidebar_items

FILE: app/controllers/components/course/scholaistic_component.rb
  class Course::ScholaisticComponent (line 2) | class Course::ScholaisticComponent < SimpleDelegator
    method enabled_by_default? (line 6) | def self.enabled_by_default?
    method sidebar_items (line 10) | def sidebar_items
    method main_sidebar_items (line 16) | def main_sidebar_items
    method student_sidebar_items (line 22) | def student_sidebar_items
    method assistant_sidebar_items (line 34) | def assistant_sidebar_items
    method admin_sidebar_items (line 51) | def admin_sidebar_items
    method settings_sidebar_items (line 66) | def settings_sidebar_items

FILE: app/controllers/components/course/settings_component.rb
  class Course::SettingsComponent (line 2) | class Course::SettingsComponent < SimpleDelegator
    method can_be_disabled_for_course? (line 6) | def self.can_be_disabled_for_course?
    method sidebar_items (line 10) | def sidebar_items
    method admin_sidebar_items (line 16) | def admin_sidebar_items
    method settings_sidebar_items (line 30) | def settings_sidebar_items
    method settings_index_item (line 39) | def settings_index_item
    method settings_components_item (line 48) | def settings_components_item
    method settings_sidebar_item (line 57) | def settings_sidebar_item
    method settings_notifications (line 66) | def settings_notifications

FILE: app/controllers/components/course/statistics_component.rb
  class Course::StatisticsComponent (line 2) | class Course::StatisticsComponent < SimpleDelegator
    method sidebar_items (line 5) | def sidebar_items

FILE: app/controllers/components/course/stories_component.rb
  class Course::StoriesComponent (line 2) | class Course::StoriesComponent < SimpleDelegator
    method enabled_by_default? (line 5) | def self.enabled_by_default?
    method sidebar_items (line 9) | def sidebar_items
    method main_sidebar_items (line 15) | def main_sidebar_items
    method student_sidebar_items (line 24) | def student_sidebar_items
    method staff_sidebar_items (line 36) | def staff_sidebar_items
    method settings_sidebar_items (line 50) | def settings_sidebar_items

FILE: app/controllers/components/course/survey_component.rb
  class Course::SurveyComponent (line 2) | class Course::SurveyComponent < SimpleDelegator
    method lesson_plan_item_actable_names (line 5) | def self.lesson_plan_item_actable_names
    method sidebar_items (line 9) | def sidebar_items

FILE: app/controllers/components/course/users_component.rb
  class Course::UsersComponent (line 2) | class Course::UsersComponent < SimpleDelegator
    method can_be_disabled_for_course? (line 6) | def self.can_be_disabled_for_course?
    method sidebar_items (line 11) | def sidebar_items
    method main_sidebar_items (line 17) | def main_sidebar_items
    method admin_sidebar_items (line 30) | def admin_sidebar_items

FILE: app/controllers/components/course/videos_component.rb
  class Course::VideosComponent (line 2) | class Course::VideosComponent < SimpleDelegator
    method lesson_plan_item_actable_names (line 6) | def self.lesson_plan_item_actable_names
    method sidebar_items (line 10) | def sidebar_items
    method main_sidebar_items (line 16) | def main_sidebar_items
    method settings_sidebar_items (line 29) | def settings_sidebar_items

FILE: app/controllers/concerns/application_ability_concern.rb
  type ApplicationAbilityConcern (line 2) | module ApplicationAbilityConcern
    function current_ability (line 4) | def current_ability

FILE: app/controllers/concerns/application_announcements_concern.rb
  type ApplicationAnnouncementsConcern (line 2) | module ApplicationAnnouncementsConcern
    function unread_global_announcements (line 8) | def unread_global_announcements
    function global_announcements (line 15) | def global_announcements

FILE: app/controllers/concerns/application_authentication_concern.rb
  type ApplicationAuthenticationConcern (line 2) | module ApplicationAuthenticationConcern
    function current_user_from_token (line 15) | def current_user_from_token
    function current_session_id (line 20) | def current_session_id
    function token_from_request (line 24) | def token_from_request
    function current_decoded_token (line 28) | def current_decoded_token
    function authenticate_token (line 34) | def authenticate_token
    function get_token_from_bearer (line 49) | def get_token_from_bearer
    function get_token_from_cookies (line 68) | def get_token_from_cookies

FILE: app/controllers/concerns/application_components_concern.rb
  type ApplicationComponentsConcern (line 2) | module ApplicationComponentsConcern
    function handle_component_not_found (line 11) | def handle_component_not_found(exception)

FILE: app/controllers/concerns/application_controller_multitenancy_concern.rb
  type ApplicationControllerMultitenancyConcern (line 2) | module ApplicationControllerMultitenancyConcern

FILE: app/controllers/concerns/application_instance_user_concern.rb
  type ApplicationInstanceUserConcern (line 2) | module ApplicationInstanceUserConcern
    function current_instance_user (line 9) | def current_instance_user
    function track_instance_user (line 17) | def track_instance_user

FILE: app/controllers/concerns/application_internationalization_concern.rb
  type ApplicationInternationalizationConcern (line 2) | module ApplicationInternationalizationConcern
    function set_locale (line 10) | def set_locale

FILE: app/controllers/concerns/application_multitenancy.rb
  type ApplicationMultitenancy (line 2) | module ApplicationMultitenancy
    function deduce_and_set_current_tenant (line 5) | def deduce_and_set_current_tenant
    function deduce_tenant (line 14) | def deduce_tenant
    function deduce_tenant_host (line 27) | def deduce_tenant_host
    type ClassMethods (line 43) | module ClassMethods
      function set_current_tenant_through_filter (line 44) | def set_current_tenant_through_filter

FILE: app/controllers/concerns/application_pagination_concern.rb
  type ApplicationPaginationConcern (line 2) | module ApplicationPaginationConcern
    function page_param (line 9) | def page_param

FILE: app/controllers/concerns/application_user_concern.rb
  type ApplicationUserConcern (line 2) | module ApplicationUserConcern
    function url_to_user_or_course_user (line 16) | def url_to_user_or_course_user(course, user)
    function current_user (line 23) | def current_user
    function publicly_accessible? (line 29) | def publicly_accessible?
    function handle_access_denied (line 33) | def handle_access_denied(exception)
    function authenticate! (line 39) | def authenticate!
    function add_token_to_cookie (line 46) | def add_token_to_cookie
    function update_user_tracked_fields (line 51) | def update_user_tracked_fields
    function update_tracked_fields (line 57) | def update_tracked_fields

FILE: app/controllers/concerns/application_user_time_zone_concern.rb
  type ApplicationUserTimeZoneConcern (line 2) | module ApplicationUserTimeZoneConcern
    function set_time_zone (line 12) | def set_time_zone(&block) # rubocop:disable Naming/AccessorMethodName

FILE: app/controllers/concerns/codaveri_language_concern.rb
  type CodaveriLanguageConcern (line 2) | module CodaveriLanguageConcern
    function codaveri_language (line 3) | def codaveri_language
    function codaveri_version (line 7) | def codaveri_version
    function programming_language_map (line 15) | def programming_language_map

FILE: app/controllers/concerns/course/achievement_conditional_concern.rb
  type Course::AchievementConditionalConcern (line 2) | module Course::AchievementConditionalConcern
    function success_action (line 5) | def success_action
    function set_conditional (line 9) | def set_conditional

FILE: app/controllers/concerns/course/activity_feeds_concern.rb
  type Course::ActivityFeedsConcern (line 2) | module Course::ActivityFeedsConcern
    function recent_activity_feeds (line 8) | def recent_activity_feeds

FILE: app/controllers/concerns/course/assessment/answer/update_answer_concern.rb
  type Course::Assessment::Answer::UpdateAnswerConcern (line 2) | module Course::Assessment::Answer::UpdateAnswerConcern
    function update_answer (line 7) | def update_answer(answer, answer_params)
    function update_answer_params (line 21) | def update_answer_params(answer, update_params)
    function additional_answer_params (line 27) | def additional_answer_params(answer)
    function update_specific_answer_type_params (line 34) | def update_specific_answer_type_params(answer) # rubocop:disable Metri...
    function update_multiple_response_params (line 59) | def update_multiple_response_params(array_params)
    function update_programming_params (line 63) | def update_programming_params(array_params)
    function update_text_response_params (line 67) | def update_text_response_params(scalar_params)
    function update_voice_response_params (line 72) | def update_voice_response_params(scalar_params)
    function update_rubric_based_response_params (line 76) | def update_rubric_based_response_params(scalar_params, array_params, a...
    function update_forum_post_response_params (line 83) | def update_forum_post_response_params(scalar_params, array_params)

FILE: app/controllers/concerns/course/assessment/koditsu_assessment_concern.rb
  type Course::Assessment::KoditsuAssessmentConcern (line 2) | module Course::Assessment::KoditsuAssessmentConcern
    function create_assessment_in_koditsu (line 5) | def create_assessment_in_koditsu
    function adjust_assessment_from_koditsu_response (line 17) | def adjust_assessment_from_koditsu_response(status, response)
    function update_assessment_in_koditsu (line 28) | def update_assessment_in_koditsu
    function create_or_update_assessment_in_koditsu (line 43) | def create_or_update_assessment_in_koditsu
    function flag_assessment_not_synced_with_koditsu (line 51) | def flag_assessment_not_synced_with_koditsu
    function remove_question_from_assessment_in_koditsu (line 55) | def remove_question_from_assessment_in_koditsu(question_id)
    function questions_in_koditsu (line 72) | def questions_in_koditsu(koditsu_assessment_id)
    function monitoring_configuration (line 83) | def monitoring_configuration
    function edit_koditsu_assessment (line 105) | def edit_koditsu_assessment(assessment, questions, course, monitoring_...

FILE: app/controllers/concerns/course/assessment/koditsu_assessment_invitation_concern.rb
  type Course::Assessment::KoditsuAssessmentInvitationConcern (line 2) | module Course::Assessment::KoditsuAssessmentInvitationConcern
    function send_invitation_for_koditsu_assessment (line 5) | def send_invitation_for_koditsu_assessment(assessment)
    function all_invitation_successful? (line 21) | def all_invitation_successful?(invitation_response)

FILE: app/controllers/concerns/course/assessment/live_feedback/file_concern.rb
  type Course::Assessment::LiveFeedback::FileConcern (line 2) | module Course::Assessment::LiveFeedback::FileConcern
    function snapshot_files_hash (line 5) | def snapshot_files_hash(file_ids)
    function answer_files_hash (line 11) | def answer_files_hash
    function fetch_all_unchanged_files (line 17) | def fetch_all_unchanged_files(file_hash, current_answer_file_hash)
    function fetch_all_modified_files (line 25) | def fetch_all_modified_files(file_hash, current_answer_file_hash)
    function fetch_all_files_to_be_associated (line 34) | def fetch_all_files_to_be_associated(file_ids)

FILE: app/controllers/concerns/course/assessment/live_feedback/message_concern.rb
  type Course::Assessment::LiveFeedback::MessageConcern (line 2) | module Course::Assessment::LiveFeedback::MessageConcern
    function handle_save_user_message (line 6) | def handle_save_user_message
    function create_new_message (line 26) | def create_new_message

FILE: app/controllers/concerns/course/assessment/live_feedback/message_file_concern.rb
  type Course::Assessment::LiveFeedback::MessageFileConcern (line 2) | module Course::Assessment::LiveFeedback::MessageFileConcern
    function associate_new_message_with_new_or_existing_files (line 6) | def associate_new_message_with_new_or_existing_files(new_message)
    function associated_file_ids_with_last_message (line 17) | def associated_file_ids_with_last_message(new_message)
    function save_message_file_association (line 27) | def save_message_file_association(new_message, associated_file_ids)

FILE: app/controllers/concerns/course/assessment/live_feedback/thread_concern.rb
  type Course::Assessment::LiveFeedback::ThreadConcern (line 2) | module Course::Assessment::LiveFeedback::ThreadConcern
    function safe_create_and_save_thread_info (line 5) | def safe_create_and_save_thread_info
    function existing_thread_status (line 20) | def existing_thread_status(thread)
    function create_and_save_thread_if_empty (line 29) | def create_and_save_thread_if_empty(submission_question)
    function save_thread_info (line 37) | def save_thread_info(thread_info, submission_question_id)

FILE: app/controllers/concerns/course/assessment/monitoring/seb_payload_concern.rb
  type Course::Assessment::Monitoring::SebPayloadConcern (line 2) | module Course::Assessment::Monitoring::SebPayloadConcern
    function seb_payload_from_request (line 7) | def seb_payload_from_request(request)
    function stub_heartbeat_from_request (line 16) | def stub_heartbeat_from_request(request)

FILE: app/controllers/concerns/course/assessment/monitoring_concern.rb
  type Course::Assessment::MonitoringConcern (line 2) | module Course::Assessment::MonitoringConcern
    function monitoring (line 20) | def monitoring
    function seb_payload (line 26) | def seb_payload
    function unblock_monitor (line 33) | def unblock_monitor
    function upsert_monitoring! (line 43) | def upsert_monitoring!
    function monitoring_params (line 52) | def monitoring_params
    function unblock_monitor_params (line 56) | def unblock_monitor_params
    function raise_if_no_monitor (line 60) | def raise_if_no_monitor
    function check_blocked_by_monitor (line 64) | def check_blocked_by_monitor
    function blocked_by_monitor? (line 68) | def blocked_by_monitor?
    function monitoring_service (line 72) | def monitoring_service
    function monitoring_component_enabled? (line 78) | def monitoring_component_enabled?
    function can_manage_monitor? (line 82) | def can_manage_monitor?
    function monitor (line 86) | def monitor
    function should_disable_block? (line 90) | def should_disable_block?
    function submitted_assessment? (line 94) | def submitted_assessment?

FILE: app/controllers/concerns/course/assessment/question/codaveri_question_concern.rb
  type Course::Assessment::Question::CodaveriQuestionConcern (line 2) | module Course::Assessment::Question::CodaveriQuestionConcern
    function safe_create_or_update_codaveri_question (line 5) | def safe_create_or_update_codaveri_question(question)
    function extract_pathname_from_java_file (line 19) | def extract_pathname_from_java_file(file_content)

FILE: app/controllers/concerns/course/assessment/question/koditsu_question_concern.rb
  type Course::Assessment::Question::KoditsuQuestionConcern (line 3) | module Course::Assessment::Question::KoditsuQuestionConcern
    function create_koditsu_question (line 7) | def create_koditsu_question
    function adjust_question_from_koditsu_response (line 17) | def adjust_question_from_koditsu_response(status, response)
    function arrange_questions_in_assessment_in_koditsu (line 31) | def arrange_questions_in_assessment_in_koditsu
    function edit_koditsu_question (line 50) | def edit_koditsu_question
    function delete_koditsu_question (line 60) | def delete_koditsu_question(id)
    function create_or_edit_question_in_koditsu (line 67) | def create_or_edit_question_in_koditsu
    function extract_programming_question_metadata (line 77) | def extract_programming_question_metadata
    function programming_package_service (line 83) | def programming_package_service
    function koditsu_programming_language_map (line 89) | def koditsu_programming_language_map

FILE: app/controllers/concerns/course/assessment/question/multiple_responses_concern.rb
  type Course::Assessment::Question::MultipleResponsesConcern (line 2) | module Course::Assessment::Question::MultipleResponsesConcern
    function switch_mcq_mrq_type (line 5) | def switch_mcq_mrq_type(is_mcq, unsubmit)
    function unsubmit_submissions (line 18) | def unsubmit_submissions

FILE: app/controllers/concerns/course/assessment/question/rubric_based_response_controller_concern.rb
  type Course::Assessment::Question::RubricBasedResponseControllerConcern (line 2) | module Course::Assessment::Question::RubricBasedResponseControllerConcern
    function create_new_category_grade_instances (line 6) | def create_new_category_grade_instances(new_category_ids)
    function update_all_submission_answer_grades (line 28) | def update_all_submission_answer_grades
    function preload_criterions_per_category (line 43) | def preload_criterions_per_category

FILE: app/controllers/concerns/course/assessment/question/rubric_based_response_question_concern.rb
  type Course::Assessment::Question::RubricBasedResponseQuestionConcern (line 2) | module Course::Assessment::Question::RubricBasedResponseQuestionConcern
    function construct_answer_score_array (line 5) | def construct_answer_score_array
    function total_grade_for (line 14) | def total_grade_for(selections, maximum_grade)
    function grade_value (line 20) | def grade_value(selection)
    function answer_object (line 24) | def answer_object(answer, total_grade)

FILE: app/controllers/concerns/course/assessment/question_bundle_assignment_concern.rb
  type Course::Assessment::QuestionBundleAssignmentConcern (line 2) | module Course::Assessment::QuestionBundleAssignmentConcern
    class AssignmentSet (line 26) | class AssignmentSet
      method initialize (line 29) | def initialize(students, group_bundles)
      method add_assignment (line 37) | def add_assignment(student, bundle)
    class AssignmentRandomizer (line 48) | class AssignmentRandomizer
      method initialize (line 51) | def initialize(assessment)
      method load (line 64) | def load
      method save (line 72) | def save(assignment_set)
      method randomize (line 90) | def randomize
      method validate (line 101) | def validate(assignment_set)
      method validate_no_overlapping_questions (line 112) | def validate_no_overlapping_questions
      method validate_no_empty_groups (line 129) | def validate_no_empty_groups
      method validate_one_bundle_assigned (line 143) | def validate_one_bundle_assigned(assignment_set)
      method validate_no_repeat_bundles (line 170) | def validate_no_repeat_bundles(assignment_set)
      method t_scoped (line 204) | def t_scoped(key, *args, **kwargs)

FILE: app/controllers/concerns/course/assessment/submission/koditsu/answers_concern.rb
  type Course::Assessment::Submission::Koditsu::AnswersConcern (line 2) | module Course::Assessment::Submission::Koditsu::AnswersConcern
    function build_answer_hash (line 5) | def build_answer_hash(answers)
    function destroy_all_existing_autogradings (line 13) | def destroy_all_existing_autogradings(answers)
    function destroy_all_existing_files (line 17) | def destroy_all_existing_files(answers)
    function update_all_submission_files (line 23) | def update_all_submission_files(submission_answers)
    function process_all_answers (line 40) | def process_all_answers(submission_answers)
    function process_all_test_case_results (line 46) | def process_all_test_case_results(submission_answers)
    function update_all_answer_status (line 63) | def update_all_answer_status(submission_answers)
    function build_answer_object (line 74) | def build_answer_object(question, answer, submitted_answer)
    function save_all_test_case_results (line 86) | def save_all_test_case_results(submission_answers)
    function new_autograding_id (line 106) | def new_autograding_id(answer)

FILE: app/controllers/concerns/course/assessment/submission/koditsu/submission_times_concern.rb
  type Course::Assessment::Submission::Koditsu::SubmissionTimesConcern (line 2) | module Course::Assessment::Submission::Koditsu::SubmissionTimesConcern
    function calculate_submission_time (line 5) | def calculate_submission_time(state, questions)
    function final_submission_time (line 17) | def final_submission_time(attempted_questions)

FILE: app/controllers/concerns/course/assessment/submission/koditsu/submissions_concern.rb
  type Course::Assessment::Submission::Koditsu::SubmissionsConcern (line 2) | module Course::Assessment::Submission::Koditsu::SubmissionsConcern
    function fetch_all_submissions_from_koditsu (line 10) | def fetch_all_submissions_from_koditsu(assessment, user)
    function process_fetch_submissions_response (line 21) | def process_fetch_submissions_response(response)
    function submission_status_hash (line 32) | def submission_status_hash
    function process_all_submissions (line 39) | def process_all_submissions
    function process_submission (line 51) | def process_submission(submission, cm_submission)
    function create_new_submissions_if_not_existing (line 61) | def create_new_submissions_if_not_existing
    function create_new_submission_for (line 78) | def create_new_submission_for(creator, course_user)
    function update_submission (line 90) | def update_submission(cm_submission, state, submitted_at)
    function process_submission_answers (line 98) | def process_submission_answers(submission, cm_submission)

FILE: app/controllers/concerns/course/assessment/submission/koditsu/test_cases_concern.rb
  type Course::Assessment::Submission::Koditsu::TestCasesConcern (line 2) | module Course::Assessment::Submission::Koditsu::TestCasesConcern
    function test_cases_order_for (line 5) | def test_cases_order_for(questions)
    function order_test_cases_type (line 14) | def order_test_cases_type
    function sort_for_koditsu (line 22) | def sort_for_koditsu(test_cases)

FILE: app/controllers/concerns/course/assessment/submission/koditsu/users_concern.rb
  type Course::Assessment::Submission::Koditsu::UsersConcern (line 2) | module Course::Assessment::Submission::Koditsu::UsersConcern
    function user_related_hash (line 5) | def user_related_hash(user_ids)
    function course_user_submission_hash (line 17) | def course_user_submission_hash(submissions)
    function email_course_user_hash (line 26) | def email_course_user_hash(emails)
    function email_submission_hash (line 39) | def email_submission_hash(submissions)

FILE: app/controllers/concerns/course/assessment/submission/monitoring_concern.rb
  type Course::Assessment::Submission::MonitoringConcern (line 2) | module Course::Assessment::Submission::MonitoringConcern
    function should_monitor? (line 11) | def should_monitor? # rubocop:disable Metrics/CyclomaticComplexity
    function monitoring_service (line 20) | def monitoring_service
    function monitoring_component_enabled? (line 28) | def monitoring_component_enabled?
    function can_update_monitoring_session? (line 32) | def can_update_monitoring_session?
    function stop_monitoring_session_if_submitted (line 36) | def stop_monitoring_session_if_submitted
    function check_blocked_by_monitor (line 40) | def check_blocked_by_monitor
    function blocked_by_monitor? (line 44) | def blocked_by_monitor?

FILE: app/controllers/concerns/course/assessment/submission/submissions_controller_service_concern.rb
  type Course::Assessment::Submission::SubmissionsControllerServiceConcern (line 2) | module Course::Assessment::Submission::SubmissionsControllerServiceConcern
    function service_class (line 10) | def service_class
    function service (line 17) | def service
    function extract_instance_variables (line 25) | def extract_instance_variables(service)
    type ClassMethods (line 32) | module ClassMethods
      function delegate_to_service (line 36) | def delegate_to_service(action)

FILE: app/controllers/concerns/course/assessment/submission_concern.rb
  type Course::Assessment::SubmissionConcern (line 2) | module Course::Assessment::SubmissionConcern
    function authorize_submission! (line 7) | def authorize_submission!
    function check_password (line 15) | def check_password
    function authentication_service (line 25) | def authentication_service
    function log_service (line 30) | def log_service
    function new_session_path (line 35) | def new_session_path

FILE: app/controllers/concerns/course/assessment_conditional_concern.rb
  type Course::AssessmentConditionalConcern (line 2) | module Course::AssessmentConditionalConcern
    function success_action (line 5) | def success_action
    function set_conditional (line 9) | def set_conditional
    function conditional_params (line 15) | def conditional_params

FILE: app/controllers/concerns/course/cikgo_chats_concern.rb
  type Course::CikgoChatsConcern (line 2) | module Course::CikgoChatsConcern
    function find_or_create_room (line 5) | def find_or_create_room(course_user)
    function get_mission_control_url (line 13) | def get_mission_control_url(course_user)
    function create_cikgo_user (line 19) | def create_cikgo_user(user)

FILE: app/controllers/concerns/course/cikgo_push_concern.rb
  type Course::CikgoPushConcern (line 2) | module Course::CikgoPushConcern
    function push_lesson_plan_items_to_remote_course (line 8) | def push_lesson_plan_items_to_remote_course
    function pushable_lesson_plan_items (line 29) | def pushable_lesson_plan_items

FILE: app/controllers/concerns/course/discussion/posts_concern.rb
  type Course::Discussion::PostsConcern (line 2) | module Course::Discussion::PostsConcern
    function update_topic_pending_status (line 18) | def update_topic_pending_status
    function skip_update_topic_status (line 29) | def skip_update_topic_status
    function create_topic_subscription (line 36) | def create_topic_subscription
    function discussion_topic (line 44) | def discussion_topic
    function post_params (line 50) | def post_params
    function set_topic (line 55) | def set_topic

FILE: app/controllers/concerns/course/forum/auto_answering_concern.rb
  type Course::Forum::AutoAnsweringConcern (line 2) | module Course::Forum::AutoAnsweringConcern
    function auto_answer_action (line 5) | def auto_answer_action(query_post, topic, is_regenerated_response: false)
    function publish_post_action (line 20) | def publish_post_action
    function last_rag_auto_answering_job (line 27) | def last_rag_auto_answering_job
    function rag_settings (line 34) | def rag_settings
    function publish_post (line 42) | def publish_post(post, topic, current_author, current_course_author)
    function create_topic_subscription (line 59) | def create_topic_subscription(topic, current_user)
    function send_created_notification (line 67) | def send_created_notification(current_author, current_course_author, p...
    function response_should_not_be_generated? (line 75) | def response_should_not_be_generated?(is_regenerated_response)

FILE: app/controllers/concerns/course/forum/topic_controller_hiding_concern.rb
  type Course::Forum::TopicControllerHidingConcern (line 2) | module Course::Forum::TopicControllerHidingConcern
    function set_hidden (line 5) | def set_hidden
    function hidden_params (line 15) | def hidden_params

FILE: app/controllers/concerns/course/forum/topic_controller_locking_concern.rb
  type Course::Forum::TopicControllerLockingConcern (line 2) | module Course::Forum::TopicControllerLockingConcern
    function set_locked (line 5) | def set_locked
    function locked_params (line 15) | def locked_params

FILE: app/controllers/concerns/course/forum/topic_controller_subscription_concern.rb
  type Course::Forum::TopicControllerSubscriptionConcern (line 2) | module Course::Forum::TopicControllerSubscriptionConcern
    function subscribe (line 5) | def subscribe
    function set_subscription_state (line 16) | def set_subscription_state
    function subscribe? (line 24) | def subscribe?

FILE: app/controllers/concerns/course/group/group_manager_concern.rb
  type Course::Group::GroupManagerConcern (line 2) | module Course::Group::GroupManagerConcern
    function manageable_groups (line 4) | def manageable_groups
    function viewable_group_categories (line 8) | def viewable_group_categories

FILE: app/controllers/concerns/course/koditsu_workspace_concern.rb
  type Course::KoditsuWorkspaceConcern (line 2) | module Course::KoditsuWorkspaceConcern
    function setup_koditsu_workspace (line 5) | def setup_koditsu_workspace

FILE: app/controllers/concerns/course/lesson_plan/acts_as_lesson_plan_item_concern.rb
  type Course::LessonPlan::ActsAsLessonPlanItemConcern (line 2) | module Course::LessonPlan::ActsAsLessonPlanItemConcern
    type ClassMethods (line 5) | module ClassMethods
      function build_and_authorize_new_lesson_plan_item (line 8) | def build_and_authorize_new_lesson_plan_item(item_name, options)

FILE: app/controllers/concerns/course/lesson_plan/learning_rate_concern.rb
  type Course::LessonPlan::LearningRateConcern (line 2) | module Course::LessonPlan::LearningRateConcern
    function lesson_plan_items_submission_time_hash (line 14) | def lesson_plan_items_submission_time_hash(course_user)
    function compute_learning_rate_ema (line 31) | def compute_learning_rate_ema(course_user, items_affecting_personal_ti...
    function compute_learning_rate_effective_limits (line 70) | def compute_learning_rate_effective_limits(course_user, items, submitt...
    function lesson_plan_items_with_sorted_times_for (line 90) | def lesson_plan_items_with_sorted_times_for(course_user)
    function merge_course_assessments (line 108) | def merge_course_assessments(hash, course_user)
    function merge_course_videos (line 125) | def merge_course_videos(hash, course_user)
    function merge_course_stories (line 135) | def merge_course_stories(hash, course_user)

FILE: app/controllers/concerns/course/lesson_plan/personalization_concern.rb
  type Course::LessonPlan::PersonalizationConcern (line 2) | module Course::LessonPlan::PersonalizationConcern
    function update_personalized_timeline_for_user (line 21) | def update_personalized_timeline_for_user(course_user, timeline_algori...
    function update_personalized_timeline_for_item (line 51) | def update_personalized_timeline_for_item(lesson_plan_item)

FILE: app/controllers/concerns/course/lesson_plan/stories_concern.rb
  type Course::LessonPlan::StoriesConcern (line 2) | module Course::LessonPlan::StoriesConcern
    function delete_all_future_stories_personal_times (line 5) | def delete_all_future_stories_personal_times(course_user)
    function stories_for (line 20) | def stories_for(course_user)

FILE: app/controllers/concerns/course/lesson_plan/strategies/base_personalization_strategy.rb
  class Course::LessonPlan::Strategies::BasePersonalizationStrategy (line 4) | class Course::LessonPlan::Strategies::BasePersonalizationStrategy
    method precompute_data (line 30) | def precompute_data(course_user) # rubocop:disable Metrics/AbcSize, Me...
    method execute (line 58) | def execute(_course_user, _precomputed_data, _items_to_shift = nil)
    method round_to_date (line 70) | def round_to_date(datetime, course_tz, to_2359: false)

FILE: app/controllers/concerns/course/lesson_plan/strategies/fixed_personalization_strategy.rb
  class Course::LessonPlan::Strategies::FixedPersonalizationStrategy (line 2) | class Course::LessonPlan::Strategies::FixedPersonalizationStrategy <
    method precompute_data (line 9) | def precompute_data(course_user)
    method execute (line 20) | def execute(course_user, precompute_data, _items_to_shift)

FILE: app/controllers/concerns/course/lesson_plan/strategies/fomo_personalization_strategy.rb
  class Course::LessonPlan::Strategies::FomoPersonalizationStrategy (line 2) | class Course::LessonPlan::Strategies::FomoPersonalizationStrategy <
    method execute (line 18) | def execute(course_user, precomputed_data, items_to_shift = nil) # rub...
    method update_points (line 55) | def update_points(course_user, item, submitted_items, reference_point,...
    method cannot_shift_item (line 78) | def cannot_shift_item(course_user, item, submitted_items, items_to_shift)
    method item_is_straggling (line 83) | def item_is_straggling(personal_time, reference_time)
    method item_is_open_and_straggling (line 100) | def item_is_open_and_straggling(personal_time, reference_time)
    method shift_start_at (line 118) | def shift_start_at(personal_time, reference_time, personal_point, refe...
    method reset_bonus_end_at (line 135) | def reset_bonus_end_at(personal_time, reference_time)
    method reset_end_at (line 146) | def reset_end_at(personal_time, reference_time)

FILE: app/controllers/concerns/course/lesson_plan/strategies/otot_personalization_strategy.rb
  class Course::LessonPlan::Strategies::OtotPersonalizationStrategy (line 2) | class Course::LessonPlan::Strategies::OtotPersonalizationStrategy <
    method precompute_data (line 10) | def precompute_data(course_user) # rubocop:disable Metrics/AbcSize, Me...
    method execute (line 43) | def execute(course_user, precomputed_data, items_to_shift = nil)

FILE: app/controllers/concerns/course/lesson_plan/strategies/stragglers_personalization_strategy.rb
  class Course::LessonPlan::Strategies::StragglersPersonalizationStrategy (line 2) | class Course::LessonPlan::Strategies::StragglersPersonalizationStrategy <
    method execute (line 19) | def execute(course_user, precomputed_data, items_to_shift = nil) # rub...
    method update_points (line 60) | def update_points(course_user, item, submitted_items, reference_point,...
    method cannot_shift_item (line 85) | def cannot_shift_item(course_user, item, submitted_items, reference_po...
    method reset_start_at (line 96) | def reset_start_at(personal_time, reference_time)
    method reset_bonus_end_at (line 107) | def reset_bonus_end_at(personal_time, reference_time)
    method shift_end_at (line 125) | def shift_end_at(personal_time, reference_time, personal_point, refere...
    method fix_items (line 154) | def fix_items(course_user, items, submitted_items)

FILE: app/controllers/concerns/course/reminder_service_concern.rb
  type Course::ReminderServiceConcern (line 2) | module Course::ReminderServiceConcern
    function name_list (line 10) | def name_list(course_users)

FILE: app/controllers/concerns/course/scholaistic/concern.rb
  type Course::Scholaistic::Concern (line 2) | module Course::Scholaistic::Concern
    function scholaistic_course_linked? (line 9) | def scholaistic_course_linked?
    function can_attempt_scholaistic_assessment? (line 14) | def can_attempt_scholaistic_assessment?(assessment)
    function sync_all_scholaistic_submissions! (line 20) | def sync_all_scholaistic_submissions!
    function primary_email_to_user_id (line 81) | def primary_email_to_user_id
    function build_assessments_hash_and_submission_ids_set (line 88) | def build_assessments_hash_and_submission_ids_set
    function user_id_to_course_user (line 110) | def user_id_to_course_user

FILE: app/controllers/concerns/course/ssid_folder_concern.rb
  type Course::SsidFolderConcern (line 2) | module Course::SsidFolderConcern
    function sync_course_ssid_folder (line 5) | def sync_course_ssid_folder(course)
    function sync_assessment_ssid_folder (line 12) | def sync_assessment_ssid_folder(course, assessment)
    function create_ssid_folder (line 24) | def create_ssid_folder(folder_name, parent_folder_id = nil)

FILE: app/controllers/concerns/course/statistics/counts_concern.rb
  type Course::Statistics::CountsConcern (line 2) | module Course::Statistics::CountsConcern
    function num_attempted_students_hash (line 7) | def num_attempted_students_hash
    function num_submitted_students_hash (line 23) | def num_submitted_students_hash
    function num_late_students_hash (line 40) | def num_late_students_hash
    function latest_submission_time_hash (line 61) | def latest_submission_time_hash
    function not_late_hash (line 79) | def not_late_hash(submissions)
    function not_late_count (line 96) | def not_late_count(submissions)
    function not_late_submission_hash (line 103) | def not_late_submission_hash(assessments, not_late_count)

FILE: app/controllers/concerns/course/statistics/grades_concern.rb
  type Course::Statistics::GradesConcern (line 2) | module Course::Statistics::GradesConcern
    function grade_statistics_hash (line 5) | def grade_statistics_hash
    function max_grade_statistics_hash (line 25) | def max_grade_statistics_hash

FILE: app/controllers/concerns/course/statistics/reference_times_concern.rb
  type Course::Statistics::ReferenceTimesConcern (line 2) | module Course::Statistics::ReferenceTimesConcern
    function personal_end_at_hash (line 5) | def personal_end_at_hash(assessment_id_array, course_id)
    function reference_times_hash (line 68) | def reference_times_hash(assessment_id_array, course_id)

FILE: app/controllers/concerns/course/statistics/submissions_concern.rb
  type Course::Statistics::SubmissionsConcern (line 2) | module Course::Statistics::SubmissionsConcern
    function initialize_student_hash (line 7) | def initialize_student_hash(students)
    function fetch_hash_for_main_assessment (line 11) | def fetch_hash_for_main_assessment(submissions, students)
    function fetch_hash_for_ancestor_assessment (line 18) | def fetch_hash_for_ancestor_assessment(submissions, students)
    function answer_statistics_hash (line 25) | def answer_statistics_hash
    function populate_hash_including_answers (line 88) | def populate_hash_including_answers(student_hash, submissions)
    function populate_hash_without_answers (line 104) | def populate_hash_without_answers(student_hash, submissions)
    function fetch_personal_and_reference_timeline_hash (line 118) | def fetch_personal_and_reference_timeline_hash

FILE: app/controllers/concerns/course/statistics/times_concern.rb
  type Course::Statistics::TimesConcern (line 2) | module Course::Statistics::TimesConcern
    function duration_statistics_hash (line 5) | def duration_statistics_hash

FILE: app/controllers/concerns/course/statistics/users_concern.rb
  type Course::Statistics::UsersConcern (line 2) | module Course::Statistics::UsersConcern
    function group_names_hash (line 5) | def group_names_hash

FILE: app/controllers/concerns/course/survey/reordering_concern.rb
  type Course::Survey::ReorderingConcern (line 2) | module Course::Survey::ReorderingConcern
    function reorder_sections (line 5) | def reorder_sections
    function reorder_questions (line 14) | def reorder_questions
    function ordered_section_ids (line 25) | def ordered_section_ids
    function reorder_params (line 32) | def reorder_params
    function valid_section_ordering? (line 40) | def valid_section_ordering?(proposed_ordering)
    function valid_question_ordering? (line 51) | def valid_question_ordering?(proposed_ordering)
    function valid_section_ids? (line 63) | def valid_section_ids?(section_ids, require_all: false)
    function valid_question_ids? (line 75) | def valid_question_ids?(question_ids)
    function update_sections_ordering (line 83) | def update_sections_ordering(ordering)
    function update_questions_ordering (line 97) | def update_questions_ordering(ordering)
    function update_question_ordering (line 114) | def update_question_ordering(question, weight, section_id)

FILE: app/controllers/concerns/course/unread_counts_concern.rb
  type Course::UnreadCountsConcern (line 2) | module Course::UnreadCountsConcern
    function unread_announcements_count (line 7) | def unread_announcements_count
    function unread_forum_topics_count (line 13) | def unread_forum_topics_count
    function unwatched_videos_count (line 19) | def unwatched_videos_count
    function pending_enrol_requests_count (line 25) | def pending_enrol_requests_count
    function pending_assessment_submissions_count (line 35) | def pending_assessment_submissions_count
    function unread_comments_count (line 47) | def unread_comments_count # rubocop:disable Metrics/PerceivedComplexit...

FILE: app/controllers/concerns/course/users_controller_management_concern.rb
  type Course::UsersControllerManagementConcern (line 2) | module Course::UsersControllerManagementConcern
    function update (line 15) | def update
    function destroy (line 27) | def destroy
    function students (line 35) | def students
    function staff (line 43) | def staff
    function upgrade_to_staff (line 52) | def upgrade_to_staff
    function assign_timeline (line 61) | def assign_timeline
    function suspend (line 84) | def suspend
    function unsuspend (line 101) | def unsuspend
    function should_update_personalized_timeline (line 120) | def should_update_personalized_timeline
    function course_user_params (line 124) | def course_user_params
    function upgrade_to_staff_params (line 130) | def upgrade_to_staff_params
    function assign_timeline_params (line 135) | def assign_timeline_params
    function suspend_params (line 139) | def suspend_params
    function unsuspend_params (line 143) | def unsuspend_params
    function load_resource (line 147) | def load_resource
    function upgrade_students_to_staff (line 159) | def upgrade_students_to_staff
    function authorize_show! (line 173) | def authorize_show!
    function authorize_edit! (line 178) | def authorize_edit!
    function update_request_origin (line 183) | def update_request_origin
    function delete_redirect_path (line 193) | def delete_redirect_path
    function upgrade_to_staff_success (line 201) | def upgrade_to_staff_success
    function upgrade_to_staff_failure (line 211) | def upgrade_to_staff_failure
    function update_user_success (line 217) | def update_user_success
    function update_user_failure (line 230) | def update_user_failure
    function destroy_user_success (line 236) | def destroy_user_success
    function destroy_user_failure (line 242) | def destroy_user_failure

FILE: app/controllers/concerns/signals/emission_concern.rb
  type Signals::EmissionConcern (line 2) | module Signals::EmissionConcern
    type ClassMethods (line 9) | module ClassMethods
      function signals (line 12) | def signals(slice_name, options = {})
    function slice_class_name (line 28) | def slice_class_name(slice_name)
    function slice_class (line 32) | def slice_class(slice_name)
    function generate_sync_method_name (line 36) | def generate_sync_method_name(slice_name)

FILE: app/controllers/concerns/signals/slices/announcements.rb
  type Signals::Slices::Announcements (line 2) | module Signals::Slices::Announcements
    function generate_sync_for_announcements (line 5) | def generate_sync_for_announcements

FILE: app/controllers/concerns/signals/slices/assessment_submissions.rb
  type Signals::Slices::AssessmentSubmissions (line 2) | module Signals::Slices::AssessmentSubmissions
    function generate_sync_for_assessment_submissions (line 5) | def generate_sync_for_assessment_submissions

FILE: app/controllers/concerns/signals/slices/cikgo_mission_control.rb
  type Signals::Slices::CikgoMissionControl (line 2) | module Signals::Slices::CikgoMissionControl
    function generate_sync_for_cikgo_mission_control (line 3) | def generate_sync_for_cikgo_mission_control

FILE: app/controllers/concerns/signals/slices/cikgo_open_threads_count.rb
  type Signals::Slices::CikgoOpenThreadsCount (line 2) | module Signals::Slices::CikgoOpenThreadsCount
    function generate_sync_for_cikgo_open_threads_count (line 3) | def generate_sync_for_cikgo_open_threads_count

FILE: app/controllers/concerns/signals/slices/comments.rb
  type Signals::Slices::Comments (line 2) | module Signals::Slices::Comments
    function generate_sync_for_comments (line 5) | def generate_sync_for_comments

FILE: app/controllers/concerns/signals/slices/enrol_requests.rb
  type Signals::Slices::EnrolRequests (line 2) | module Signals::Slices::EnrolRequests
    function generate_sync_for_enrol_requests (line 5) | def generate_sync_for_enrol_requests

FILE: app/controllers/concerns/signals/slices/forums.rb
  type Signals::Slices::Forums (line 2) | module Signals::Slices::Forums
    function generate_sync_for_forums (line 5) | def generate_sync_for_forums

FILE: app/controllers/concerns/signals/slices/videos.rb
  type Signals::Slices::Videos (line 2) | module Signals::Slices::Videos
    function generate_sync_for_videos (line 5) | def generate_sync_for_videos

FILE: app/controllers/course/achievement/achievements_controller.rb
  class Course::Achievement::AchievementsController (line 2) | class Course::Achievement::AchievementsController < Course::Achievement:...
    method index (line 5) | def index
    method show (line 9) | def show
    method create (line 16) | def create
    method update (line 26) | def update
    method destroy (line 39) | def destroy
    method reorder (line 47) | def reorder
    method achievement_course_users (line 59) | def achievement_course_users
    method achievement_params (line 77) | def achievement_params
    method achievement_order_params (line 85) | def achievement_order_params
    method authorize_achievement! (line 90) | def authorize_achievement!
    method achievements_hash (line 97) | def achievements_hash
    method valid_ordering? (line 107) | def valid_ordering?(proposed_ordering)

FILE: app/controllers/course/achievement/condition/achievements_controller.rb
  class Course::Achievement::Condition::AchievementsController (line 2) | class Course::Achievement::Condition::AchievementsController <

FILE: app/controllers/course/achievement/condition/assessments_controller.rb
  class Course::Achievement::Condition::AssessmentsController (line 2) | class Course::Achievement::Condition::AssessmentsController <

FILE: app/controllers/course/achievement/condition/levels_controller.rb
  class Course::Achievement::Condition::LevelsController (line 2) | class Course::Achievement::Condition::LevelsController < Course::Conditi...

FILE: app/controllers/course/achievement/condition/scholaistic_assessments_controller.rb
  class Course::Achievement::Condition::ScholaisticAssessmentsController (line 2) | class Course::Achievement::Condition::ScholaisticAssessmentsController <

FILE: app/controllers/course/achievement/condition/surveys_controller.rb
  class Course::Achievement::Condition::SurveysController (line 2) | class Course::Achievement::Condition::SurveysController < Course::Condit...

FILE: app/controllers/course/achievement/controller.rb
  class Course::Achievement::Controller (line 2) | class Course::Achievement::Controller < Course::ComponentController
    method component (line 11) | def component

FILE: app/controllers/course/admin/admin_controller.rb
  class Course::Admin::AdminController (line 2) | class Course::Admin::AdminController < Course::Admin::Controller
    method index (line 3) | def index
    method update (line 9) | def update
    method destroy (line 24) | def destroy
    method suspend (line 33) | def suspend
    method unsuspend (line 39) | def unsuspend
    method course_setting_params (line 47) | def course_setting_params
    method destroy_success (line 58) | def destroy_success
    method destroy_failure (line 62) | def destroy_failure
    method shift_all_items (line 66) | def shift_all_items
    method time_offset_params (line 78) | def time_offset_params

FILE: app/controllers/course/admin/announcement_settings_controller.rb
  class Course::Admin::AnnouncementSettingsController (line 2) | class Course::Admin::AnnouncementSettingsController < Course::Admin::Con...
    method edit (line 3) | def edit
    method update (line 9) | def update
    method announcement_settings_params (line 19) | def announcement_settings_params
    method component (line 23) | def component

FILE: app/controllers/course/admin/assessment_settings_controller.rb
  class Course::Admin::AssessmentSettingsController (line 2) | class Course::Admin::AssessmentSettingsController < Course::Admin::Contr...
    method edit (line 3) | def edit
    method update (line 9) | def update
    method move_assessments (line 17) | def move_assessments
    method move_tabs (line 36) | def move_tabs
    method move_assessments_params (line 56) | def move_assessments_params
    method move_tabs_params (line 60) | def move_tabs_params
    method category_params (line 64) | def category_params
    method component (line 88) | def component

FILE: app/controllers/course/admin/assessments/categories_controller.rb
  class Course::Admin::Assessments::CategoriesController (line 2) | class Course::Admin::Assessments::CategoriesController < Course::Admin::...
    method new (line 8) | def new
    method create (line 11) | def create
    method destroy (line 19) | def destroy
    method category_params (line 34) | def category_params
    method component (line 40) | def component

FILE: app/controllers/course/admin/assessments/tabs_controller.rb
  class Course::Admin::Assessments::TabsController (line 2) | class Course::Admin::Assessments::TabsController < Course::Admin::Contro...
    method new (line 11) | def new
    method create (line 14) | def create
    method destroy (line 22) | def destroy
    method tab_params (line 34) | def tab_params
    method component (line 40) | def component

FILE: app/controllers/course/admin/codaveri_settings_controller.rb
  class Course::Admin::CodaveriSettingsController (line 2) | class Course::Admin::CodaveriSettingsController < Course::Admin::Controller
    method edit (line 3) | def edit
    method assessment (line 7) | def assessment
    method update (line 12) | def update
    method update_evaluator (line 24) | def update_evaluator
    method update_live_feedback_enabled (line 31) | def update_live_feedback_enabled
    method assessment_params (line 40) | def assessment_params
    method codaveri_settings_params (line 44) | def codaveri_settings_params
    method update_evaluator_params (line 51) | def update_evaluator_params
    method update_live_feedback_enabled_params (line 55) | def update_live_feedback_enabled_params
    method component (line 59) | def component
    method load_course_assessments_data (line 63) | def load_course_assessments_data

FILE: app/controllers/course/admin/component_settings_controller.rb
  class Course::Admin::ComponentSettingsController (line 2) | class Course::Admin::ComponentSettingsController < Course::Admin::Contro...
    method edit (line 7) | def edit
    method update (line 13) | def update # rubocop:disable Metrics/AbcSize
    method settings_components_params (line 31) | def settings_components_params
    method load_settings (line 36) | def load_settings

FILE: app/controllers/course/admin/controller.rb
  class Course::Admin::Controller (line 2) | class Course::Admin::Controller < Course::ComponentController
    method authorize_admin (line 7) | def authorize_admin
    method component (line 13) | def component

FILE: app/controllers/course/admin/discussion/topic_settings_controller.rb
  class Course::Admin::Discussion::TopicSettingsController (line 2) | class Course::Admin::Discussion::TopicSettingsController < Course::Admin...
    method edit (line 3) | def edit
    method update (line 9) | def update
    method topic_settings_params (line 19) | def topic_settings_params
    method component (line 23) | def component

FILE: app/controllers/course/admin/forum_settings_controller.rb
  class Course::Admin::ForumSettingsController (line 2) | class Course::Admin::ForumSettingsController < Course::Admin::Controller
    method edit (line 3) | def edit
    method update (line 9) | def update
    method forum_settings_params (line 19) | def forum_settings_params
    method component (line 24) | def component

FILE: app/controllers/course/admin/leaderboard_settings_controller.rb
  class Course::Admin::LeaderboardSettingsController (line 2) | class Course::Admin::LeaderboardSettingsController < Course::Admin::Cont...
    method edit (line 3) | def edit
    method update (line 9) | def update
    method leaderboard_settings_params (line 19) | def leaderboard_settings_params
    method component (line 24) | def component

FILE: app/controllers/course/admin/lesson_plan_settings_controller.rb
  class Course::Admin::LessonPlanSettingsController (line 2) | class Course::Admin::LessonPlanSettingsController < Course::Admin::Contr...
    method edit (line 5) | def edit
    method update (line 11) | def update
    method update_lesson_plan_items_settings (line 23) | def update_lesson_plan_items_settings
    method update_lesson_plan_component_settings (line 28) | def update_lesson_plan_component_settings
    method lesson_plan_item_settings_params (line 33) | def lesson_plan_item_settings_params
    method load_item_settings (line 40) | def load_item_settings
    method page_data (line 44) | def page_data
    method component (line 51) | def component

FILE: app/controllers/course/admin/material_settings_controller.rb
  class Course::Admin::MaterialSettingsController (line 2) | class Course::Admin::MaterialSettingsController < Course::Admin::Controller
    method edit (line 3) | def edit
    method update (line 9) | def update
    method material_settings_params (line 19) | def material_settings_params
    method component (line 23) | def component

FILE: app/controllers/course/admin/notification_settings_controller.rb
  class Course::Admin::NotificationSettingsController (line 2) | class Course::Admin::NotificationSettingsController < Course::Admin::Con...
    method edit (line 3) | def edit
    method update (line 9) | def update
    method page_data (line 19) | def page_data
    method notification_settings_params (line 23) | def notification_settings_params
    method notification_enabled_params (line 27) | def notification_enabled_params

FILE: app/controllers/course/admin/rag_wise_settings_controller.rb
  class Course::Admin::RagWiseSettingsController (line 2) | class Course::Admin::RagWiseSettingsController < Course::Admin::Controller
    method edit (line 5) | def edit
    method update (line 11) | def update
    method materials (line 19) | def materials
    method folders (line 24) | def folders
    method courses (line 28) | def courses
    method forums (line 42) | def forums
    method import_course_forums (line 54) | def import_course_forums
    method destroy_imported_discussions (line 73) | def destroy_imported_discussions
    method authorize_import_forums (line 84) | def authorize_import_forums
    method set_parent_courses (line 89) | def set_parent_courses
    method rag_wise_settings_params (line 104) | def rag_wise_settings_params
    method import_course_forum_params (line 108) | def import_course_forum_params
    method component (line 112) | def component
    method last_forum_importing_job (line 116) | def last_forum_importing_job

FILE: app/controllers/course/admin/scholaistic_settings_controller.rb
  class Course::Admin::ScholaisticSettingsController (line 2) | class Course::Admin::ScholaisticSettingsController < Course::Admin::Cont...
    method edit (line 6) | def edit
    method update (line 10) | def update
    method confirm_link_course (line 18) | def confirm_link_course
    method link_course (line 25) | def link_course
    method unlink_course (line 37) | def unlink_course
    method publicly_accessible? (line 56) | def publicly_accessible?
    method scholaistic_settings_params (line 62) | def scholaistic_settings_params
    method component (line 66) | def component
    method render_settings (line 70) | def render_settings

FILE: app/controllers/course/admin/sidebar_settings_controller.rb
  class Course::Admin::SidebarSettingsController (line 2) | class Course::Admin::SidebarSettingsController < Course::Admin::Controller
    method edit (line 5) | def edit
    method update (line 11) | def update
    method settings_sidebar_params (line 21) | def settings_sidebar_params
    method load_settings (line 26) | def load_settings

FILE: app/controllers/course/admin/stories_settings_controller.rb
  class Course::Admin::StoriesSettingsController (line 2) | class Course::Admin::StoriesSettingsController < Course::Admin::Controller
    method edit (line 8) | def edit
    method update (line 11) | def update
    method ping_remote_course (line 24) | def ping_remote_course
    method stories_settings_params (line 33) | def stories_settings_params
    method component (line 37) | def component

FILE: app/controllers/course/admin/video_settings_controller.rb
  class Course::Admin::VideoSettingsController (line 2) | class Course::Admin::VideoSettingsController < Course::Admin::Controller
    method edit (line 3) | def edit
    method update (line 9) | def update
    method video_settings_params (line 21) | def video_settings_params
    method video_tabs_params (line 25) | def video_tabs_params
    method component (line 32) | def component

FILE: app/controllers/course/admin/videos/tabs_controller.rb
  class Course::Admin::Videos::TabsController (line 2) | class Course::Admin::Videos::TabsController < Course::Admin::Controller
    method new (line 8) | def new
    method create (line 11) | def create
    method destroy (line 19) | def destroy
    method tab_params (line 29) | def tab_params
    method component (line 35) | def component

FILE: app/controllers/course/announcements_controller.rb
  class Course::AnnouncementsController (line 2) | class Course::AnnouncementsController < Course::ComponentController
    method index (line 12) | def index
    method create (line 21) | def create
    method update (line 30) | def update
    method destroy (line 40) | def destroy
    method announcement_params (line 50) | def announcement_params
    method component (line 56) | def component
    method mark_announcements_as_read (line 60) | def mark_announcements_as_read

FILE: app/controllers/course/assessment/assessments_controller.rb
  class Course::Assessment::AssessmentsController (line 2) | class Course::Assessment::AssessmentsController < Course::Assessment::Co...
    method index (line 18) | def index
    method show (line 35) | def show
    method new (line 51) | def new
    method create (line 54) | def create
    method edit (line 70) | def edit
    method update (line 79) | def update
    method destroy (line 97) | def destroy
    method sync_with_koditsu (line 109) | def sync_with_koditsu
    method invite_to_koditsu (line 148) | def invite_to_koditsu
    method reorder (line 167) | def reorder
    method authenticate (line 185) | def authenticate
    method remind (line 194) | def remind
    method auto_feedback_count (line 206) | def auto_feedback_count
    method publish_auto_feedback (line 215) | def publish_auto_feedback
    method requirements (line 232) | def requirements
    method statistics (line 241) | def statistics
    method plagiarism (line 246) | def plagiarism
    method load_assessment_options (line 252) | def load_assessment_options
    method load_assessment_submission_counts (line 260) | def load_assessment_submission_counts
    method question_order_ids (line 265) | def question_order_ids
    method assessment_params (line 272) | def assessment_params
    method auto_feedback_count_params (line 286) | def auto_feedback_count_params
    method publish_auto_feedback_params (line 290) | def publish_auto_feedback_params
    method autograded_params (line 294) | def autograded_params
    method autograded? (line 304) | def autograded?
    method tab_params (line 316) | def tab_params
    method skip_tab_filter? (line 325) | def skip_tab_filter?
    method tab (line 329) | def tab
    method category (line 340) | def category
    method load_question_duplication_data (line 351) | def load_question_duplication_data
    method question_assessments_hash (line 358) | def question_assessments_hash
    method valid_ordering? (line 368) | def valid_ordering?(proposed_ordering)
    method create_koditsu_invitation_job (line 372) | def create_koditsu_invitation_job
    method execute_koditsu_invitation_job_later (line 387) | def execute_koditsu_invitation_job_later
    method create_fetch_koditsu_submissions_job (line 393) | def create_fetch_koditsu_submissions_job
    method compound_tab_titles (line 410) | def compound_tab_titles
    method ordered_assessments_by_tab (line 428) | def ordered_assessments_by_tab
    method student_course_users (line 443) | def student_course_users
    method can_access_assessment? (line 447) | def can_access_assessment?
    method authentication_service (line 453) | def authentication_service
    method submissions (line 457) | def submissions
    method draft_file_annotation_posts (line 467) | def draft_file_annotation_posts(course_users)

FILE: app/controllers/course/assessment/categories_controller.rb
  class Course::Assessment::CategoriesController (line 2) | class Course::Assessment::CategoriesController < Course::ComponentContro...
    method index (line 11) | def index; end
    method component (line 20) | def component

FILE: app/controllers/course/assessment/component_controller.rb
  class Course::Assessment::ComponentController (line 2) | class Course::Assessment::ComponentController < Course::Assessment::Cont...

FILE: app/controllers/course/assessment/condition/achievements_controller.rb
  class Course::Assessment::Condition::AchievementsController (line 2) | class Course::Assessment::Condition::AchievementsController <

FILE: app/controllers/course/assessment/condition/assessments_controller.rb
  class Course::Assessment::Condition::AssessmentsController (line 2) | class Course::Assessment::Condition::AssessmentsController <

FILE: app/controllers/course/assessment/condition/levels_controller.rb
  class Course::Assessment::Condition::LevelsController (line 2) | class Course::Assessment::Condition::LevelsController < Course::Conditio...

FILE: app/controllers/course/assessment/condition/scholaistic_assessments_controller.rb
  class Course::Assessment::Condition::ScholaisticAssessmentsController (line 2) | class Course::Assessment::Condition::ScholaisticAssessmentsController <

FILE: app/controllers/course/assessment/condition/surveys_controller.rb
  class Course::Assessment::Condition::SurveysController (line 2) | class Course::Assessment::Condition::SurveysController < Course::Conditi...

FILE: app/controllers/course/assessment/controller.rb
  class Course::Assessment::Controller (line 2) | class Course::Assessment::Controller < Course::ComponentController
    method load_assessment_options (line 10) | def load_assessment_options
    method category (line 14) | def category
    method tab (line 18) | def tab
    method load_category_and_tab (line 24) | def load_category_and_tab
    method load_and_authorize_assessment (line 29) | def load_and_authorize_assessment
    method component (line 37) | def component

FILE: app/controllers/course/assessment/mock_answers_controller.rb
  class Course::Assessment::MockAnswersController (line 2) | class Course::Assessment::MockAnswersController < Course::Assessment::Qu...
    method create (line 5) | def create
    method mock_answer_params (line 16) | def mock_answer_params

FILE: app/controllers/course/assessment/question/controller.rb
  class Course::Assessment::Question::Controller (line 2) | class Course::Assessment::Question::Controller < Course::Assessment::Com...
    method build_and_authorize_new_question (line 14) | def self.build_and_authorize_new_question(question_name, options)
    method authorize_create_question_in_koditsu (line 28) | def authorize_create_question_in_koditsu
    method flag_not_synced_with_koditsu (line 35) | def flag_not_synced_with_koditsu
    method load_question_assessment_for (line 43) | def load_question_assessment_for(question)
    method update_skill_ids_if_params_present (line 47) | def update_skill_ids_if_params_present(question_assessment_params)
    method destroy (line 52) | def destroy
    method authorize_assessment (line 58) | def authorize_assessment

FILE: app/controllers/course/assessment/question/forum_post_responses_controller.rb
  class Course::Assessment::Question::ForumPostResponsesController (line 2) | class Course::Assessment::Question::ForumPostResponsesController < Cours...
    method create (line 10) | def create
    method edit (line 18) | def edit
    method update (line 25) | def update
    method destroy (line 35) | def destroy
    method update_forum_post_response_question (line 48) | def update_forum_post_response_question
    method forum_post_response_question_params (line 52) | def forum_post_response_question_params
    method load_question_assessment (line 60) | def load_question_assessment

FILE: app/controllers/course/assessment/question/multiple_responses_controller.rb
  class Course::Assessment::Question::MultipleResponsesController (line 2) | class Course::Assessment::Question::MultipleResponsesController < Course...
    method new (line 11) | def new
    method create (line 15) | def create
    method edit (line 28) | def edit
    method update (line 31) | def update
    method destroy (line 51) | def destroy
    method generate (line 62) | def generate
    method respond_to_switch_mcq_mrq_type (line 88) | def respond_to_switch_mcq_mrq_type
    method update_multiple_response_question (line 104) | def update_multiple_response_question
    method multiple_response_question_params (line 110) | def multiple_response_question_params
    method load_question_assessment (line 119) | def load_question_assessment
    method parse_generation_params (line 123) | def parse_generation_params
    method parse_source_question_data (line 132) | def parse_source_question_data
    method validate_generation_params (line 140) | def validate_generation_params(params)
    method format_generation_response (line 146) | def format_generation_response(questions)
    method format_options (line 159) | def format_options(options)
    method format_question (line 173) | def format_question(question)

FILE: app/controllers/course/assessment/question/programming_controller.rb
  class Course::Assessment::Question::ProgrammingController (line 2) | class Course::Assessment::Question::ProgrammingController < Course::Asse...
    method new (line 14) | def new
    method create (line 20) | def create
    method edit (line 33) | def edit
    method update (line 42) | def update
    method import_result (line 63) | def import_result
    method codaveri_languages (line 67) | def codaveri_languages
    method generate (line 75) | def generate
    method update_question_setting (line 96) | def update_question_setting
    method destroy (line 105) | def destroy
    method format_test_cases (line 118) | def format_test_cases
    method set_attributes_for_programming_question (line 130) | def set_attributes_for_programming_question
    method programming_question_params (line 134) | def programming_question_params
    method programming_question_setting_params (line 144) | def programming_question_setting_params
    method render_success_json (line 148) | def render_success_json(redirect_to_edit)
    method render_failure_json (line 152) | def render_failure_json
    method process_package (line 156) | def process_package
    method programming_package_service (line 164) | def programming_package_service(params = nil)
    method load_question_assessment (line 170) | def load_question_assessment

FILE: app/controllers/course/assessment/question/rubric_based_responses_controller.rb
  class Course::Assessment::Question::RubricBasedResponsesController (line 2) | class Course::Assessment::Question::RubricBasedResponsesController < Cou...
    method create (line 16) | def create
    method edit (line 31) | def edit
    method update (line 43) | def update
    method destroy (line 54) | def destroy
    method migrate_rubric (line 65) | def migrate_rubric
    method add_bonus_category_to_rubric_based_question (line 73) | def add_bonus_category_to_rubric_based_question
    method update_rubric_based_response_question (line 92) | def update_rubric_based_response_question
    method rubric_based_response_question_params (line 105) | def rubric_based_response_question_params
    method load_question_assessment (line 117) | def load_question_assessment

FILE: app/controllers/course/assessment/question/scribing_controller.rb
  class Course::Assessment::Question::ScribingController (line 2) | class Course::Assessment::Question::ScribingController < Course::Assessm...
    method new (line 10) | def new
    method show (line 16) | def show
    method create (line 22) | def create # rubocop:disable Metrics/MethodLength
    method edit (line 42) | def edit
    method update (line 50) | def update
    method destroy (line 61) | def destroy
    method scribing_question_params (line 74) | def scribing_question_params
    method render_scribing_question_json (line 81) | def render_scribing_question_json
    method render_success_json (line 86) | def render_success_json(message)
    method render_failure_json (line 90) | def render_failure_json(message)
    method file_is_pdf? (line 95) | def file_is_pdf?
    method pdf_import_service (line 99) | def pdf_import_service
    method load_question_assessment (line 103) | def load_question_assessment

FILE: app/controllers/course/assessment/question/text_responses_controller.rb
  class Course::Assessment::Question::TextResponsesController (line 2) | class Course::Assessment::Question::TextResponsesController < Course::As...
    method new (line 10) | def new
    method create (line 20) | def create
    method edit (line 28) | def edit
    method update (line 37) | def update
    method destroy (line 47) | def destroy
    method update_text_response_question (line 60) | def update_text_response_question
    method text_response_question_params (line 66) | def text_response_question_params
    method load_question_assessment (line 97) | def load_question_assessment

FILE: app/controllers/course/assessment/question/voice_responses_controller.rb
  class Course::Assessment::Question::VoiceResponsesController (line 2) | class Course::Assessment::Question::VoiceResponsesController < Course::A...
    method create (line 10) | def create
    method new (line 18) | def new
    method update (line 21) | def update
    method edit (line 31) | def edit
    method destroy (line 34) | def destroy
    method update_voice_response_question (line 47) | def update_voice_response_question
    method voice_response_question_params (line 51) | def voice_response_question_params
    method load_question_assessment (line 59) | def load_question_assessment

FILE: app/controllers/course/assessment/question_bundle_assignments_controller.rb
  class Course::Assessment::QuestionBundleAssignmentsController (line 2) | class Course::Assessment::QuestionBundleAssignmentsController < Course::...
    method index (line 7) | def index
    method create (line 26) | def create
    method edit (line 46) | def edit
    method update (line 49) | def update
    method destroy (line 57) | def destroy
    method recompute (line 66) | def recompute
    method past_assignments_hash (line 81) | def past_assignments_hash

FILE: app/controllers/course/assessment/question_bundle_questions_controller.rb
  class Course::Assessment::QuestionBundleQuestionsController (line 2) | class Course::Assessment::QuestionBundleQuestionsController < Course::As...
    method index (line 7) | def index
    method new (line 16) | def new
    method create (line 20) | def create
    method edit (line 29) | def edit
    method update (line 32) | def update
    method destroy (line 40) | def destroy
    method question_bundle_question_params (line 51) | def question_bundle_question_params

FILE: app/controllers/course/assessment/question_bundles_controller.rb
  class Course::Assessment::QuestionBundlesController (line 2) | class Course::Assessment::QuestionBundlesController < Course::Assessment...
    method index (line 5) | def index
    method new (line 8) | def new
    method create (line 11) | def create
    method edit (line 19) | def edit
    method update (line 22) | def update
    method destroy (line 30) | def destroy
    method question_bundle_params (line 42) | def question_bundle_params

FILE: app/controllers/course/assessment/question_groups_controller.rb
  class Course::Assessment::QuestionGroupsController (line 2) | class Course::Assessment::QuestionGroupsController < Course::Assessment:...
    method index (line 5) | def index
    method new (line 9) | def new
    method create (line 12) | def create
    method edit (line 20) | def edit
    method update (line 23) | def update
    method destroy (line 31) | def destroy
    method question_group_params (line 42) | def question_group_params

FILE: app/controllers/course/assessment/questions_controller.rb
  class Course::Assessment::QuestionsController (line 2) | class Course::Assessment::QuestionsController < Course::Assessment::Cont...
    method duplicate (line 10) | def duplicate
    method show (line 20) | def show
    method load_and_authorize_assessments (line 26) | def load_and_authorize_assessments
    method duplicated_question (line 37) | def duplicated_question
    method duplicate_question_and_skills (line 42) | def duplicate_question_and_skills

FILE: app/controllers/course/assessment/rubrics_controller.rb
  class Course::Assessment::RubricsController (line 2) | class Course::Assessment::RubricsController < Course::Assessment::Questi...
    method index (line 5) | def index
    method show (line 16) | def show
    method create (line 20) | def create
    method destroy (line 30) | def destroy
    method rubric_answers (line 34) | def rubric_answers
    method fetch_answer_evaluations (line 40) | def fetch_answer_evaluations
    method fetch_mock_answer_evaluations (line 44) | def fetch_mock_answer_evaluations
    method initialize_answer_evaluations (line 48) | def initialize_answer_evaluations
    method initialize_mock_answer_evaluations (line 63) | def initialize_mock_answer_evaluations
    method evaluate_mock_answer (line 80) | def evaluate_mock_answer
    method evaluate_answer (line 99) | def evaluate_answer # rubocop:disable Metrics/AbcSize
    method delete_answer_evaluations (line 120) | def delete_answer_evaluations
    method delete_mock_answer_evaluations (line 125) | def delete_mock_answer_evaluations
    method export_evaluations (line 135) | def export_evaluations
    method create_params (line 144) | def create_params
    method initialize_mock_answer_evaluations_params (line 154) | def initialize_mock_answer_evaluations_params

FILE: app/controllers/course/assessment/sessions_controller.rb
  class Course::Assessment::SessionsController (line 2) | class Course::Assessment::SessionsController < Course::Assessment::Contr...
    method new (line 5) | def new
    method create (line 8) | def create
    method load_and_authorize_submission (line 18) | def load_and_authorize_submission
    method load_submission (line 23) | def load_submission
    method redirect_or_create_submission (line 33) | def redirect_or_create_submission
    method create_params (line 43) | def create_params
    method authentication_service (line 47) | def authentication_service
    method log_service (line 52) | def log_service

FILE: app/controllers/course/assessment/skill_branches_controller.rb
  class Course::Assessment::SkillBranchesController (line 2) | class Course::Assessment::SkillBranchesController < Course::ComponentCon...
    method create (line 7) | def create
    method update (line 15) | def update
    method destroy (line 23) | def destroy
    method skill_branch_params (line 33) | def skill_branch_params
    method component (line 39) | def component

FILE: app/controllers/course/assessment/skills_controller.rb
  class Course::Assessment::SkillsController (line 2) | class Course::Assessment::SkillsController < Course::ComponentController
    method index (line 7) | def index
    method create (line 14) | def create
    method update (line 22) | def update
    method destroy (line 30) | def destroy
    method options (line 38) | def options
    method skill_params (line 46) | def skill_params
    method load_skill_branches (line 50) | def load_skill_branches
    method component (line 57) | def component

FILE: app/controllers/course/assessment/submission/answer/answers_controller.rb
  class Course::Assessment::Submission::Answer::AnswersController (line 3) | class Course::Assessment::Submission::Answer::AnswersController <
    method show (line 11) | def show
    method update (line 15) | def update
    method submit_answer (line 25) | def submit_answer
    method answer_params (line 41) | def answer_params
    method should_auto_grade_on_submit (line 45) | def should_auto_grade_on_submit(answer)
    method auto_grade (line 54) | def auto_grade(answer)
    method valid_for_grading? (line 67) | def valid_for_grading?(answer)
    method last_attempt_answer_submitted_job (line 74) | def last_attempt_answer_submitted_job(answer)
    method reattempt_and_grade_answer (line 83) | def reattempt_and_grade_answer(answer)
    method reattempt_answer (line 98) | def reattempt_answer(answer, finalise: true)

FILE: app/controllers/course/assessment/submission/answer/controller.rb
  class Course::Assessment::Submission::Answer::Controller (line 2) | class Course::Assessment::Submission::Answer::Controller < \

FILE: app/controllers/course/assessment/submission/answer/forum_post_response/posts_controller.rb
  class Course::Assessment::Submission::Answer::ForumPostResponse::PostsController (line 2) | class Course::Assessment::Submission::Answer::ForumPostResponse::PostsCo...
    method selected (line 4) | def selected
    method post_params (line 10) | def post_params

FILE: app/controllers/course/assessment/submission/answer/programming/annotations_controller.rb
  class Course::Assessment::Submission::Answer::Programming::AnnotationsController (line 2) | class Course::Assessment::Submission::Answer::Programming::AnnotationsCo...
    method create (line 19) | def create
    method annotation_params (line 39) | def annotation_params
    method load_existing_annotation (line 43) | def load_existing_annotation
    method line_param (line 52) | def line_param
    method discussion_topic (line 58) | def discussion_topic
    method create_topic_subscription (line 62) | def create_topic_subscription
    method send_created_notification (line 75) | def send_created_notification(post)
    method render_create_response (line 81) | def render_create_response

FILE: app/controllers/course/assessment/submission/answer/programming/controller.rb
  class Course::Assessment::Submission::Answer::Programming::Controller (line 2) | class Course::Assessment::Submission::Answer::Programming::Controller < \
    method set_programming_answer (line 6) | def set_programming_answer

FILE: app/controllers/course/assessment/submission/answer/programming/programming_controller.rb
  class Course::Assessment::Submission::Answer::Programming::ProgrammingController (line 2) | class Course::Assessment::Submission::Answer::Programming::ProgrammingCo...
    method create_programming_files (line 8) | def create_programming_files
    method destroy_programming_file (line 18) | def destroy_programming_file
    method create_programming_files_params (line 31) | def create_programming_files_params
    method delete_programming_file_params (line 35) | def delete_programming_file_params
    method update_answer_files_attributes (line 39) | def update_answer_files_attributes(answer_params)
    method delete_programming_file (line 43) | def delete_programming_file(file_id)

FILE: app/controllers/course/assessment/submission/answer/scribing/controller.rb
  class Course::Assessment::Submission::Answer::Scribing::Controller (line 2) | class Course::Assessment::Submission::Answer::Scribing::Controller < \
    method set_scribing_answer (line 10) | def set_scribing_answer

FILE: app/controllers/course/assessment/submission/answer/scribing/scribbles_controller.rb
  class Course::Assessment::Submission::Answer::Scribing::ScribblesController (line 2) | class Course::Assessment::Submission::Answer::Scribing::ScribblesControl...
    method create (line 6) | def create
    method scribble_params (line 21) | def scribble_params
    method load_scribble (line 25) | def load_scribble

FILE: app/controllers/course/assessment/submission/answer/text_response/controller.rb
  class Course::Assessment::Submission::Answer::TextResponse::Controller (line 2) | class Course::Assessment::Submission::Answer::TextResponse::Controller < \
    method set_text_response_answer (line 6) | def set_text_response_answer

FILE: app/controllers/course/assessment/submission/answer/text_response/text_response_controller.rb
  class Course::Assessment::Submission::Answer::TextResponse::TextResponseController (line 2) | class Course::Assessment::Submission::Answer::TextResponse::TextResponse...
    method create_files (line 8) | def create_files
    method delete_file (line 20) | def delete_file
    method create_files_params (line 34) | def create_files_params
    method delete_file_params (line 38) | def delete_file_params

FILE: app/controllers/course/assessment/submission/controller.rb
  class Course::Assessment::Submission::Controller (line 2) | class Course::Assessment::Submission::Controller < Course::Assessment::C...

FILE: app/controllers/course/assessment/submission/live_feedback_controller.rb
  class Course::Assessment::Submission::LiveFeedbackController (line 3) | class Course::Assessment::Submission::LiveFeedbackController <
    method save_live_feedback (line 5) | def save_live_feedback
    method save_new_feedback (line 20) | def save_new_feedback(content, is_error)
    method associate_new_message_with_existing_files (line 35) | def associate_new_message_with_existing_files

FILE: app/controllers/course/assessment/submission/logs_controller.rb
  class Course::Assessment::Submission::LogsController (line 2) | class Course::Assessment::Submission::LogsController < \
    method index (line 5) | def index

FILE: app/controllers/course/assessment/submission/submissions_controller.rb
  class Course::Assessment::Submission::SubmissionsController (line 2) | class Course::Assessment::Submission::SubmissionsController < # rubocop:...
    method index (line 30) | def index
    method create (line 39) | def create # rubocop:disable Metrics/AbcSize
    method edit (line 61) | def edit
    method auto_grade (line 69) | def auto_grade
    method reevaluate_answer (line 76) | def reevaluate_answer
    method generate_feedback (line 85) | def generate_feedback
    method generate_live_feedback (line 94) | def generate_live_feedback
    method fetch_live_feedback_chat (line 126) | def fetch_live_feedback_chat
    method create_live_feedback_chat (line 140) | def create_live_feedback_chat
    method fetch_live_feedback_status (line 152) | def fetch_live_feedback_status
    method reload_answer (line 170) | def reload_answer
    method publish_all (line 186) | def publish_all
    method force_submit_all (line 200) | def force_submit_all
    method fetch_submissions_from_koditsu (line 214) | def fetch_submissions_from_koditsu
    method download_all (line 232) | def download_all
    method download_statistics (line 241) | def download_statistics
    method unsubmit (line 256) | def unsubmit
    method unsubmit_all (line 274) | def unsubmit_all
    method delete (line 285) | def delete
    method reset_question_bundle_assignments (line 301) | def reset_question_bundle_assignments
    method delete_all (line 306) | def delete_all
    method create_params (line 319) | def create_params
    method live_feedback_params (line 323) | def live_feedback_params
    method create_success_response (line 327) | def create_success_response(submission)
    method authorize_assessment! (line 342) | def authorize_assessment!
    method reload_answer_params (line 346) | def reload_answer_params
    method answer_params (line 350) | def answer_params
    method thread_params (line 354) | def thread_params
    method not_downloadable (line 358) | def not_downloadable
    method download_job (line 364) | def download_job
    method check_zombie_jobs (line 376) | def check_zombie_jobs # rubocop:disable Metrics/AbcSize, Metrics/Perce...
    method course_user_ids (line 396) | def course_user_ids
    method user_ids_without_submission (line 401) | def user_ids_without_submission

FILE: app/controllers/course/assessment/submission_question/comments_controller.rb
  class Course::Assessment::SubmissionQuestion::CommentsController (line 2) | class Course::Assessment::SubmissionQuestion::CommentsController < Cours...
    method create (line 8) | def create
    method create_topic_subscription (line 30) | def create_topic_subscription
    method send_created_notification (line 43) | def send_created_notification(post)
    method last_post_from (line 50) | def last_post_from(submission_question)
    method discussion_topic (line 55) | def discussion_topic
    method render_create_response (line 59) | def render_create_response

FILE: app/controllers/course/assessment/submission_question/controller.rb
  class Course::Assessment::SubmissionQuestion::Controller (line 2) | class Course::Assessment::SubmissionQuestion::Controller < Course::Asses...

FILE: app/controllers/course/assessment/submission_question/submission_questions_controller.rb
  class Course::Assessment::SubmissionQuestion::SubmissionQuestionsController (line 2) | class Course::Assessment::SubmissionQuestion::SubmissionQuestionsControl...
    method all_answers (line 5) | def all_answers
    method all_answers_params (line 27) | def all_answers_params

FILE: app/controllers/course/assessment/submissions_controller.rb
  class Course::Assessment::SubmissionsController (line 2) | class Course::Assessment::SubmissionsController < Course::ComponentContr...
    method index (line 11) | def index
    method pending (line 23) | def pending
    method submission_params (line 36) | def submission_params
    method pending_submission_params (line 40) | def pending_submission_params
    method filter_params (line 44) | def filter_params
    method category_param (line 50) | def category_param
    method category (line 55) | def category
    method load_submissions (line 67) | def load_submissions
    method pending_submissions (line 81) | def pending_submissions
    method load_group_managers (line 91) | def load_group_managers
    method load_assessments (line 97) | def load_assessments
    method component (line 107) | def component

FILE: app/controllers/course/component_controller.rb
  class Course::ComponentController (line 2) | class Course::ComponentController < Course::Controller
    method load_current_component_host (line 11) | def load_current_component_host
    method check_component (line 19) | def check_component
    method load_settings (line 24) | def load_settings
    method component (line 33) | def component

FILE: app/controllers/course/condition/achievements_controller.rb
  class Course::Condition::AchievementsController (line 2) | class Course::Condition::AchievementsController < Course::ConditionsCont...
    method index (line 9) | def index
    method show (line 13) | def show
    method create (line 17) | def create
    method update (line 25) | def update
    method destroy (line 29) | def destroy
    method render_available_achievements (line 35) | def render_available_achievements
    method try_to_perform (line 51) | def try_to_perform(operation_succeeded)
    method achievement_condition_params (line 59) | def achievement_condition_params
    method set_course (line 63) | def set_course
    method component (line 71) | def component

FILE: app/controllers/course/condition/assessments_controller.rb
  class Course::Condition::AssessmentsController (line 2) | class Course::Condition::AssessmentsController < Course::ConditionsContr...
    method index (line 7) | def index
    method show (line 11) | def show
    method create (line 15) | def create
    method update (line 19) | def update
    method destroy (line 23) | def destroy
    method render_available_assessments (line 29) | def render_available_assessments
    method try_to_perform (line 36) | def try_to_perform(operation_succeeded)
    method assessment_condition_params (line 44) | def assessment_condition_params
    method set_course_and_conditional (line 48) | def set_course_and_conditional
    method component (line 57) | def component

FILE: app/controllers/course/condition/levels_controller.rb
  class Course::Condition::LevelsController (line 2) | class Course::Condition::LevelsController < Course::ConditionsController
    method create (line 7) | def create
    method update (line 12) | def update
    method destroy (line 16) | def destroy
    method try_to_perform (line 22) | def try_to_perform(operation_succeeded)
    method level_condition_params (line 30) | def level_condition_params
    method set_course (line 34) | def set_course
    method component (line 42) | def component

FILE: app/controllers/course/condition/scholaistic_assessments_controller.rb
  class Course::Condition::ScholaisticAssessmentsController (line 2) | class Course::Condition::ScholaisticAssessmentsController < Course::Cond...
    method index (line 7) | def index
    method show (line 11) | def show
    method create (line 15) | def create
    method update (line 19) | def update
    method destroy (line 23) | def destroy
    method render_available_scholaistic_assessments (line 29) | def render_available_scholaistic_assessments
    method try_to_perform (line 36) | def try_to_perform(operation_succeeded)
    method scholaistic_assessment_condition_params (line 44) | def scholaistic_assessment_condition_params
    method set_course_and_conditional (line 48) | def set_course_and_conditional
    method component (line 53) | def component

FILE: app/controllers/course/condition/surveys_controller.rb
  class Course::Condition::SurveysController (line 2) | class Course::Condition::SurveysController < Course::ConditionsController
    method index (line 7) | def index
    method show (line 11) | def show
    method create (line 15) | def create
    method update (line 19) | def update
    method destroy (line 23) | def destroy
    method render_available_surveys (line 29) | def render_available_surveys
    method try_to_perform (line 36) | def try_to_perform(operation_succeeded)
    method survey_condition_params (line 44) | def survey_condition_params
    method set_course_and_conditional (line 48) | def set_course_and_conditional
    method component (line 57) | def component

FILE: app/controllers/course/conditions_controller.rb
  class Course::ConditionsController (line 2) | class Course::ConditionsController < Course::ComponentController
    method success_action (line 6) | def success_action
    method set_conditional (line 18) | def set_conditional
    method authorize_conditional (line 23) | def authorize_conditional
    method load_and_authorize_conditional (line 27) | def load_and_authorize_conditional

FILE: app/controllers/course/controller.rb
  class Course::Controller (line 2) | class Course::Controller < ApplicationController
    method sidebar_items (line 12) | def sidebar_items(type: nil)
    method current_course (line 25) | def current_course
    method current_course_user (line 34) | def current_course_user
    method current_component_host (line 46) | def current_component_host
    method current_ability (line 52) | def current_ability
    method handle_access_denied (line 59) | def handle_access_denied(exception)
    method sidebar_items_of_type (line 70) | def sidebar_items_of_type(type)
    method sidebar_items_weights (line 80) | def sidebar_items_weights(type: nil)
    method set_last_active_at (line 91) | def set_last_active_at

FILE: app/controllers/course/courses_controller.rb
  class Course::CoursesController (line 2) | class Course::CoursesController < Course::Controller
    method index (line 6) | def index
    method show (line 10) | def show
    method create (line 28) | def create
    method destroy (line 36) | def destroy
    method sidebar (line 39) | def sidebar
    method publicly_accessible? (line 52) | def publicly_accessible?
    method course_params (line 58) | def course_params
    method load_todos (line 63) | def load_todos # rubocop:disable Metrics/AbcSize
    method load_items_with_timeline (line 91) | def load_items_with_timeline # rubocop:disable Metrics/CyclomaticCompl...
    method load_activity_course_users (line 105) | def load_activity_course_users

FILE: app/controllers/course/discussion/posts_controller.rb
  class Course::Discussion::PostsController (line 2) | class Course::Discussion::PostsController < Course::ComponentController
    method create (line 13) | def create
    method update (line 33) | def update
    method destroy (line 50) | def destroy
    method discussion_topic (line 61) | def discussion_topic
    method create_topic_subscription (line 65) | def create_topic_subscription
    method topic_id_param (line 71) | def topic_id_param
    method codaveri_rating_param (line 75) | def codaveri_rating_param
    method load_topic (line 79) | def load_topic
    method send_created_notification (line 84) | def send_created_notification(post)
    method handle_codaveri_feedback (line 91) | def handle_codaveri_feedback(rating)
    method component (line 99) | def component

FILE: app/controllers/course/discussion/topics_controller.rb
  class Course::Discussion::TopicsController (line 2) | class Course::Discussion::TopicsController < Course::ComponentController
    method index (line 13) | def index
    method all (line 16) | def all
    method pending (line 27) | def pending
    method my_students (line 37) | def my_students
    method my_students_pending (line 42) | def my_students_pending
    method toggle_pending (line 47) | def toggle_pending
    method mark_as_read (line 60) | def mark_as_read
    method pagination_page_param (line 71) | def pagination_page_param
    method unread_topics_for_student (line 75) | def unread_topics_for_student
    method all_topics (line 79) | def all_topics
    method my_students_topics (line 90) | def my_students_topics
    method component (line 109) | def component
    method mark_as_pending? (line 113) | def mark_as_pending?
    method render_topics_list_data (line 117) | def render_topics_list_data

FILE: app/controllers/course/duplications_controller.rb
  class Course::DuplicationsController (line 2) | class Course::DuplicationsController < Course::ComponentController
    method show (line 5) | def show; end
    method create (line 7) | def create
    method authorize_duplication (line 18) | def authorize_duplication
    method create_duplication_params (line 30) | def create_duplication_params
    method instance_params (line 34) | def instance_params
    method duplication_job_options (line 42) | def duplication_job_options
    method component (line 48) | def component

FILE: app/controllers/course/enrol_requests_controller.rb
  class Course::EnrolRequestsController (line 2) | class Course::EnrolRequestsController < Course::ComponentController
    method index (line 10) | def index
    method create (line 14) | def create
    method destroy (line 26) | def destroy
    method approve (line 35) | def approve
    method reject (line 48) | def reject
    method course_user_params (line 61) | def course_user_params
    method component (line 67) | def component
    method approve_success (line 71) | def approve_success
    method approve_failure (line 77) | def approve_failure(course_user)
    method reject_success (line 83) | def reject_success
    method reject_failure (line 89) | def reject_failure

FILE: app/controllers/course/experience_points/disbursement_controller.rb
  class Course::ExperiencePoints::DisbursementController (line 2) | class Course::ExperiencePoints::DisbursementController < Course::Compone...
    method new (line 6) | def new
    method create (line 12) | def create
    method load_resource (line 22) | def load_resource
    method disbursement_params (line 26) | def disbursement_params
    method authorize_resource (line 41) | def authorize_resource
    method recipient_count (line 48) | def recipient_count
    method component (line 54) | def component

FILE: app/controllers/course/experience_points/forum_disbursement_controller.rb
  class Course::ExperiencePoints::ForumDisbursementController (line 2) | class Course::ExperiencePoints::ForumDisbursementController <
    method create (line 4) | def create
    method load_resource (line 14) | def load_resource
    method disbursement_params (line 18) | def disbursement_params
    method new_disbursement_params (line 27) | def new_disbursement_params
    method create_disbursement_params (line 36) | def create_disbursement_params

FILE: app/controllers/course/experience_points_records_controller.rb
  class Course::ExperiencePointsRecordsController (line 2) | class Course::ExperiencePointsRecordsController < Course::ComponentContr...
    method index (line 8) | def index
    method show (line 15) | def show
    method download (line 20) | def download
    method update (line 28) | def update
    method destroy (line 44) | def destroy
    method load_active_experience_points_records (line 54) | def load_active_experience_points_records
    method experience_points_record_params (line 59) | def experience_points_record_params
    method filter_and_paginate_params (line 63) | def filter_and_paginate_params
    method filter_download_params (line 69) | def filter_download_params
    method paginate_and_preload_experience_points (line 75) | def paginate_and_preload_experience_points
    method preload_exp_points_updater (line 82) | def preload_exp_points_updater
    method component (line 89) | def component

FILE: app/controllers/course/forum/component_controller.rb
  class Course::Forum::ComponentController (line 2) | class Course::Forum::ComponentController < Course::Forum::Controller

FILE: app/controllers/course/forum/controller.rb
  class Course::Forum::Controller (line 2) | class Course::Forum::Controller < Course::ComponentController
    method load_forum (line 9) | def load_forum
    method component (line 15) | def component
    method skip_load_forum? (line 19) | def skip_load_forum?

FILE: app/controllers/course/forum/forums_controller.rb
  class Course::Forum::ForumsController (line 2) | class Course::Forum::ForumsController < Course::Forum::Controller
    method index (line 10) | def index
    method show (line 19) | def show
    method create (line 32) | def create
    method update (line 42) | def update
    method destroy (line 53) | def destroy
    method subscribe (line 61) | def subscribe
    method unsubscribe (line 69) | def unsubscribe
    method all_posts (line 77) | def all_posts
    method search (line 91) | def search
    method mark_all_as_read (line 95) | def mark_all_as_read
    method mark_as_read (line 103) | def mark_as_read
    method search_params (line 112) | def search_params
    method forum_params (line 120) | def forum_params
    method skip_load_forum? (line 124) | def skip_load_forum?
    method forum_with_statistics (line 128) | def forum_with_statistics
    method preload_topic_subscriptons (line 137) | def preload_topic_subscriptons

FILE: app/controllers/course/forum/posts_controller.rb
  class Course::Forum::PostsController (line 2) | class Course::Forum::PostsController < Course::Forum::ComponentController
    method create (line 11) | def create
    method update (line 29) | def update
    method vote (line 37) | def vote
    method toggle_answer (line 43) | def toggle_answer
    method mark_answer_and_publish (line 54) | def mark_answer_and_publish
    method destroy (line 63) | def destroy
    method publish (line 77) | def publish
    method generate_reply (line 86) | def generate_reply
    method discussion_topic (line 99) | def discussion_topic
    method skip_update_topic_status (line 103) | def skip_update_topic_status
    method topic_id_param (line 109) | def topic_id_param
    method load_topic (line 113) | def load_topic
    method post_vote_param (line 117) | def post_vote_param
    method authorize_locked_topic (line 121) | def authorize_locked_topic
    method creator_json (line 125) | def creator_json

FILE: app/controllers/course/forum/topics_controller.rb
  class Course::Forum::TopicsController (line 2) | class Course::Forum::TopicsController < Course::Forum::ComponentController
    method show (line 17) | def show
    method create (line 28) | def create
    method update (line 41) | def update
    method destroy (line 52) | def destroy
    method update_topic_params (line 62) | def update_topic_params
    method topic_params (line 66) | def topic_params
    method load_topic (line 70) | def load_topic
    method mark_posts_read (line 74) | def mark_posts_read
    method authorize_topic_type! (line 78) | def authorize_topic_type!(type)
    method send_created_notification (line 87) | def send_created_notification(topic)

FILE: app/controllers/course/group/group_categories_controller.rb
  class Course::Group::GroupCategoriesController (line 2) | class Course::Group::GroupCategoriesController < Course::ComponentContro...
    method index (line 7) | def index
    method show (line 13) | def show
    method show_info (line 16) | def show_info
    method show_users (line 22) | def show_users
    method create (line 26) | def create
    method create_groups (line 35) | def create_groups
    method update (line 48) | def update
    method update_group_members (line 56) | def update_group_members
    method destroy (line 70) | def destroy
    method partition_new_users (line 80) | def partition_new_users(new_users, existing_users)
    method add_new_members (line 87) | def add_new_members(members_to_add, group)
    method update_members (line 94) | def update_members(members_to_update, existing_users)
    method destroy_members (line 101) | def destroy_members(members_to_destroy)
    method group_category_params (line 107) | def group_category_params
    method groups_params (line 111) | def groups_params
    method update_groups_params (line 118) | def update_groups_params
    method component (line 127) | def component

FILE: app/controllers/course/group/groups_controller.rb
  class Course::Group::GroupsController (line 2) | class Course::Group::GroupsController < Course::ComponentController
    method update (line 5) | def update
    method destroy (line 13) | def destroy
    method group_params (line 23) | def group_params
    method component (line 29) | def component

FILE: app/controllers/course/leaderboards_controller.rb
  class Course::LeaderboardsController (line 2) | class Course::LeaderboardsController < Course::ComponentController
    method index (line 8) | def index
    method check_component_settings (line 21) | def check_component_settings
    method preload_course_levels (line 29) | def preload_course_levels
    method component (line 35) | def component
    method fetch_course_users (line 40) | def fetch_course_users
    method fetch_users_list (line 45) | def fetch_users_list(achievements_enabled)
    method fetch_groups_list (line 52) | def fetch_groups_list(achievements_enabled)

FILE: app/controllers/course/learning_map_controller.rb
  class Course::LearningMapController (line 2) | class Course::LearningMapController < Course::ComponentController
    method index (line 9) | def index
    method add_parent_node (line 17) | def add_parent_node
    method remove_parent_node (line 29) | def remove_parent_node
    method toggle_satisfiability_type (line 41) | def toggle_satisfiability_type
    method authorize_learning_map (line 60) | def authorize_learning_map
    method authorize_update (line 64) | def authorize_update
    method component (line 70) | def component
    method error_response (line 74) | def error_response(errors)
    method prepare_response_data (line 82) | def prepare_response_data
    method map_conditionals_to_nodes (line 88) | def map_conditionals_to_nodes
    method generate_all_node_relations (line 94) | def generate_all_node_relations # rubocop:disable Metrics/AbcSize, Met...
    method init_all_node_relations (line 120) | def init_all_node_relations
    method map_condition_to_parent (line 126) | def map_condition_to_parent(condition)
    method generate_nodes_from_conditionals (line 134) | def generate_nodes_from_conditionals(all_node_relations) # rubocop:dis...
    method generate_node_depths (line 159) | def generate_node_depths(nodes)
    method init_depths (line 175) | def init_depths(nodes)
    method toposort (line 179) | def toposort(nodes)
    method dfs (line 191) | def dfs(node, node_ids_to_nodes, visited_node_ids, post_order_nodes)
    method parent_and_node_id_pair_params (line 202) | def parent_and_node_id_pair_params
    method node_params (line 206) | def node_params
    method get_node_id (line 210) | def get_node_id(conditional)
    method create_condition (line 214) | def create_condition(node_id, conditional)
    method get_conditional (line 226) | def get_conditional(node_id)
    method get_condition (line 231) | def get_condition(parent_node_id, node_id)

FILE: app/controllers/course/lesson_plan/controller.rb
  class Course::LessonPlan::Controller (line 2) | class Course::LessonPlan::Controller < Course::ComponentController
    method component (line 11) | def component

FILE: app/controllers/course/lesson_plan/events_controller.rb
  class Course::LessonPlan::EventsController (line 2) | class Course::LessonPlan::EventsController < Course::LessonPlan::Controller
    method create (line 10) | def create
    method update (line 18) | def update
    method destroy (line 26) | def destroy
    method event_params (line 36) | def event_params

FILE: app/controllers/course/lesson_plan/items_controller.rb
  class Course::LessonPlan::ItemsController (line 2) | class Course::LessonPlan::ItemsController < Course::LessonPlan::Controller
    method index (line 13) | def index
    method update (line 19) | def update
    method item_params (line 29) | def item_params
    method render_json_response (line 33) | def render_json_response
    method visibility_hash (line 56) | def visibility_hash
    method assessment_tabs_visibility_hash (line 66) | def assessment_tabs_visibility_hash
    method component_visibility_hash (line 75) | def component_visibility_hash
    method assessment_tabs_titles_hash (line 86) | def assessment_tabs_titles_hash
    method tab_title_array (line 100) | def tab_title_array(tab)
    method assessment_item_settings (line 108) | def assessment_item_settings
    method component_item_settings (line 118) | def component_item_settings
    method load_item_settings (line 126) | def load_item_settings

FILE: app/controllers/course/lesson_plan/milestones_controller.rb
  class Course::LessonPlan::MilestonesController (line 2) | class Course::LessonPlan::MilestonesController < Course::LessonPlan::Con...
    method create (line 12) | def create
    method update (line 20) | def update
    method destroy (line 28) | def destroy
    method milestone_params (line 38) | def milestone_params

FILE: app/controllers/course/lesson_plan/todos_controller.rb
  class Course::LessonPlan::TodosController (line 2) | class Course::LessonPlan::TodosController < Course::LessonPlan::Controller
    method ignore (line 6) | def ignore

FILE: app/controllers/course/levels_controller.rb
  class Course::LevelsController (line 2) | class Course::LevelsController < Course::ComponentController
    method index (line 5) | def index
    method create (line 8) | def create
    method component (line 22) | def component

FILE: app/controllers/course/material/controller.rb
  class Course::Material::Controller (line 2) | class Course::Material::Controller < Course::ComponentController
    method create_text_chunks (line 6) | def create_text_chunks
    method destroy_text_chunks (line 22) | def destroy_text_chunks
    method material_chunking_params (line 32) | def material_chunking_params
    method last_text_chunking_job (line 36) | def last_text_chunking_job
    method component (line 43) | def component
    method root_folder_name (line 48) | def root_folder_name

FILE: app/controllers/course/material/folders_controller.rb
  class Course::Material::FoldersController (line 2) | class Course::Material::FoldersController < Course::Material::Controller
    method index (line 7) | def index
    method show (line 12) | def show
    method update (line 16) | def update
    method destroy (line 26) | def destroy
    method create_subfolder (line 34) | def create_subfolder
    method upload_materials (line 45) | def upload_materials
    method download (line 57) | def download
    method breadcrumbs (line 65) | def breadcrumbs
    method authorize_read_owner! (line 71) | def authorize_read_owner!
    method folder_params (line 75) | def folder_params
    method files_params (line 80) | def files_params
    method load_subfolders (line 84) | def load_subfolders
    method load_root_folder_with_subfolders (line 91) | def load_root_folder_with_subfolders
    method handle_not_found (line 98) | def handle_not_found

FILE: app/controllers/course/material/materials_controller.rb
  class Course::Material::MaterialsController (line 2) | class Course::Material::MaterialsController < Course::Material::Controller
    method show (line 5) | def show
    method update (line 11) | def update
    method destroy (line 30) | def destroy
    method material_params (line 40) | def material_params
    method create_submission (line 44) | def create_submission
    method authentication_service (line 62) | def authentication_service
    method log_service (line 67) | def log_service
    method delete_material_text_chunks (line 72) | def delete_material_text_chunks

FILE: app/controllers/course/object_duplications_controller.rb
  class Course::ObjectDuplicationsController (line 2) | class Course::ObjectDuplicationsController < Course::ComponentController
    method new (line 6) | def new
    method create (line 12) | def create
    method authorize_duplication (line 21) | def authorize_duplication
    method load_destination_courses_data (line 27) | def load_destination_courses_data
    method load_items_data (line 41) | def load_items_data
    method load_assessments_component_data (line 49) | def load_assessments_component_data
    method load_survey_component_data (line 53) | def load_survey_component_data
    method load_achievements_component_data (line 57) | def load_achievements_component_data
    method load_materials_component_data (line 61) | def load_materials_component_data
    method load_videos_component_data (line 65) | def load_videos_component_data
    method load_destination_instances_data (line 69) | def load_destination_instances_data
    method create_duplication_params (line 84) | def create_duplication_params
    method authorized_destination_course (line 91) | def authorized_destination_course
    method course_item_finders (line 101) | def course_item_finders
    method objects_to_duplicate (line 115) | def objects_to_duplicate
    method component (line 123) | def component

FILE: app/controllers/course/personal_times_controller.rb
  class Course::PersonalTimesController (line 2) | class Course::PersonalTimesController < Course::ComponentController
    method index (line 8) | def index
    method create (line 27) | def create
    method destroy (line 38) | def destroy
    method recompute (line 48) | def recompute
    method component (line 56) | def component
    method authorize_personal_times! (line 60) | def authorize_personal_times!
    method personal_time_params (line 64) | def personal_time_params

FILE: app/controllers/course/plagiarism/assessments_controller.rb
  class Course::Plagiarism::AssessmentsController (line 2) | class Course::Plagiarism::AssessmentsController < Course::Plagiarism::Co...
    method index (line 9) | def index
    method plagiarism_data (line 22) | def plagiarism_data
    method plagiarism_check (line 46) | def plagiarism_check
    method plagiarism_checks (line 59) | def plagiarism_checks
    method fetch_plagiarism_checks (line 77) | def fetch_plagiarism_checks
    method download_submission_pair_result (line 92) | def download_submission_pair_result
    method share_submission_pair_result (line 99) | def share_submission_pair_result
    method share_assessment_result (line 106) | def share_assessment_result
    method linked_and_unlinked_assessments (line 112) | def linked_and_unlinked_assessments
    method update_assessment_links (line 142) | def update_assessment_links
    method plagiarism_data_params (line 153) | def plagiarism_data_params
    method should_timeout_plagiarism_check? (line 157) | def should_timeout_plagiarism_check?(assessment)
    method should_query_plagiarism_check? (line 164) | def should_query_plagiarism_check?(assessment)
    method timeout_plagiarism_check (line 171) | def timeout_plagiarism_check(assessment)
    method query_and_update_plagiarism_check (line 175) | def query_and_update_plagiarism_check(assessment)
    method fetch_plagiarism_data_submissions (line 190) | def fetch_plagiarism_data_submissions(submission_ids)
    method fetch_all_assessment_related_statistics_hash (line 217) | def fetch_all_assessment_related_statistics_hash
    method fetch_can_manage_rows_hash (line 223) | def fetch_can_manage_rows_hash(rows)
    method viewer_is_administrator? (line 240) | def viewer_is_administrator?
    method num_plagiarism_checkable_questions_hash (line 245) | def num_plagiarism_checkable_questions_hash

FILE: app/controllers/course/plagiarism/controller.rb
  class Course::Plagiarism::Controller (line 2) | class Course::Plagiarism::Controller < Course::ComponentController
    method authorize_manage_plagiarism! (line 7) | def authorize_manage_plagiarism!
    method component (line 13) | def component

FILE: app/controllers/course/plagiarism/plagiarism_controller.rb
  class Course::Plagiarism::PlagiarismController (line 2) | class Course::Plagiarism::PlagiarismController < Course::Plagiarism::Con...
    method index (line 5) | def index

FILE: app/controllers/course/reference_timelines_controller.rb
  class Course::ReferenceTimelinesController (line 2) | class Course::ReferenceTimelinesController < Course::ComponentController
    method index (line 5) | def index
    method create (line 15) | def create
    method update (line 23) | def update
    method destroy (line 31) | def destroy
    method reference_timeline_params (line 52) | def reference_timeline_params
    method revert_course_users_to_alternative_timeline (line 56) | def revert_course_users_to_alternative_timeline
    method destroy_params (line 65) | def destroy_params
    method component (line 69) | def component

FILE: app/controllers/course/reference_times_controller.rb
  class Course::ReferenceTimesController (line 2) | class Course::ReferenceTimesController < Course::ReferenceTimelinesContr...
    method create (line 5) | def create
    method update (line 13) | def update
    method destroy (line 21) | def destroy
    method create_params (line 31) | def create_params
    method update_params (line 35) | def update_params

FILE: app/controllers/course/rubrics_controller.rb
  class Course::RubricsController (line 2) | class Course::RubricsController < Course::Controller
    method index (line 5) | def index
    method destroy (line 9) | def destroy

FILE: app/controllers/course/scholaistic/assistants_controller.rb
  class Course::Scholaistic::AssistantsController (line 2) | class Course::Scholaistic::AssistantsController < Course::Scholaistic::C...
    method index (line 3) | def index
    method show (line 13) | def show

FILE: app/controllers/course/scholaistic/controller.rb
  class Course::Scholaistic::Controller (line 2) | class Course::Scholaistic::Controller < Course::ComponentController
    method component (line 9) | def component
    method not_found_if_scholaistic_course_not_linked (line 13) | def not_found_if_scholaistic_course_not_linked

FILE: app/controllers/course/scholaistic/scholaistic_assessments_controller.rb
  class Course::Scholaistic::ScholaisticAssessmentsController (line 2) | class Course::Scholaistic::ScholaisticAssessmentsController < Course::Sc...
    method index (line 8) | def index
    method new (line 34) | def new
    method show (line 42) | def show
    method edit (line 57) | def edit
    method update (line 65) | def update
    method update_params (line 75) | def update_params
    method sync_scholaistic_assessments! (line 79) | def sync_scholaistic_assessments!

FILE: app/controllers/course/scholaistic/submissions_controller.rb
  class Course::Scholaistic::SubmissionsController (line 2) | class Course::Scholaistic::SubmissionsController < Course::Scholaistic::...
    method index (line 7) | def index
    method show (line 15) | def show
    method submission (line 35) | def submission
    method load_and_authorize_scholaistic_assessment (line 49) | def load_and_authorize_scholaistic_assessment
    method sync_scholaistic_submission! (line 54) | def sync_scholaistic_submission!
    method submission_id (line 78) | def submission_id

FILE: app/controllers/course/statistics/aggregate_controller.rb
  class Course::Statistics::AggregateController (line 3) | class Course::Statistics::AggregateController < Course::Statistics::Cont...
    method course_progression (line 9) | def course_progression
    method course_performance (line 14) | def course_performance
    method all_staff (line 20) | def all_staff
    method all_students (line 25) | def all_students
    method all_assessments (line 30) | def all_assessments
    method activity_get_help (line 38) | def activity_get_help
    method download_score_summary (line 50) | def download_score_summary
    method sanitize_date_range (line 59) | def sanitize_date_range(start_at_param, end_at_param)
    method valid_date_range? (line 65) | def valid_date_range?(start_date, end_date)
    method fetch_course_get_help_data (line 71) | def fetch_course_get_help_data(start_date, end_date)
    method load_assessment_question_hash (line 96) | def load_assessment_question_hash
    method assessment_info_array (line 111) | def assessment_info_array
    method user_submission_array (line 119) | def user_submission_array # rubocop:disable Metrics/AbcSize
    method correctness_hash (line 140) | def correctness_hash
    method fetch_all_assessment_related_statistics_hash (line 182) | def fetch_all_assessment_related_statistics_hash
    method course_users (line 191) | def course_users
    method group_manager_preload_service (line 195) | def group_manager_preload_service
    method preload_levels (line 201) | def preload_levels

FILE: app/controllers/course/statistics/assessments_controller.rb
  class Course::Statistics::AssessmentsController (line 2) | class Course::Statistics::AssessmentsController < Course::Statistics::Co...
    method assessment_statistics (line 7) | def assessment_statistics
    method submission_statistics (line 19) | def submission_statistics
    method ancestor_statistics (line 36) | def ancestor_statistics
    method live_feedback_statistics (line 52) | def live_feedback_statistics
    method live_feedback_history (line 65) | def live_feedback_history
    method ancestor_info (line 85) | def ancestor_info
    method load_ordered_questions (line 91) | def load_ordered_questions
    method assessment_params (line 95) | def assessment_params
    method load_course_user_students_info (line 99) | def load_course_user_students_info
    method fetch_all_ancestor_assessments (line 104) | def fetch_all_ancestor_assessments
    method create_question_related_hash (line 121) | def create_question_related_hash
    method create_student_live_feedback_hash (line 128) | def create_student_live_feedback_hash
    method fetch_message_grade_hash (line 173) | def fetch_message_grade_hash
    method build_message_grade_sql (line 191) | def build_message_grade_sql(student_ids, submission_question_ids)
    method feedback_messages_cte (line 217) | def feedback_messages_cte(student_ids, submission_question_ids)
    method feedback_answers_cte (line 238) | def feedback_answers_cte
    method grades_before_cte (line 256) | def grades_before_cte
    method grades_after_cte (line 268) | def grades_after_cte
    method build_live_feedback_data (line 284) | def build_live_feedback_data(submission, final_grade_hash, message_gra...
    method calculate_prompt_hash (line 308) | def calculate_prompt_hash(message_hash)
    method fetch_messages_for_question (line 318) | def fetch_messages_for_question(submission_question_id)
    method create_question_order_hash (line 325) | def create_question_order_hash
    method create_submission_question_id_hash (line 331) | def create_submission_question_id_hash(questions)

FILE: app/controllers/course/statistics/controller.rb
  class Course::Statistics::Controller (line 2) | class Course::Statistics::Controller < Course::ComponentController
    method authorize_read_statistics! (line 7) | def authorize_read_statistics!
    method component (line 13) | def component

FILE: app/controllers/course/statistics/statistics_controller.rb
  class Course::Statistics::StatisticsController (line 2) | class Course::Statistics::StatisticsController < Course::Statistics::Con...
    method index (line 5) | def index

FILE: app/controllers/course/statistics/users_controller.rb
  class Course::Statistics::UsersController (line 2) | class Course::Statistics::UsersController < Course::Statistics::Controller
    method learning_rate_records (line 3) | def learning_rate_records

FILE: app/controllers/course/stories/stories_controller.rb
  class Course::Stories::StoriesController (line 2) | class Course::Stories::StoriesController < Course::ComponentController
    method learn (line 12) | def learn
    method learn_settings (line 18) | def learn_settings
    method mission_control (line 24) | def mission_control
    method check_course_user_and_push_key (line 33) | def check_course_user_and_push_key
    method push_key (line 37) | def push_key
    method component (line 41) | def component

FILE: app/controllers/course/survey/controller.rb
  class Course::Survey::Controller (line 2) | class Course::Survey::Controller < Course::ComponentController
    method component (line 13) | def component
    method load_sections (line 17) | def load_sections

FILE: app/controllers/course/survey/questions_controller.rb
  class Course::Survey::QuestionsController (line 2) | class Course::Survey::QuestionsController < Course::Survey::Controller
    method create (line 5) | def create
    method update (line 15) | def update
    method destroy (line 23) | def destroy
    method load_question_options (line 33) | def load_question_options
    method render_question_json (line 37) | def render_question_json
    method question_params (line 42) | def question_params

FILE: app/controllers/course/survey/responses_controller.rb
  class Course::Survey::ResponsesController (line 2) | class Course::Survey::ResponsesController < Course::Survey::Controller
    method index (line 5) | def index
    method create (line 11) | def create
    method show (line 23) | def show
    method edit (line 28) | def edit
    method update (line 39) | def update
    method unsubmit (line 56) | def unsubmit
    method handle_create_error (line 67) | def handle_create_error(error)
    method build_response (line 77) | def build_response
    method load_answers (line 82) | def load_answers
    method render_response_json (line 86) | def render_response_json
    method response_update_params (line 96) | def response_update_params

FILE: app/controllers/course/survey/sections_controller.rb
  class Course::Survey::SectionsController (line 2) | class Course::Survey::SectionsController < Course::Survey::Controller
    method create (line 5) | def create
    method update (line 15) | def update
    method destroy (line 23) | def destroy
    method load_questions (line 33) | def load_questions
    method render_section_json (line 37) | def render_section_json
    method section_params (line 42) | def section_params

FILE: app/controllers/course/survey/surveys_controller.rb
  class Course::Survey::SurveysController (line 2) | class Course::Survey::SurveysController < Course::Survey::Controller
    method index (line 8) | def index
    method create (line 13) | def create
    method show (line 21) | def show
    method update (line 25) | def update
    method destroy (line 33) | def destroy
    method results (line 41) | def results
    method remind (line 46) | def remind
    method download (line 59) | def download
    method student_course_users (line 70) | def student_course_users
    method render_survey_with_questions_json (line 74) | def render_survey_with_questions_json
    method preload_questions_results (line 82) | def preload_questions_results
    method survey_params (line 91) | def survey_params
    method preload_student_submitted_responses_counts (line 100) | def preload_student_submitted_responses_counts

FILE: app/controllers/course/user_email_subscriptions_controller.rb
  class Course::UserEmailSubscriptionsController (line 2) | class Course::UserEmailSubscriptionsController < Course::ComponentContro...
    method edit (line 5) | def edit
    method update (line 13) | def update
    method email_setting_params (line 22) | def email_setting_params
    method subscription_params (line 26) | def subscription_params
    method email_setting_filter_params (line 30) | def email_setting_filter_params
    method update_subscription_setting (line 34) | def update_subscription_setting
    method load_subscription_settings (line 43) | def load_subscription_settings
    method load_email_settings (line 51) | def load_email_settings
    method filter_subscription_settings (line 62) | def filter_subscription_settings
    method unsubscribe (line 75) | def unsubscribe
    method component (line 84) | def component

FILE: app/controllers/course/user_invitations_controller.rb
  class Course::UserInvitationsController (line 2) | class Course::UserInvitationsController < Course::ComponentController
    method index (line 7) | def index
    method create (line 16) | def create
    method destroy (line 26) | def destroy
    method resend_invitation (line 34) | def resend_invitation
    method resend_invitations (line 44) | def resend_invitations
    method toggle_registration (line 52) | def toggle_registration
    method course_user_invitation_params (line 58) | def course_user_invitation_params
    method invitation_params (line 70) | def invitation_params
    method registration_params (line 78) | def registration_params
    method resend_invitation_params (line 85) | def resend_invitation_params
    method load_invitations (line 93) | def load_invitations
    method authorize_invitation! (line 106) | def authorize_invitation!
    method invite_by_file? (line 113) | def invite_by_file?
    method invite (line 120) | def invite
    method invitation_service (line 130) | def invitation_service
    method propagate_errors (line 137) | def propagate_errors
    method propagate_errors_to_file (line 144) | def propagate_errors_to_file
    method aggregate_errors (line 152) | def aggregate_errors
    method invalid_course_user_errors (line 159) | def invalid_course_user_errors
    method invalid_course_users (line 169) | def invalid_course_users
    method invalid_invitation_email_errors (line 176) | def invalid_invitation_email_errors
    method invalid_invitations (line 186) | def invalid_invitations
    method parse_invitation_result (line 191) | def parse_invitation_result(new_invitations, existing_invitations, new...
    method enable_registration_code (line 204) | def enable_registration_code(enable)
    method component (line 217) | def component
    method resend_invitation_success (line 221) | def resend_invitation_success
    method resend_invitation_failure (line 229) | def resend_invitation_failure
    method resend_invitations_success (line 235) | def resend_invitations_success
    method resend_invitations_failure (line 243) | def resend_invitations_failure
    method destroy_invitation_success (line 249) | def destroy_invitation_success
    method destroy_invitation_failure (line 255) | def destroy_invitation_failure
    method create_invitation_success (line 261) | def create_invitation_success(result)

FILE: app/controllers/course/user_notifications_controller.rb
  class Course::UserNotificationsController (line 2) | class Course::UserNotificationsController < Course::Controller
    method fetch (line 6) | def fetch
    method mark_as_read (line 10) | def mark_as_read
    method publicly_accessible? (line 17) | def publicly_accessible?
    method next_popup_notification (line 28) | def next_popup_notification

FILE: app/controllers/course/user_registrations_controller.rb
  class Course::UserRegistrationsController (line 2) | class Course::UserRegistrationsController < Course::ComponentController
    method create (line 7) | def create
    method registration_params (line 19) | def registration_params
    method ensure_unregistered_user (line 23) | def ensure_unregistered_user
    method load_registration (line 32) | def load_registration
    method registration_service (line 39) | def registration_service
    method component (line 45) | def component

FILE: app/controllers/course/users_controller.rb
  class Course::UsersController (line 2) | class Course::UsersController < Course::ComponentController
    method index (line 8) | def index
    method destroy (line 11) | def destroy
    method show (line 20) | def show
    method load_resource (line 30) | def load_resource
    method component (line 52) | def component

FILE: app/controllers/course/video/controller.rb
  class Course::Video::Controller (line 2) | class Course::Video::Controller < Course::ComponentController
    method current_tab (line 9) | def current_tab
    method component (line 15) | def component

FILE: app/controllers/course/video/submission/controller.rb
  class Course::Video::Submission::Controller (line 2) | class Course::Video::Submission::Controller < Course::Video::Controller

FILE: app/controllers/course/video/submission/sessions_controller.rb
  class Course::Video::Submission::SessionsController (line 2) | class Course::Video::Submission::SessionsController < Course::Video::Sub...
    method create (line 5) | def create
    method update (line 9) | def update
    method current_tab (line 37) | def current_tab
    method update_params (line 41) | def update_params
    method video_params (line 47) | def video_params

FILE: app/controllers/course/video/submission/submissions_controller.rb
  class Course::Video::Submission::SubmissionsController (line 2) | class Course::Video::Submission::SubmissionsController < Course::Video::...
    method index (line 11) | def index
    method show (line 21) | def show
    method create (line 29) | def create
    method edit (line 39) | def edit
    method create_params (line 57) | def create_params
    method scroll_topic_params (line 61) | def scroll_topic_params
    method seek_time_params (line 65) | def seek_time_params
    method authorize_attempt_video! (line 69) | def authorize_attempt_video!
    method authorize_analyze_video! (line 73) | def authorize_analyze_video!
    method set_seek_and_scroll (line 77) | def set_seek_and_scroll
    method set_monitoring (line 83) | def set_monitoring
    method current_tab (line 88) | def current_tab

FILE: app/controllers/course/video/topics_controller.rb
  class Course::Video::TopicsController (line 2) | class Course::Video::TopicsController < Course::Video::Controller
    method index (line 8) | def index
    method create (line 14) | def create
    method show (line 25) | def show
    method topic_params (line 30) | def topic_params
    method discussion_topic (line 34) | def discussion_topic
    method create_topic_subscription (line 38) | def create_topic_subscription
    method current_tab (line 42) | def current_tab

FILE: app/controllers/course/video/videos_controller.rb
  class Course::Video::VideosController (line 2) | class Course::Video::VideosController < Course::Video::Controller
    method index (line 7) | def index
    method show (line 25) | def show
    method create (line 31) | def create
    method update (line 41) | def update
    method destroy (line 53) | def destroy
    method can_for_videos_in_current_course? (line 63) | def can_for_videos_in_current_course?(ability)
    method video_params (line 67) | def video_params
    method current_tab (line 73) | def current_tab
    method load_video_tabs (line 83) | def load_video_tabs
    method preload_video_item (line 87) | def preload_video_item
    method preload_student_submission_count (line 98) | def preload_student_submission_count

FILE: app/controllers/course/video_submissions_controller.rb
  class Course::VideoSubmissionsController (line 2) | class Course::VideoSubmissionsController < Course::ComponentController
    method index (line 7) | def index
    method component (line 18) | def component
    method load_video_submissions (line 23) | def load_video_submissions
    method authorize_analyze_video! (line 27) | def authorize_analyze_video!

FILE: app/controllers/csrf_token_controller.rb
  class CsrfTokenController (line 2) | class CsrfTokenController < ApplicationController
    method csrf_token (line 3) | def csrf_token
    method publicly_accessible? (line 9) | def publicly_accessible?

FILE: app/controllers/health_check_controller.rb
  class HealthCheckController (line 3) | class HealthCheckController < ActionController::Base
    method show (line 6) | def show

FILE: app/controllers/instance_user_role_requests_controller.rb
  class InstanceUserRoleRequestsController (line 2) | class InstanceUserRoleRequestsController < ApplicationController
    method index (line 5) | def index
    method create (line 13) | def create
    method update (line 23) | def update
    method approve (line 31) | def approve
    method reject (line 43) | def reject
    method user_role_request_params (line 54) | def user_role_request_params
    method user_role_request_rejection_params (line 58) | def user_role_request_rejection_params
    method send_rejection_email (line 62) | def send_rejection_email

FILE: app/controllers/jobs_controller.rb
  class JobsController (line 2) | class JobsController < ApplicationController
    method show (line 5) | def show
    method publicly_accessible? (line 17) | def publicly_accessible?
    method load_job (line 23) | def load_job
    method show_completed_job (line 27) | def show_completed_job
    method show_errored_job (line 33) | def show_errored_job
    method show_submitted_job (line 39) | def show_submitted_job

FILE: app/controllers/system/admin/admin_controller.rb
  class System::Admin::AdminController (line 2) | class System::Admin::AdminController < System::Admin::Controller
    method index (line 3) | def index
    method deployment_info (line 6) | def deployment_info

FILE: app/controllers/system/admin/announcements_controller.rb
  class System::Admin::AnnouncementsController (line 2) | class System::Admin::AnnouncementsController < System::Admin::Controller
    method index (line 5) | def index
    method create (line 13) | def create
    method update (line 23) | def update
    method destroy (line 33) | def destroy
    method announcement_params (line 43) | def announcement_params

FILE: app/controllers/system/admin/controller.rb
  class System::Admin::Controller (line 2) | class System::Admin::Controller < ApplicationController
    method authorize_admin (line 7) | def authorize_admin

FILE: app/controllers/system/admin/courses_controller.rb
  class System::Admin::CoursesController (line 2) | class System::Admin::CoursesController < System::Admin::Controller
    method index (line 5) | def index
    method destroy (line 13) | def destroy
    method search_param (line 25) | def search_param
    method unscope_resources (line 29) | def unscope_resources(&block)
    method preload_courses (line 33) | def preload_courses

FILE: app/controllers/system/admin/get_help_controller.rb
  class System::Admin::GetHelpController (line 2) | class System::Admin::GetHelpController < System::Admin::Controller
    method index (line 3) | def index
    method sanitize_date_range (line 24) | def sanitize_date_range(start_at_param, end_at_param)
    method valid_date_range? (line 30) | def valid_date_range?(start_date, end_date)
    method load_course_user_hash (line 36) | def load_course_user_hash(user_ids)
    method fetch_system_get_help_data (line 43) | def fetch_system_get_help_data(start_date, end_date)
    method load_assessment_and_course_hash (line 64) | def load_assessment_and_course_hash(assessment_ids)
    method load_course_instance_hash (line 79) | def load_course_instance_hash
    method build_question_hash (line 93) | def build_question_hash(assessment, question_assessment, course, quest...

FILE: app/controllers/system/admin/instance/admin_controller.rb
  class System::Admin::Instance::AdminController (line 2) | class System::Admin::Instance::AdminController < System::Admin::Instance...
    method index (line 3) | def index

FILE: app/controllers/system/admin/instance/announcements_controller.rb
  class System::Admin::Instance::AnnouncementsController (line 2) | class System::Admin::Instance::AnnouncementsController < System::Admin::...
    method index (line 6) | def index
    method create (line 14) | def create
    method update (line 24) | def update
    method destroy (line 34) | def destroy
    method announcement_params (line 44) | def announcement_params

FILE: app/controllers/system/admin/instance/components_controller.rb
  class System::Admin::Instance::ComponentsController (line 2) | class System::Admin::Instance::ComponentsController < System::Admin::Ins...
    method index (line 5) | def index
    method update (line 11) | def update
    method settings_components_params (line 21) | def settings_components_params
    method settings (line 26) | def settings

FILE: app/controllers/system/admin/instance/controller.rb
  class System::Admin::Instance::Controller (line 2) | class System::Admin::Instance::Controller < ApplicationController
    method load_instance (line 8) | def load_instance
    method authorize_instance_admin (line 12) | def authorize_instance_admin

FILE: app/controllers/system/admin/instance/courses_controller.rb
  class System::Admin::Instance::CoursesController (line 2) | class System::Admin::Instance::CoursesController < System::Admin::Instan...
    method index (line 5) | def index
    method destroy (line 13) | def destroy
    method search_param (line 23) | def search_param
    method preload_courses (line 27) | def preload_courses # rubocop:disable Metrics/AbcSize

FILE: app/controllers/system/admin/instance/get_help_controller.rb
  class System::Admin::Instance::GetHelpController (line 2) | class System::Admin::Instance::GetHelpController < System::Admin::Instan...
    method index (line 3) | def index
    method sanitize_date_range (line 21) | def sanitize_date_range(start_at_param, end_at_param)
    method valid_date_range? (line 27) | def valid_date_range?(start_date, end_date)
    method load_course_user_hash (line 33) | def load_course_user_hash(user_ids)
    method fetch_instance_get_help_data (line 41) | def fetch_instance_get_help_data(start_date, end_date)
    method load_assessment_and_course_hash (line 67) | def load_assessment_and_course_hash(assessment_ids)
    method build_question_hash (line 82) | def build_question_hash(assessment, question_assessment, course, quest...

FILE: app/controllers/system/admin/instance/user_invitations_controller.rb
  class System::Admin::Instance::UserInvitationsController (line 2) | class System::Admin::Instance::UserInvitationsController < System::Admin...
    method index (line 7) | def index
    method new (line 14) | def new
    method create (line 18) | def create
    method destroy (line 30) | def destroy
    method resend_invitation (line 39) | def resend_invitation
    method resend_invitations (line 49) | def resend_invitations
    method instance_user_invitation_params (line 60) | def instance_user_invitation_params
    method invitation_params (line 67) | def invitation_params
    method resend_invitation_params (line 71) | def resend_invitation_params
    method invite (line 79) | def invite
    method invitation_service (line 83) | def invitation_service
    method invitations (line 87) | def invitations
    method parse_invitation_result (line 100) | def parse_invitation_result(new_invitations, existing_invitations, new...

FILE: app/controllers/system/admin/instance/users_controller.rb
  class System::Admin::Instance::UsersController (line 2) | class System::Admin::Instance::UsersController < System::Admin::Instance...
    method index (line 6) | def index
    method update (line 15) | def update
    method destroy (line 25) | def destroy
    method load_instance_users (line 35) | def load_instance_users
    method load_counts (line 49) | def load_counts
    method instance_user_params (line 56) | def instance_user_params
    method search_param (line 60) | def search_param

FILE: app/controllers/system/admin/instances_controller.rb
  class System::Admin::InstancesController (line 2) | class System::Admin::InstancesController < System::Admin::Controller
    method index (line 5) | def index
    method create (line 13) | def create
    method update (line 22) | def update
    method destroy (line 32) | def destroy
    method instance_params (line 42) | def instance_params
    method preload_instances (line 46) | def preload_instances

FILE: app/controllers/system/admin/users_controller.rb
  class System::Admin::UsersController (line 2) | class System::Admin::UsersController < System::Admin::Controller
    method index (line 5) | def index
    method update (line 17) | def update
    method destroy (line 28) | def destroy
    method get_user_course_hash (line 47) | def get_user_course_hash(user_ids)
    method user_params (line 53) | def user_params
    method search_param (line 57) | def search_param
    method load_users (line 61) | def load_users
    method load_counts (line 69) | def load_counts

FILE: app/controllers/test/controller.rb
  class Test::Controller (line 2) | class Test::Controller < ActionController::Base
    method restrict_to_test (line 7) | def restrict_to_test

FILE: app/controllers/test/factories_controller.rb
  class Test::FactoriesController (line 2) | class Test::FactoriesController < Test::Controller
    method create (line 5) | def create
    method create_params (line 24) | def create_params
    method set_user_stamper (line 28) | def set_user_stamper
    method traits_from (line 32) | def traits_from(attributes)

FILE: app/controllers/test/mailer_controller.rb
  class Test::MailerController (line 2) | class Test::MailerController < Test::Controller
    method last_sent (line 3) | def last_sent
    method clear (line 7) | def clear

FILE: app/controllers/user/confirmations_controller.rb
  class User::ConfirmationsController (line 2) | class User::ConfirmationsController < Devise::ConfirmationsController
    method show (line 5) | def show

FILE: app/controllers/user/emails_controller.rb
  class User::EmailsController (line 2) | class User::EmailsController < ApplicationController
    method index (line 5) | def index
    method create (line 8) | def create
    method destroy (line 16) | def destroy
    method set_primary (line 25) | def set_primary
    method send_confirmation (line 34) | def send_confirmation
    method render_emails (line 45) | def render_emails
    method email_params (line 50) | def email_params

FILE: app/controllers/user/passwords_controller.rb
  class User::PasswordsController (line 2) | class User::PasswordsController < Devise::PasswordsController
    method edit (line 5) | def edit
    method hash_reset_password_token (line 17) | def hash_reset_password_token(token)

FILE: app/controllers/user/profiles_controller.rb
  class User::ProfilesController (line 2) | class User::ProfilesController < ApplicationController
    method show (line 3) | def show
    method edit (line 6) | def edit
    method update (line 9) | def update
    method time_zones (line 18) | def time_zones
    method profile_params (line 24) | def profile_params

FILE: app/controllers/user/registrations_controller.rb
  class User::RegistrationsController (line 2) | class User::RegistrationsController < Devise::RegistrationsController
    method new (line 8) | def new
    method create (line 38) | def create
    method configure_sign_up_params (line 96) | def configure_sign_up_params
    method build_resource (line 117) | def build_resource(*)
    method load_invitation (line 122) | def load_invitation
    method invitation_params (line 134) | def invitation_params
    method authenticate_scope! (line 138) | def authenticate_scope!

FILE: app/controllers/user/sessions_controller.rb
  class User::SessionsController (line 2) | class User::SessionsController < Devise::SessionsController

FILE: app/controllers/users_controller.rb
  class UsersController (line 2) | class UsersController < ApplicationController
    method show (line 5) | def show

FILE: app/helpers/application_formatters_helper.rb
  type ApplicationFormattersHelper (line 5) | module ApplicationFormattersHelper
    function format_inline_text (line 12) | def format_inline_text(text)
    function display_user (line 21) | def display_user(user)
    function user_image (line 30) | def user_image(user, url: false)
    function link_to_user (line 43) | def link_to_user(user, options = {})
    function format_datetime (line 69) | def format_datetime(date, format = :long, user: nil)
    function format_duration (line 81) | def format_duration(total_seconds)
    function clean_html_text (line 96) | def clean_html_text(text)
    function clean_html_text_blank? (line 109) | def clean_html_text_blank?(text)

FILE: app/helpers/application_helper.rb
  type ApplicationHelper (line 3) | module ApplicationHelper
    function user_time_zone (line 10) | def user_time_zone
    function url_to_course_logo (line 14) | def url_to_course_logo(course)

FILE: app/helpers/application_html_formatters_helper.rb
  type ApplicationHtmlFormattersHelper (line 3) | module ApplicationHtmlFormattersHelper
    function sanitize (line 9) | def sanitize(text, _options = {})
    function format_html (line 19) | def format_html(text)
    function format_ckeditor_rich_text (line 23) | def format_ckeditor_rich_text(text)
    function sanitize_ckeditor_rich_text (line 27) | def sanitize_ckeditor_rich_text(text)
    function format_code_block (line 41) | def format_code_block(code, language = nil, start_line = 1)
    function highlight_code_block (line 59) | def highlight_code_block(code, language = nil)
    function build_html_pipeline (line 75) | def self.build_html_pipeline(custom_options)
    function code_size_exceeds_limit? (line 226) | def code_size_exceeds_limit?(code)
    function sanitize_and_format_code (line 230) | def sanitize_and_format_code(code, language, start_line)
    function process_ckeditor_rich_text_with_pipeline (line 242) | def process_ckeditor_rich_text_with_pipeline(pipeline, text)
    function format_with_pipeline (line 255) | def format_with_pipeline(pipeline, text)
    function default_code_pipeline (line 263) | def default_code_pipeline(starting_line_number = 1)
    function remove_internal_adjacent_code_tags (line 278) | def remove_internal_adjacent_code_tags(text)

FILE: app/helpers/application_jobs_helper.rb
  type ApplicationJobsHelper (line 3) | module ApplicationJobsHelper
    function job_error_message (line 4) | def job_error_message(error)

FILE: app/helpers/application_mailer_helper.rb
  type ApplicationMailerHelper (line 3) | module ApplicationMailerHelper
    function plain_link_to (line 8) | def plain_link_to(text, url)

FILE: app/helpers/application_notifications_helper.rb
  type ApplicationNotificationsHelper (line 2) | module ApplicationNotificationsHelper
    function notification_view_path (line 7) | def notification_view_path(notification)
    function notification_directory_path (line 15) | def notification_directory_path(notification)

FILE: app/helpers/consolidated_opening_reminder_mailer_helper.rb
  type ConsolidatedOpeningReminderMailerHelper (line 2) | module ConsolidatedOpeningReminderMailerHelper
    function actable_type_partial_path (line 10) | def actable_type_partial_path(notification, actable_type)

FILE: app/helpers/course/achievement/achievements_helper.rb
  type Course::Achievement::AchievementsHelper (line 2) | module Course::Achievement::AchievementsHelper
    function achievement_badge_path (line 8) | def achievement_badge_path(achievement = nil)

FILE: app/helpers/course/achievement/controller_helper.rb
  type Course::Achievement::ControllerHelper (line 2) | module Course::Achievement::ControllerHelper
    function achievement_status_class (line 13) | def achievement_status_class(achievement, current_course_user)

FILE: app/helpers/course/assessment/answer/programming_test_case_helper.rb
  type Course::Assessment::Answer::ProgrammingTestCaseHelper (line 2) | module Course::Assessment::Answer::ProgrammingTestCaseHelper
    function get_hint (line 9) | def get_hint(test_case, test_case_result)
    function get_output (line 21) | def get_output(test_case_result)
    function get_failed_test_cases_by_type (line 35) | def get_failed_test_cases_by_type(test_cases_and_results)
    function get_test_cases_and_results (line 54) | def get_test_cases_and_results(test_cases_by_type, auto_grading)
    function get_first_failed_test (line 69) | def get_first_failed_test(test_cases_and_results_of_type)

FILE: app/helpers/course/assessment/assessments_helper.rb
  type Course::Assessment::AssessmentsHelper (line 2) | module Course::Assessment::AssessmentsHelper
    function condition_not_satisfied (line 6) | def condition_not_satisfied(can_attempt, assessment, assessment_time)
    function assessment_not_started (line 12) | def assessment_not_started(assessment_time)
    function show_bonus_attributes? (line 16) | def show_bonus_attributes?
    function show_end_at? (line 26) | def show_end_at?
    function display_graded_test_types (line 32) | def display_graded_test_types(assessment)

FILE: app/helpers/course/assessment/question/programming_helper.rb
  type Course::Assessment::Question::ProgrammingHelper (line 2) | module Course::Assessment::Question::ProgrammingHelper
    function import_result_error (line 7) | def import_result_error
    function import_errored? (line 20) | def import_errored?
    function display_build_log? (line 27) | def display_build_log?
    function validation_errors (line 33) | def validation_errors
    function check_import_job? (line 39) | def check_import_job?
    function can_switch_package_type? (line 43) | def can_switch_package_type?
    function can_edit_online? (line 47) | def can_edit_online?
    function import_job_error_map (line 55) | def import_job_error_map

FILE: app/helpers/course/assessment/submission/submissions_helper.rb
  type Course::Assessment::Submission::SubmissionsHelper (line 2) | module Course::Assessment::Submission::SubmissionsHelper
    function last_attempt (line 14) | def last_attempt(answer)

FILE: app/helpers/course/assessment/submissions_helper.rb
  type Course::Assessment::SubmissionsHelper (line 2) | module Course::Assessment::SubmissionsHelper
    function pending_submissions_count (line 6) | def pending_submissions_count
    function my_students_pending_submissions_count (line 16) | def my_students_pending_submissions_count
    function pending_submission_count_for (line 29) | def pending_submission_count_for(student_ids)

FILE: app/helpers/course/condition/conditions_helper.rb
  type Course::Condition::ConditionsHelper (line 2) | module Course::Condition::ConditionsHelper
    function component_enabled? (line 8) | def component_enabled?(class_name)
    function conditions_component_hash (line 17) | def conditions_component_hash

FILE: app/helpers/course/controller_helper.rb
  type Course::ControllerHelper (line 2) | module Course::ControllerHelper
    function display_course_user (line 10) | def display_course_user(user)
    function display_user (line 20) | def display_user(user)
    function link_to_course_user (line 41) | def link_to_course_user(user, options = {})
    function link_to_user (line 55) | def link_to_user(user, options = {}, &block)
    function url_to_material (line 66) | def url_to_material(course, folder, material)

FILE: app/helpers/course/discussion/topics_helper.rb
  type Course::Discussion::TopicsHelper (line 2) | module Course::Discussion::TopicsHelper
    function display_code_lines (line 9) | def display_code_lines(file, line_start, line_end)
    function all_staff_unread_count (line 20) | def all_staff_unread_count
    function my_students_unread_count (line 25) | def my_students_unread_count
    function from_user (line 39) | def from_user(topic, my_student_ids) # rubocop:disable Metrics/Perceiv...
    function all_student_unread_count (line 53) | def all_student_unread_count

FILE: app/helpers/course/forum/controller_helper.rb
  type Course::Forum::ControllerHelper (line 2) | module Course::Forum::ControllerHelper
    function next_unread_topic_link (line 7) | def next_unread_topic_link(forum = nil)
    function email_setting_enabled (line 18) | def email_setting_enabled(component, setting)
    function email_setting_enabled_current_course_user (line 22) | def email_setting_enabled_current_course_user(component, setting)
    function email_subscription_enabled_current_course_user (line 28) | def email_subscription_enabled_current_course_user(component, setting)
    function topic_type_keys (line 34) | def topic_type_keys(topic)
    function post_anonymous? (line 41) | def post_anonymous?(post)

FILE: app/helpers/course/group/group_categories_helper.rb
  type Course::Group::GroupCategoriesHelper (line 2) | module Course::Group::GroupCategoriesHelper

FILE: app/helpers/course/leaderboards_helper.rb
  type Course::LeaderboardsHelper (line 2) | module Course::LeaderboardsHelper
    function display_user_count (line 6) | def display_user_count
    function leaderboard_position (line 17) | def leaderboard_position(course, course_user, display_user_count)

FILE: app/helpers/course/material/folders_helper.rb
  type Course::Material::FoldersHelper (line 2) | module Course::Material::FoldersHelper
    function show_sdl_warning? (line 8) | def show_sdl_warning?(folder)

FILE: app/helpers/course/object_duplications_helper.rb
  type Course::ObjectDuplicationsHelper (line 2) | module Course::ObjectDuplicationsHelper
    function cherrypickable_components_hash (line 4) | def cherrypickable_components_hash
    function cherrypickable_items_hash (line 15) | def cherrypickable_items_hash
    function map_components_to_frontend_tokens (line 31) | def map_components_to_frontend_tokens(components)

FILE: app/helpers/course/users_helper.rb
  type Course::UsersHelper (line 2) | module Course::UsersHelper
    function preload_course_users_hash (line 7) | def preload_course_users_hash(course)

FILE: app/helpers/route_overrides_helper.rb
  type RouteOverridesHelper (line 2) | module RouteOverridesHelper
    function mapping_for (line 6) | def mapping_for(from, to)
    function map_route_helpers_with (line 13) | def map_route_helpers_with(mapping)
    function map_route (line 30) | def map_route(from, to:)

FILE: app/helpers/tmp_cleanup_helper.rb
  type TmpCleanupHelper (line 2) | module TmpCleanupHelper
    function cleanup (line 5) | def cleanup

FILE: app/jobs/application_job.rb
  class ApplicationJob (line 2) | class ApplicationJob < ActiveJob::Base

FILE: app/jobs/consolidated_item_email_job.rb
  class ConsolidatedItemEmailJob (line 2) | class ConsolidatedItemEmailJob < ApplicationJob
    method perform (line 4) | def perform

FILE: app/jobs/course/announcement/opening_reminder_job.rb
  class Course::Announcement::OpeningReminderJob (line 2) | class Course::Announcement::OpeningReminderJob < ApplicationJob
    method perform (line 7) | def perform(user, announcement, token)

FILE: app/jobs/course/assessment/answer/auto_grading_job.rb
  class Course::Assessment::Answer::AutoGradingJob (line 2) | class Course::Assessment::Answer::AutoGradingJob < Course::Assessment::A...
    method default_queue_name (line 23) | def default_queue_name
    method delayed_queue_name (line 27) | def delayed_queue_name

FILE: app/jobs/course/assessment/answer/base_auto_grading_job.rb
  class Course::Assessment::Answer::BaseAutoGradingJob (line 2) | class Course::Assessment::Answer::BaseAutoGradingJob < ApplicationJob
    class PriorityShouldBeLoweredError (line 7) | class PriorityShouldBeLoweredError < StandardError
      method initialize (line 8) | def initialize(message = nil)
    method default_queue_name (line 24) | def default_queue_name
    method delayed_queue_name (line 28) | def delayed_queue_name
    method perform_tracked (line 38) | def perform_tracked(answer, redirect_to_path = nil)
    method update_exp? (line 54) | def update_exp?(submission)
    method downgrade_if_timeout (line 59) | def downgrade_if_timeout(question, &block)

FILE: app/jobs/course/assessment/answer/programming_codaveri_feedback_job.rb
  class Course::Assessment::Answer::ProgrammingCodaveriFeedbackJob (line 2) | class Course::Assessment::Answer::ProgrammingCodaveriFeedbackJob < Appli...
    method perform_tracked (line 10) | def perform_tracked(assessment, question, answer)

FILE: app/jobs/course/assessment/answer/reduce_priority_auto_grading_job.rb
  class Course::Assessment::Answer::ReducePriorityAutoGradingJob (line 2) | class Course::Assessment::Answer::ReducePriorityAutoGradingJob < Course:...
    method default_queue_name (line 18) | def default_queue_name
    method delayed_queue_name (line 22) | def delayed_queue_name

FILE: app/jobs/course/assessment/closing_reminder_job.rb
  class Course::Assessment::ClosingReminderJob (line 2) | class Course::Assessment::ClosingReminderJob < ApplicationJob
    method perform (line 7) | def perform(assessment, token)

FILE: app/jobs/course/assessment/invite_to_koditsu_job.rb
  class Course::Assessment::InviteToKoditsuJob (line 2) | class Course::Assessment::InviteToKoditsuJob < ApplicationJob
    method perform_tracked (line 9) | def perform_tracked(assessment_id, updated_at)

FILE: app/jobs/course/assessment/plagiarism_check_job.rb
  class Course::Assessment::PlagiarismCheckJob (line 2) | class Course::Assessment::PlagiarismCheckJob < ApplicationJob
    method perform_tracked (line 7) | def perform_tracked(course, assessment)

FILE: app/jobs/course/assessment/question/answers_evaluation_job.rb
  class Course::Assessment::Question::AnswersEvaluationJob (line 2) | class Course::Assessment::Question::AnswersEvaluationJob < ApplicationJob
    method perform (line 3) | def perform(question)

FILE: app/jobs/course/assessment/question/codaveri_import_job.rb
  class Course::Assessment::Question::CodaveriImportJob (line 2) | class Course::Assessment::Question::CodaveriImportJob < ApplicationJob
    method perform_tracked (line 13) | def perform_tracked(question, attachment)
    method perform_import (line 24) | def perform_import(question, attachment)

FILE: app/jobs/course/assessment/question/programming_import_job.rb
  class Course::Assessment::Question::ProgrammingImportJob (line 2) | class Course::Assessment::Question::ProgrammingImportJob < ApplicationJob
    method perform_tracked (line 13) | def perform_tracked(question, attachment, max_time_limit)
    method perform_import (line 25) | def perform_import(question, attachment)

FILE: app/jobs/course/assessment/submission/auto_feedback_job.rb
  class Course::Assessment::Submission::AutoFeedbackJob (line 2) | class Course::Assessment::Submission::AutoFeedbackJob < ApplicationJob
    method perform_tracked (line 12) | def perform_tracked(submission)

FILE: app/jobs/course/assessment/submission/auto_grading_job.rb
  class Course::Assessment::Submission::AutoGradingJob (line 2) | class Course::Assessment::Submission::AutoGradingJob < ApplicationJob
    method perform_tracked (line 35) | def perform_tracked(submission, only_ungraded = false) # rubocop:disab...

FILE: app/jobs/course/assessment/submission/csv_download_job.rb
  class Course::Assessment::Submission::CsvDownloadJob (line 2) | class Course::Assessment::Submission::CsvDownloadJob < ApplicationJob
    method perform_tracked (line 14) | def perform_tracked(current_course_user, assessment, course_users = nil)

FILE: app/jobs/course/assessment/submission/deleting_job.rb
  class Course::Assessment::Submission::DeletingJob (line 2) | class Course::Assessment::Submission::DeletingJob < ApplicationJob
    method perform_tracked (line 8) | def perform_tracked(deleter, submission_ids, assessment)
    method delete_submission (line 23) | def delete_submission(assessment, submissions, deleter)
    method reset_question_bundle_assignments (line 43) | def reset_question_bundle_assignments(assessment, submissions)

FILE: app/jobs/course/assessment/submission/fetch_submissions_from_koditsu_job.rb
  class Course::Assessment::Submission::FetchSubmissionsFromKoditsuJob (line 2) | class Course::Assessment::Submission::FetchSubmissionsFromKoditsuJob <
    method perform_tracked (line 10) | def perform_tracked(assessment_id, updated_at, user)

FILE: app/jobs/course/assessment/submission/force_submit_timed_submission_job.rb
  class Course::Assessment::Submission::ForceSubmitTimedSubmissionJob (line 3) | class Course::Assessment::Submission::ForceSubmitTimedSubmissionJob < Ap...
    method perform_tracked (line 9) | def perform_tracked(assessment, submission_id, submitter)
    method force_submit (line 22) | def force_submit(submission, submitter)

FILE: app/jobs/course/assessment/submission/force_submitting_job.rb
  class Course::Assessment::Submission::ForceSubmittingJob (line 4) | class Course::Assessment::Submission::ForceSubmittingJob < ApplicationJob
    method perform_tracked (line 16) | def perform_tracked(assessment, user_ids, user_ids_without_submission,...
    method force_create_and_submit_submissions (line 32) | def force_create_and_submit_submissions(assessment, user_ids, user_ids...
    method create_submission (line 52) | def create_submission(assessment, course_user)
    method grade_submission (line 68) | def grade_submission(assessment, submission)
    method grade_answers (line 89) | def grade_answers(submission)

FILE: app/jobs/course/assessment/submission/publishing_job.rb
  class Course::Assessment::Submission::PublishingJob (line 2) | class Course::Assessment::Submission::PublishingJob < ApplicationJob
    method perform_tracked (line 8) | def perform_tracked(graded_submission_ids, assessment, publisher)
    method publish_submissions (line 23) | def publish_submissions(submissions, publisher)

FILE: app/jobs/course/assessment/submission/statistics_download_job.rb
  class Course::Assessment::Submission::StatisticsDownloadJob (line 2) | class Course::Assessment::Submission::StatisticsDownloadJob < Applicatio...
    method perform_tracked (line 14) | def perform_tracked(current_course, current_user, submission_ids)

FILE: app/jobs/course/assessment/submission/unsubmitting_job.rb
  class Course::Assessment::Submission::UnsubmittingJob (line 5) | class Course::Assessment::Submission::UnsubmittingJob < ApplicationJob
    method perform_tracked (line 19) | def perform_tracked(unsubmitter, submission_ids, assessment, question ...
    method unsubmit_submission (line 36) | def unsubmit_submission(assessment, submissions, question, unsubmitter)

FILE: app/jobs/course/assessment/submission/zip_download_job.rb
  class Course::Assessment::Submission::ZipDownloadJob (line 2) | class Course::Assessment::Submission::ZipDownloadJob < ApplicationJob
    method perform_tracked (line 14) | def perform_tracked(course_user, assessment, course_users = nil)

FILE: app/jobs/course/conditional/conditional_satisfiability_evaluation_job.rb
  class Course::Conditional::ConditionalSatisfiabilityEvaluationJob (line 2) | class Course::Conditional::ConditionalSatisfiabilityEvaluationJob < Appl...
    method perform_tracked (line 13) | def perform_tracked(course_user, redirect_to_path = nil)

FILE: app/jobs/course/conditional/coursewide_conditional_satisfiability_evaluation_job.rb
  class Course::Conditional::CoursewideConditionalSatisfiabilityEvaluationJob (line 2) | class Course::Conditional::CoursewideConditionalSatisfiabilityEvaluation...
    method perform_tracked (line 16) | def perform_tracked(course, latest_update_time, redirect_to_path = nil)

FILE: app/jobs/course/discussion/post/codaveri_feedback_rating_job.rb
  class Course::Discussion::Post::CodaveriFeedbackRatingJob (line 2) | class Course::Discussion::Post::CodaveriFeedbackRatingJob < ApplicationJob
    method perform_tracked (line 10) | def perform_tracked(codaveri_feedback)

FILE: app/jobs/course/duplication_job.rb
  class Course::DuplicationJob (line 2) | class Course::DuplicationJob < ApplicationJob
    method perform_tracked (line 13) | def perform_tracked(source_course, options = {})

FILE: app/jobs/course/experience_points_download_job.rb
  class Course::ExperiencePointsDownloadJob (line 2) | class Course::ExperiencePointsDownloadJob < ApplicationJob
    method perform_tracked (line 9) | def perform_tracked(course, course_user_id)

FILE: app/jobs/course/forum/auto_answering_job.rb
  class Course::Forum::AutoAnsweringJob (line 2) | class Course::Forum::AutoAnsweringJob < ApplicationJob
    method perform_tracked (line 10) | def perform_tracked(post, topic, current_author, current_course_author...
    method create_response_post (line 27) | def create_response_post(post, response, current_author, evaluation)
    method publish_if_needed (line 41) | def publish_if_needed(post, topic, current_author, current_course_author)
    method answering! (line 47) | def answering!(post)
    method cancel_answering! (line 52) | def cancel_answering!(post)

FILE: app/jobs/course/forum/importing_job.rb
  class Course::Forum::ImportingJob (line 2) | class Course::Forum::ImportingJob < ApplicationJob
    method perform_tracked (line 8) | def perform_tracked(forum_import_ids, current_user)

FILE: app/jobs/course/lesson_plan/coursewide_personalized_timeline_update_job.rb
  class Course::LessonPlan::CoursewidePersonalizedTimelineUpdateJob (line 2) | class Course::LessonPlan::CoursewidePersonalizedTimelineUpdateJob < Appl...
    method perform (line 6) | def perform(lesson_plan_item)

FILE: app/jobs/course/material/text_chunk_job.rb
  class Course::Material::TextChunkJob (line 2) | class Course::Material::TextChunkJob < ApplicationJob
    method perform_tracked (line 8) | def perform_tracked(material_ids, current_user)

FILE: app/jobs/course/material/zip_download_job.rb
  class Course::Material::ZipDownloadJob (line 2) | class Course::Material::ZipDownloadJob < ApplicationJob
    method perform_tracked (line 16) | def perform_tracked(folder, materials, filename = folder.name)

FILE: app/jobs/course/object_duplication_job.rb
  class Course::ObjectDuplicationJob (line 2) | class Course::ObjectDuplicationJob < ApplicationJob
    method perform_tracked (line 15) | def perform_tracked(source_course, destination_course, objects, option...

FILE: app/jobs/course/rubric/rubric_evaluation_export_job.rb
  class Course::Rubric::RubricEvaluationExportJob (line 2) | class Course::Rubric::RubricEvaluationExportJob < ApplicationJob # ruboc...
    method perform_tracked (line 6) | def perform_tracked(course, rubric_id, question_id)
    method load_answers_and_evaluations (line 22) | def load_answers_and_evaluations(rubric, question)
    method evaluate_answer (line 38) | def evaluate_answer(answer, rubric)
    method export_rubric_to_rubric_based_response_question (line 56) | def export_rubric_to_rubric_based_response_question(rubric, rubric_bas...
    method build_exported_rubric_hashes (line 83) | def build_exported_rubric_hashes(rubric, rubric_based_response_question)
    method update_answer_grade_and_feedback (line 100) | def update_answer_grade_and_feedback(answer, answer_evaluation)
    method build_answer_v1_selections (line 109) | def build_answer_v1_selections(answer_evaluation, exported_categories_...
    method export_answer_rubric_grading_data (line 119) | def export_answer_rubric_grading_data(rubric, answers_to_export, expor...

FILE: app/jobs/course/statistics/assessments_score_summary_download_job.rb
  class Course::Statistics::AssessmentsScoreSummaryDownloadJob (line 2) | class Course::Statistics::AssessmentsScoreSummaryDownloadJob < Applicati...
    method perform_tracked (line 9) | def perform_tracked(course, assessment_ids)

FILE: app/jobs/course/survey/closing_reminder_job.rb
  class Course::Survey::ClosingReminderJob (line 2) | class Course::Survey::ClosingReminderJob < ApplicationJob
    method perform (line 7) | def perform(survey, token)

FILE: app/jobs/course/survey/survey_download_job.rb
  class Course::Survey::SurveyDownloadJob (line 2) | class Course::Survey::SurveyDownloadJob < ApplicationJob
    method perform_tracked (line 12) | def perform_tracked(survey)

FILE: app/jobs/course/user_deletion_job.rb
  class Course::UserDeletionJob (line 2) | class Course::UserDeletionJob < ApplicationJob
    method perform (line 3) | def perform(course, course_user, current_user)

FILE: app/jobs/course/video/closing_reminder_job.rb
  class Course::Video::ClosingReminderJob (line 2) | class Course::Video::ClosingReminderJob < ApplicationJob
    method perform (line 7) | def perform(video, token)

FILE: app/jobs/read_marks_clean_up_job.rb
  class ReadMarksCleanUpJob (line 2) | class ReadMarksCleanUpJob < ApplicationJob
    method perform (line 3) | def perform

FILE: app/jobs/user_email_database_cleanup_job.rb
  class UserEmailDatabaseCleanupJob (line 2) | class UserEmailDatabaseCleanupJob < ApplicationJob
    method perform (line 3) | def perform
    method cleanup_unconfirmed_users (line 15) | def cleanup_unconfirmed_users
    method cleanup_unconfirmed_secondary_emails (line 35) | def cleanup_unconfirmed_secondary_emails

FILE: app/jobs/video_statistic_update_job.rb
  class VideoStatisticUpdateJob (line 2) | class VideoStatisticUpdateJob < ApplicationJob
    method perform (line 10) | def perform

FILE: app/mailers/activity_mailer.rb
  class ActivityMailer (line 5) | class ActivityMailer < ApplicationMailer
    method email (line 20) | def email(recipient:, notification:, view_path:, layout_path: nil)
    method mail (line 40) | def mail(options)

FILE: app/mailers/application_mailer.rb
  class ApplicationMailer (line 2) | class ApplicationMailer < ActionMailer::Base

FILE: app/mailers/consolidated_opening_reminder_mailer.rb
  class ConsolidatedOpeningReminderMailer (line 5) | class ConsolidatedOpeningReminderMailer < ActivityMailer
    method email (line 17) | def email(recipient:, notification:, view_path:, layout_path: nil)

FILE: app/mailers/course/mailer.rb
  class Course::Mailer (line 3) | class Course::Mailer < ApplicationMailer
    method user_invitation_email (line 7) | def user_invitation_email(invitation)
    method user_enrol_request_received_email (line 24) | def user_enrol_request_received_email(course, user, requires_confirmat...
    method user_added_email (line 39) | def user_added_email(user, requires_confirmation: false)
    method user_rejected_email (line 55) | def user_rejected_email(course, user)
    method user_enrol_requested_email (line 69) | def user_enrol_requested_email(enrol_request)
    method course_duplicated_email (line 102) | def course_duplicated_email(original_course, new_course, user)
    method course_duplicate_failed_email (line 118) | def course_duplicate_failed_email(original_course, user)
    method user_suspended_email (line 132) | def user_suspended_email(course_user)
    method user_unsuspended_email (line 147) | def user_unsuspended_email(course_user)
    method course_user_deletion_failed_email (line 158) | def course_user_deletion_failed_email(course, course_user, user)
    method assessment_closing_reminder_email (line 174) | def assessment_closing_reminder_email(assessment, user)
    method assessment_closing_summary_email (line 193) | def assessment_closing_summary_email(recipient, assessment, users)
    method submission_graded_email (line 210) | def submission_graded_email(submission)
    method video_closing_reminder_email (line 228) | def video_closing_reminder_email(recipient, video)
    method survey_closing_reminder_email (line 245) | def survey_closing_reminder_email(recipient, survey)
    method survey_closing_summary_email (line 264) | def survey_closing_summary_email(recipient, survey, student_list)

FILE: app/mailers/instance/mailer.rb
  class Instance::Mailer (line 2) | class Instance::Mailer < ApplicationMailer
    method user_invitation_email (line 7) | def user_invitation_email(invitation)
    method user_added_email (line 19) | def user_added_email(user)

FILE: app/mailers/instance_user_role_request_mailer.rb
  class InstanceUserRoleRequestMailer (line 3) | class InstanceUserRoleRequestMailer < ApplicationMailer
    method new_role_request (line 10) | def new_role_request(request, recipient)
    method role_request_approved (line 22) | def role_request_approved(instance_user)
    method role_request_rejected (line 40) | def role_request_rejected(instance_user, message)

FILE: app/models/ability.rb
  class Ability (line 2) | class Ability
    method initialize (line 17) | def initialize(user, course = nil, course_user = nil, instance_user = ...
    method define_permissions (line 36) | def define_permissions

FILE: app/models/activity.rb
  class Activity (line 6) | class Activity < ApplicationRecord
    method notify (line 25) | def notify(recipient, type)
    method from_course? (line 41) | def from_course?(course)
    method notify_course (line 48) | def notify_course(course, type)
    method notify_user (line 55) | def notify_user(user, type)

FILE: app/models/application_record.rb
  class ApplicationRecord (line 2) | class ApplicationRecord < ActiveRecord::Base

FILE: app/models/attachment.rb
  class Attachment (line 2) | class Attachment < ApplicationRecord
    method find_or_initialize_by (line 30) | def find_or_initialize_by(attributes, &block)
    method find_or_create_by (line 43) | def find_or_create_by(attributes, &block)
    method file_digest (line 55) | def file_digest(file)
    method open (line 73) | def open(opt = {}, &block)
    method open_with_block (line 85) | def open_with_block(opt, block)
    method open_without_block (line 98) | def open_without_block(opt)
    method contents (line 111) | def contents

FILE: app/models/attachment_reference.rb
  class AttachmentReference (line 2) | class AttachmentReference < ApplicationRecord
    method file= (line 23) | def file=(file)
    method record_userstamp (line 29) | def record_userstamp
    method initialize_duplicate (line 33) | def initialize_duplicate(duplicator, other)
    method generate_public_url (line 40) | def generate_public_url
    method filename (line 50) | def filename(file)
    method update_expires_at (line 60) | def update_expires_at

FILE: app/models/cikgo_user.rb
  class CikgoUser (line 2) | class CikgoUser < ApplicationRecord

FILE: app/models/components/ability_host.rb
  class AbilityHost (line 2) | class AbilityHost
    type InstanceHelpers (line 5) | module InstanceHelpers
      function instance_user_hash (line 13) | def instance_user_hash(*roles)
      function instance_instance_user_hash (line 22) | def instance_instance_user_hash(*roles)
    type TimeBoundedHelpers (line 29) | module TimeBoundedHelpers
      function currently_valid_hashes (line 37) | def currently_valid_hashes
      function already_started_hash (line 55) | def already_started_hash

FILE: app/models/components/course/achievements_ability_component.rb
  type Course::AchievementsAbilityComponent (line 2) | module Course::AchievementsAbilityComponent
    function define_permissions (line 5) | def define_permissions
    function allow_read_achievements (line 21) | def allow_read_achievements
    function allow_user_with_achievement_show_badges (line 25) | def allow_user_with_achievement_show_badges
    function allow_read_draft_achievements_and_display_badge (line 29) | def allow_read_draft_achievements_and_display_badge
    function allow_manage_achievements (line 33) | def allow_manage_achievements
    function do_not_allow_award_automatically_awarded_achievements (line 37) | def do_not_allow_award_automatically_awarded_achievements

FILE: app/models/components/course/announcements_ability_component.rb
  type Course::AnnouncementsAbilityComponent (line 2) | module Course::AnnouncementsAbilityComponent
    function define_permissions (line 5) | def define_permissions
    function allow_students_show_announcements (line 17) | def allow_students_show_announcements
    function allow_staff_read_announcements (line 21) | def allow_staff_read_announcements
    function allow_teaching_staff_manage_announcements (line 25) | def allow_teaching_staff_manage_announcements

FILE: app/models/components/course/assessments_ability_component.rb
  type Course::AssessmentsAbilityComponent (line 2) | module Course::AssessmentsAbilityComponent

FILE: app/models/components/course/conditions_ability_component.rb
  type Course::ConditionsAbilityComponent (line 2) | module Course::ConditionsAbilityComponent
    function define_permissions (line 5) | def define_permissions
    function allow_teaching_staff_manage_conditions (line 13) | def allow_teaching_staff_manage_conditions

FILE: app/models/components/course/course_ability_component.rb
  type Course::CourseAbilityComponent (line 2) | module Course::CourseAbilityComponent
    function define_permissions (line 5) | def define_permissions
    function allow_instructors_create_courses (line 28) | def allow_instructors_create_courses
    function allow_unregistered_users_registering_courses (line 32) | def allow_unregistered_users_registering_courses
    function allow_registered_users_showing_course (line 37) | def allow_registered_users_showing_course
    function allow_staff_show_course_users (line 41) | def allow_staff_show_course_users
    function define_teaching_staff_course_permissions (line 45) | def define_teaching_staff_course_permissions
    function allow_teaching_staff_manage_personal_times (line 51) | def allow_teaching_staff_manage_personal_times
    function allow_teaching_staff_analyze_videos (line 55) | def allow_teaching_staff_analyze_videos
    function allow_teaching_staff_manage_course_rubrics (line 59) | def allow_teaching_staff_manage_course_rubrics
    function define_owners_course_permissions (line 63) | def define_owners_course_permissions
    function allow_owners_managing_course (line 67) | def allow_owners_managing_course
    function disallow_managers_delete_course (line 74) | def disallow_managers_delete_course

FILE: app/models/components/course/course_user_ability_component.rb
  type Course::CourseUserAbilityComponent (line 2) | module Course::CourseUserAbilityComponent
    function define_permissions (line 5) | def define_permissions
    function allow_course_users_show_coursemates (line 13) | def allow_course_users_show_coursemates

FILE: app/models/components/course/discussions_ability_component.rb
  type Course::DiscussionsAbilityComponent (line 2) | module Course::DiscussionsAbilityComponent
    function define_permissions (line 5) | def define_permissions
    function allow_course_users_show_topics (line 23) | def allow_course_users_show_topics
    function allow_course_users_mark_topics_as_read (line 27) | def allow_course_users_mark_topics_as_read
    function allow_course_teaching_staff_manage_discussion_topics (line 31) | def allow_course_teaching_staff_manage_discussion_topics
    function allow_course_users_create_posts (line 35) | def allow_course_users_create_posts
    function allow_course_users_reply_and_vote_posts (line 39) | def allow_course_users_reply_and_vote_posts
    function allow_course_users_view_own_anonymous_posts (line 43) | def allow_course_users_view_own_anonymous_posts
    function allow_course_staff_view_anonymous_posts (line 47) | def allow_course_staff_view_anonymous_posts
    function allow_course_teaching_staff_manage_posts (line 51) | def allow_course_teaching_staff_manage_posts
    function allow_course_users_update_delete_own_post (line 55) | def allow_course_users_update_delete_own_post

FILE: app/models/components/course/duplication_ability_component.rb
  type Course::DuplicationAbilityComponent (line 2) | module Course::DuplicationAbilityComponent
    function define_permissions (line 5) | def define_permissions
    function disallow_superusers_duplicate_via_frontend (line 24) | def disallow_superusers_duplicate_via_frontend
    function allow_administrator_to_duplicate_cross_instances (line 29) | def allow_administrator_to_duplicate_cross_instances
    function allow_instance_admin_to_duplicate_cross_instances (line 33) | def allow_instance_admin_to_duplicate_cross_instances
    function allow_instance_instructor_to_duplicate_cross_instances (line 39) | def allow_instance_instructor_to_duplicate_cross_instances
    function allow_managers_duplicate_to_course (line 45) | def allow_managers_duplicate_to_course
    function allow_managers_duplicate_from_course (line 49) | def allow_managers_duplicate_from_course
    function allow_observers_duplicate_from_course (line 53) | def allow_observers_duplicate_from_course

FILE: app/models/components/course/experience_points_disbursement_ability_component.rb
  type Course::ExperiencePointsDisbursementAbilityComponent (line 2) | module Course::ExperiencePointsDisbursementAbilityComponent
    function define_permissions (line 5) | def define_permissions
    function allow_staff_disburse_experience_points (line 13) | def allow_staff_disburse_experience_points

FILE: app/models/components/course/experience_points_records_ability_component.rb
  type Course::ExperiencePointsRecordsAbilityComponent (line 2) | module Course::ExperiencePointsRecordsAbilityComponent
    function define_permissions (line 5) | def define_permissions
    function allow_staff_read_all_experience_points (line 16) | def allow_staff_read_all_experience_points
    function allow_manage_experience_points_records (line 21) | def allow_manage_experience_points_records
    function allow_read_course_experience_points_records (line 25) | def allow_read_course_experience_points_records
    function allow_read_own_experience_points_records (line 29) | def allow_read_own_experience_points_records

FILE: app/models/components/course/forums_ability_component.rb
  type Course::ForumsAbilityComponent (line 2) | module Course::ForumsAbilityComponent
    function define_permissions (line 5) | def define_permissions
    function topic_course_hash (line 17) | def topic_course_hash
    function define_all_forum_permissions (line 21) | def define_all_forum_permissions
    function allow_show_forums (line 30) | def allow_show_forums
    function allow_show_topics (line 35) | def allow_show_topics
    function allow_create_topics (line 39) | def allow_create_topics
    function allow_update_topics (line 43) | def allow_update_topics
    function allow_reply_unlocked_topics (line 47) | def allow_reply_unlocked_topics
    function allow_resolve_own_topics (line 52) | def allow_resolve_own_topics
    function define_staff_forum_permissions (line 60) | def define_staff_forum_permissions
    function allow_staff_show_all_topics (line 65) | def allow_staff_show_all_topics
    function allow_staff_resolve_topics (line 70) | def allow_staff_resolve_topics
    function define_teaching_staff_forum_permissions (line 74) | def define_teaching_staff_forum_permissions
    function allow_teaching_staff_manage_forums (line 80) | def allow_teaching_staff_manage_forums
    function allow_teaching_staff_manage_topics (line 84) | def allow_teaching_staff_manage_topics
    function allow_manage_ai_responses (line 88) | def allow_manage_ai_responses

FILE: app/models/components/course/groups_ability_component.rb
  type Course::GroupsAbilityComponent (line 2) | module Course::GroupsAbilityComponent
    function define_permissions (line 5) | def define_permissions
    function allow_staff_read_groups (line 18) | def allow_staff_read_groups
    function allow_teaching_staff_manage_groups (line 23) | def allow_teaching_staff_manage_groups
    function allow_group_manager_manage_group (line 28) | def allow_group_manager_manage_group
    function allow_group_manager_read_group_category (line 32) | def allow_group_manager_read_group_category
    function course_group_manager_hash (line 36) | def course_group_manager_hash
    function course_group_category_manager_hash (line 41) | def course_group_category_manager_hash

FILE: app/models/components/course/learning_map_ability_component.rb
  type Course::LearningMapAbilityComponent (line 2) | module Course::LearningMapAbilityComponent
    function define_permissions (line 5) | def define_permissions
    function allow_read_learning_map (line 12) | def allow_read_learning_map

FILE: app/models/components/course/lesson_plan_ability_component.rb
  type Course::LessonPlanAbilityComponent (line 2) | module Course::LessonPlanAbilityComponent
    function define_permissions (line 5) | def define_permissions
    func
Copy disabled (too large) Download .json
Condensed preview — 4409 files, each showing path, character count, and a content snippet. Download the .json file for the full structured content (12,274K chars).
[
  {
    "path": ".circleci/config.yml",
    "chars": 15167,
    "preview": "version: 2.1\n\norbs:\n  codecov: codecov/codecov@5.4.3\n\nexecutors:\n  node:\n    docker:\n      - image: cimg/node:22.22.0\n\n "
  },
  {
    "path": ".codecov.yml",
    "chars": 596,
    "preview": "codecov:\n  notify:\n    require_ci_to_pass: no\n\nflags:\n  frontend:\n    paths:\n      - client/app/\n  backend:\n    paths:\n "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/1-bug-report.yml",
    "chars": 1410,
    "preview": "name: 🐞 Bug Report\ndescription: File a bug/issue\nlabels: [\"Bug\"]\nassignees:\n  - cysjonathan\n  - adi-herwana-nus\nbody:\n  "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/2-feature-request.yml",
    "chars": 1450,
    "preview": "name: 💡 Feature Request\ndescription: Suggest a new feature or enhancement\nlabels: [\"Feature\"]\nassignees:\n  - cysjonathan"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "chars": 364,
    "preview": "blank_issues_enabled: true\ncontact_links:\n  - name: User Guide\n    url: https://coursemology.github.io/coursemology-help"
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 963,
    "preview": "version: 2\nupdates:\n  - package-ecosystem: bundler\n    directory: '/'\n    schedule:\n      interval: daily\n    open-pull-"
  },
  {
    "path": ".gitignore",
    "chars": 1599,
    "preview": "# See https://help.github.com/articles/ignoring-files for more about ignoring files.\n#\n# If you find yourself ignoring t"
  },
  {
    "path": ".gitmodules",
    "chars": 362,
    "preview": "[submodule \"vendor/assets/javascripts/recorderjs\"]\n\tpath = client/vendor/recorderjs\n\turl = https://github.com/mattdiamon"
  },
  {
    "path": ".hound.yml",
    "chars": 111,
    "preview": "fail_on_violations: true\n\nrubocop:\n  config_file: .rubocop.yml\n  version: 1.22.1\n\njavascript:\n  enabled: false\n"
  },
  {
    "path": ".rspec",
    "chars": 108,
    "preview": "--color\n--format progress\n--format ParallelTests::RSpec::RuntimeLogger --out tmp/parallel_runtime_rspec.log\n"
  },
  {
    "path": ".rubocop.unhound.yml",
    "chars": 1685,
    "preview": "Style/CollectionMethods:\n  Enabled: true\n  PreferredMethods:\n    reduce:\n    inject: 'reduce'\n    find:\n    detect: 'fin"
  },
  {
    "path": ".rubocop.yml",
    "chars": 1357,
    "preview": "inherit_from:\n  - .rubocop.unhound.yml\n\nAllCops:\n  NewCops: enable\n  Exclude:\n    - 'bin/*'\n    - 'db/seeds.rb'\n    - 'd"
  },
  {
    "path": ".yardopts",
    "chars": 70,
    "preview": "--protected\n--no-private\n--embed-mixin ClassMethods\n--markup markdown\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 201,
    "preview": "# Contributing\n\nWe have shifted our contributing guides to our [Wiki](https://github.com/Coursemology/coursemology2/wiki"
  },
  {
    "path": "Gemfile",
    "chars": 5914,
    "preview": "# frozen_string_literal: true\nsource 'https://rubygems.org'\n\nruby '3.3.5'\n\n# These gems are included in Ruby defaults fo"
  },
  {
    "path": "LICENSE",
    "chars": 1119,
    "preview": "The MIT License (MIT)\n\nhttp://opensource.org/licenses/MIT\n\nCopyright (c) 2023 Coursemology.org\n\nPermission is hereby gra"
  },
  {
    "path": "README.md",
    "chars": 5619,
    "preview": "<!-- markdownlint-disable MD033 MD014 -->\n\n# Coursemology [![CircleCI](https://circleci.com/gh/Coursemology/coursemology"
  },
  {
    "path": "Rakefile",
    "chars": 440,
    "preview": "# frozen_string_literal: true\n# Add your own tasks in files placed in lib/tasks ending in .rake,\n# for example lib/tasks"
  },
  {
    "path": "app/README.md",
    "chars": 1995,
    "preview": "# Coursemology App Server\n\nCoursemology uses [Ruby on Rails](http://rubyonrails.org/) as its backend app server. This [g"
  },
  {
    "path": "app/assets/config/manifest.js",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "app/channels/application_cable/channel.rb",
    "chars": 414,
    "preview": "# frozen_string_literal: true\nclass ApplicationCable::Channel < ActionCable::Channel::Base\n  include ApplicationCableMul"
  },
  {
    "path": "app/channels/application_cable/connection.rb",
    "chars": 362,
    "preview": "# frozen_string_literal: true\nclass ApplicationCable::Connection < ActionCable::Connection::Base\n  identified_by :curren"
  },
  {
    "path": "app/channels/concerns/application_cable_ability_concern.rb",
    "chars": 486,
    "preview": "# frozen_string_literal: true\nmodule ApplicationCableAbilityConcern\n  extend ActiveSupport::Concern\n\n  included do\n    b"
  },
  {
    "path": "app/channels/concerns/application_cable_authentication_concern.rb",
    "chars": 752,
    "preview": "# frozen_string_literal: true\nmodule ApplicationCableAuthenticationConcern\n  def current_user_from_token\n    token = aut"
  },
  {
    "path": "app/channels/concerns/application_cable_component_concern.rb",
    "chars": 633,
    "preview": "# frozen_string_literal: true\nmodule ApplicationCableComponentConcern\n  extend ActiveSupport::Concern\n\n  included do\n   "
  },
  {
    "path": "app/channels/concerns/application_cable_course_concern.rb",
    "chars": 467,
    "preview": "# frozen_string_literal: true\nmodule ApplicationCableCourseConcern\n  extend ActiveSupport::Concern\n\n  included do\n    be"
  },
  {
    "path": "app/channels/concerns/application_cable_multitenancy_concern.rb",
    "chars": 254,
    "preview": "# frozen_string_literal: true\nmodule ApplicationCableMultitenancyConcern\n  extend ActiveSupport::Concern\n  include Appli"
  },
  {
    "path": "app/channels/course/channel.rb",
    "chars": 873,
    "preview": "# frozen_string_literal: true\n#\n# The base channel for all `Course`-related channels. Subclasses of this channel\n# must "
  },
  {
    "path": "app/channels/course/monitoring/heartbeat_channel.rb",
    "chars": 3925,
    "preview": "# frozen_string_literal: true\nclass Course::Monitoring::HeartbeatChannel < Course::Channel\n  ACTIONS = { next: :next, te"
  },
  {
    "path": "app/channels/course/monitoring/live_monitoring_channel.rb",
    "chars": 4006,
    "preview": "# frozen_string_literal: true\nclass Course::Monitoring::LiveMonitoringChannel < Course::Channel\n  include Course::UsersH"
  },
  {
    "path": "app/controllers/announcements_controller.rb",
    "chars": 771,
    "preview": "# frozen_string_literal: true\nclass AnnouncementsController < ApplicationController\n  load_resource :announcement, class"
  },
  {
    "path": "app/controllers/application_controller.rb",
    "chars": 2324,
    "preview": "# frozen_string_literal: true\n\nclass ApplicationController < ActionController::Base\n  # Prevent CSRF attacks by providin"
  },
  {
    "path": "app/controllers/attachment_references_controller.rb",
    "chars": 1107,
    "preview": "# frozen_string_literal: true\nclass AttachmentReferencesController < ApplicationController\n  load_resource :attachment_r"
  },
  {
    "path": "app/controllers/components/course/achievements_component.rb",
    "chars": 363,
    "preview": "# frozen_string_literal: true\nclass Course::AchievementsComponent < SimpleDelegator\n  include Course::ControllerComponen"
  },
  {
    "path": "app/controllers/components/course/announcements_component.rb",
    "chars": 764,
    "preview": "# frozen_string_literal: true\nclass Course::AnnouncementsComponent < SimpleDelegator\n  include Course::ControllerCompone"
  },
  {
    "path": "app/controllers/components/course/assessments_component.rb",
    "chars": 1605,
    "preview": "# frozen_string_literal: true\nclass Course::AssessmentsComponent < SimpleDelegator\n  include Course::ControllerComponent"
  },
  {
    "path": "app/controllers/components/course/codaveri_component.rb",
    "chars": 396,
    "preview": "# frozen_string_literal: true\nclass Course::CodaveriComponent < SimpleDelegator\n  include Course::ControllerComponentHos"
  },
  {
    "path": "app/controllers/components/course/controller_component_host.rb",
    "chars": 6873,
    "preview": "# frozen_string_literal: true\n#\n# The course component framework isolates features as components. The intent is to allow"
  },
  {
    "path": "app/controllers/components/course/discussion/topics_component.rb",
    "chars": 762,
    "preview": "# frozen_string_literal: true\nclass Course::Discussion::TopicsComponent < SimpleDelegator\n  include Course::ControllerCo"
  },
  {
    "path": "app/controllers/components/course/duplication_component.rb",
    "chars": 411,
    "preview": "# frozen_string_literal: true\nclass Course::DuplicationComponent < SimpleDelegator\n  include Course::ControllerComponent"
  },
  {
    "path": "app/controllers/components/course/experience_points_component.rb",
    "chars": 662,
    "preview": "# frozen_string_literal: true\nclass Course::ExperiencePointsComponent < SimpleDelegator\n  include Course::ControllerComp"
  },
  {
    "path": "app/controllers/components/course/forums_component.rb",
    "chars": 730,
    "preview": "# frozen_string_literal: true\nclass Course::ForumsComponent < SimpleDelegator\n  include Course::ControllerComponentHost:"
  },
  {
    "path": "app/controllers/components/course/groups_component.rb",
    "chars": 918,
    "preview": "# frozen_string_literal: true\nclass Course::GroupsComponent < SimpleDelegator\n  include Course::ControllerComponentHost:"
  },
  {
    "path": "app/controllers/components/course/koditsu_platform_component.rb",
    "chars": 192,
    "preview": "# frozen_string_literal: true\nclass Course::KoditsuPlatformComponent < SimpleDelegator\n  include Course::ControllerCompo"
  },
  {
    "path": "app/controllers/components/course/leaderboard_component.rb",
    "chars": 710,
    "preview": "# frozen_string_literal: true\nclass Course::LeaderboardComponent < SimpleDelegator\n  include Course::ControllerComponent"
  },
  {
    "path": "app/controllers/components/course/learning_map_component.rb",
    "chars": 365,
    "preview": "# frozen_string_literal: true\nclass Course::LearningMapComponent < SimpleDelegator\n  include Course::ControllerComponent"
  },
  {
    "path": "app/controllers/components/course/lesson_plan_component.rb",
    "chars": 695,
    "preview": "# frozen_string_literal: true\nclass Course::LessonPlanComponent < SimpleDelegator\n  include Course::ControllerComponentH"
  },
  {
    "path": "app/controllers/components/course/levels_component.rb",
    "chars": 446,
    "preview": "# frozen_string_literal: true\nclass Course::LevelsComponent < SimpleDelegator\n  include Course::ControllerComponentHost:"
  },
  {
    "path": "app/controllers/components/course/materials_component.rb",
    "chars": 670,
    "preview": "# frozen_string_literal: true\nclass Course::MaterialsComponent < SimpleDelegator\n  include Course::ControllerComponentHo"
  },
  {
    "path": "app/controllers/components/course/monitoring_component.rb",
    "chars": 187,
    "preview": "# frozen_string_literal: true\nclass Course::MonitoringComponent < SimpleDelegator\n  include Course::ControllerComponentH"
  },
  {
    "path": "app/controllers/components/course/multiple_reference_timelines_component.rb",
    "chars": 528,
    "preview": "# frozen_string_literal: true\nclass Course::MultipleReferenceTimelinesComponent < SimpleDelegator\n  include Course::Cont"
  },
  {
    "path": "app/controllers/components/course/plagiarism_component.rb",
    "chars": 470,
    "preview": "# frozen_string_literal: true\nclass Course::PlagiarismComponent < SimpleDelegator\n  include Course::ControllerComponentH"
  },
  {
    "path": "app/controllers/components/course/rag_wise_component.rb",
    "chars": 443,
    "preview": "# frozen_string_literal: true\nclass Course::RagWiseComponent < SimpleDelegator\n  include Course::ControllerComponentHost"
  },
  {
    "path": "app/controllers/components/course/scholaistic_component.rb",
    "chars": 1783,
    "preview": "# frozen_string_literal: true\nclass Course::ScholaisticComponent < SimpleDelegator\n  include Course::ControllerComponent"
  },
  {
    "path": "app/controllers/components/course/settings_component.rb",
    "chars": 1501,
    "preview": "# frozen_string_literal: true\nclass Course::SettingsComponent < SimpleDelegator\n  include Course::ControllerComponentHos"
  },
  {
    "path": "app/controllers/components/course/statistics_component.rb",
    "chars": 414,
    "preview": "# frozen_string_literal: true\nclass Course::StatisticsComponent < SimpleDelegator\n  include Course::ControllerComponentH"
  },
  {
    "path": "app/controllers/components/course/stories_component.rb",
    "chars": 1248,
    "preview": "# frozen_string_literal: true\nclass Course::StoriesComponent < SimpleDelegator\n  include Course::ControllerComponentHost"
  },
  {
    "path": "app/controllers/components/course/survey_component.rb",
    "chars": 381,
    "preview": "# frozen_string_literal: true\nclass Course::SurveyComponent < SimpleDelegator\n  include Course::ControllerComponentHost:"
  },
  {
    "path": "app/controllers/components/course/users_component.rb",
    "chars": 1323,
    "preview": "# frozen_string_literal: true\nclass Course::UsersComponent < SimpleDelegator\n  include Course::ControllerComponentHost::"
  },
  {
    "path": "app/controllers/components/course/videos_component.rb",
    "chars": 840,
    "preview": "# frozen_string_literal: true\nclass Course::VideosComponent < SimpleDelegator\n  include Course::ControllerComponentHost:"
  },
  {
    "path": "app/controllers/concerns/application_ability_concern.rb",
    "chars": 268,
    "preview": "# frozen_string_literal: true\nmodule ApplicationAbilityConcern\n  # Override of Cancancan#current_ability to provide curr"
  },
  {
    "path": "app/controllers/concerns/application_announcements_concern.rb",
    "chars": 606,
    "preview": "# frozen_string_literal: true\nmodule ApplicationAnnouncementsConcern\n  extend ActiveSupport::Concern\n\n  # Returns active"
  },
  {
    "path": "app/controllers/concerns/application_authentication_concern.rb",
    "chars": 2049,
    "preview": "# frozen_string_literal: true\nmodule ApplicationAuthenticationConcern\n  extend ActiveSupport::Concern\n\n  REQUIRES_AUTHEN"
  },
  {
    "path": "app/controllers/concerns/application_components_concern.rb",
    "chars": 358,
    "preview": "# frozen_string_literal: true\nmodule ApplicationComponentsConcern\n  extend ActiveSupport::Concern\n\n  included do\n    res"
  },
  {
    "path": "app/controllers/concerns/application_controller_multitenancy_concern.rb",
    "chars": 291,
    "preview": "# frozen_string_literal: true\nmodule ApplicationControllerMultitenancyConcern\n  extend ActiveSupport::Concern\n  include "
  },
  {
    "path": "app/controllers/concerns/application_instance_user_concern.rb",
    "chars": 630,
    "preview": "# frozen_string_literal: true\nmodule ApplicationInstanceUserConcern\n  extend ActiveSupport::Concern\n\n  included do\n    b"
  },
  {
    "path": "app/controllers/concerns/application_internationalization_concern.rb",
    "chars": 454,
    "preview": "# frozen_string_literal: true\nmodule ApplicationInternationalizationConcern\n  extend ActiveSupport::Concern\n\n  included "
  },
  {
    "path": "app/controllers/concerns/application_multitenancy.rb",
    "chars": 1395,
    "preview": "# frozen_string_literal: true\nmodule ApplicationMultitenancy\n  private\n\n  def deduce_and_set_current_tenant\n    tenant ="
  },
  {
    "path": "app/controllers/concerns/application_pagination_concern.rb",
    "chars": 362,
    "preview": "# frozen_string_literal: true\nmodule ApplicationPaginationConcern\n  extend ActiveSupport::Concern\n\n  protected\n\n  # Retr"
  },
  {
    "path": "app/controllers/concerns/application_user_concern.rb",
    "chars": 2099,
    "preview": "# frozen_string_literal: true\nmodule ApplicationUserConcern\n  extend ActiveSupport::Concern\n  include ApplicationAuthent"
  },
  {
    "path": "app/controllers/concerns/application_user_time_zone_concern.rb",
    "chars": 362,
    "preview": "# frozen_string_literal: true\nmodule ApplicationUserTimeZoneConcern\n  extend ActiveSupport::Concern\n\n  included do\n    a"
  },
  {
    "path": "app/controllers/concerns/codaveri_language_concern.rb",
    "chars": 1113,
    "preview": "# frozen_string_literal: true\nmodule CodaveriLanguageConcern\n  def codaveri_language\n    programming_language_map[type.c"
  },
  {
    "path": "app/controllers/concerns/course/achievement_conditional_concern.rb",
    "chars": 326,
    "preview": "# frozen_string_literal: true\nmodule Course::AchievementConditionalConcern\n  extend ActiveSupport::Concern\n\n  def succes"
  },
  {
    "path": "app/controllers/concerns/course/activity_feeds_concern.rb",
    "chars": 370,
    "preview": "# frozen_string_literal: true\nmodule Course::ActivityFeedsConcern\n  extend ActiveSupport::Concern\n\n  # Loads recent acti"
  },
  {
    "path": "app/controllers/concerns/course/assessment/answer/update_answer_concern.rb",
    "chars": 3067,
    "preview": "# frozen_string_literal: true\nmodule Course::Assessment::Answer::UpdateAnswerConcern\n  extend ActiveSupport::Concern\n\n  "
  },
  {
    "path": "app/controllers/concerns/course/assessment/koditsu_assessment_concern.rb",
    "chars": 3639,
    "preview": "# frozen_string_literal: true\nmodule Course::Assessment::KoditsuAssessmentConcern\n  extend ActiveSupport::Concern\n\n  def"
  },
  {
    "path": "app/controllers/concerns/course/assessment/koditsu_assessment_invitation_concern.rb",
    "chars": 906,
    "preview": "# frozen_string_literal: true\nmodule Course::Assessment::KoditsuAssessmentInvitationConcern\n  extend ActiveSupport::Conc"
  },
  {
    "path": "app/controllers/concerns/course/assessment/live_feedback/file_concern.rb",
    "chars": 1382,
    "preview": "# frozen_string_literal: true\nmodule Course::Assessment::LiveFeedback::FileConcern\n  extend ActiveSupport::Concern\n\n  de"
  },
  {
    "path": "app/controllers/concerns/course/assessment/live_feedback/message_concern.rb",
    "chars": 1170,
    "preview": "# frozen_string_literal: true\nmodule Course::Assessment::LiveFeedback::MessageConcern\n  extend ActiveSupport::Concern\n  "
  },
  {
    "path": "app/controllers/concerns/course/assessment/live_feedback/message_file_concern.rb",
    "chars": 1451,
    "preview": "# frozen_string_literal: true\nmodule Course::Assessment::LiveFeedback::MessageFileConcern\n  extend ActiveSupport::Concer"
  },
  {
    "path": "app/controllers/concerns/course/assessment/live_feedback/thread_concern.rb",
    "chars": 1495,
    "preview": "# frozen_string_literal: true\nmodule Course::Assessment::LiveFeedback::ThreadConcern\n  extend ActiveSupport::Concern\n\n  "
  },
  {
    "path": "app/controllers/concerns/course/assessment/monitoring/seb_payload_concern.rb",
    "chars": 696,
    "preview": "# frozen_string_literal: true\nmodule Course::Assessment::Monitoring::SebPayloadConcern\n  extend ActiveSupport::Concern\n\n"
  },
  {
    "path": "app/controllers/concerns/course/assessment/monitoring_concern.rb",
    "chars": 2939,
    "preview": "# frozen_string_literal: true\nmodule Course::Assessment::MonitoringConcern\n  extend ActiveSupport::Concern\n\n  include Co"
  },
  {
    "path": "app/controllers/concerns/course/assessment/question/codaveri_question_concern.rb",
    "chars": 1012,
    "preview": "# frozen_string_literal: true\nmodule Course::Assessment::Question::CodaveriQuestionConcern\n  extend ActiveSupport::Conce"
  },
  {
    "path": "app/controllers/concerns/course/assessment/question/koditsu_question_concern.rb",
    "chars": 4362,
    "preview": "# frozen_string_literal: true\n# rubocop:disable Metrics/ModuleLength\nmodule Course::Assessment::Question::KoditsuQuestio"
  },
  {
    "path": "app/controllers/concerns/course/assessment/question/multiple_responses_concern.rb",
    "chars": 769,
    "preview": "# frozen_string_literal: true\nmodule Course::Assessment::Question::MultipleResponsesConcern\n  extend ActiveSupport::Conc"
  },
  {
    "path": "app/controllers/concerns/course/assessment/question/rubric_based_response_controller_concern.rb",
    "chars": 1957,
    "preview": "# frozen_string_literal: true\nmodule Course::Assessment::Question::RubricBasedResponseControllerConcern\n  include Course"
  },
  {
    "path": "app/controllers/concerns/course/assessment/question/rubric_based_response_question_concern.rb",
    "chars": 929,
    "preview": "# frozen_string_literal: true\nmodule Course::Assessment::Question::RubricBasedResponseQuestionConcern\n  extend ActiveSup"
  },
  {
    "path": "app/controllers/concerns/course/assessment/question_bundle_assignment_concern.rb",
    "chars": 8277,
    "preview": "# frozen_string_literal: true\nmodule Course::Assessment::QuestionBundleAssignmentConcern\n  extend ActiveSupport::Concern"
  },
  {
    "path": "app/controllers/concerns/course/assessment/submission/koditsu/answers_concern.rb",
    "chars": 3910,
    "preview": "# frozen_string_literal: true\nmodule Course::Assessment::Submission::Koditsu::AnswersConcern\n  extend ActiveSupport::Con"
  },
  {
    "path": "app/controllers/concerns/course/assessment/submission/koditsu/submission_times_concern.rb",
    "chars": 668,
    "preview": "# frozen_string_literal: true\nmodule Course::Assessment::Submission::Koditsu::SubmissionTimesConcern\n  extend ActiveSupp"
  },
  {
    "path": "app/controllers/concerns/course/assessment/submission/koditsu/submissions_concern.rb",
    "chars": 3939,
    "preview": "# frozen_string_literal: true\nmodule Course::Assessment::Submission::Koditsu::SubmissionsConcern\n  extend ActiveSupport:"
  },
  {
    "path": "app/controllers/concerns/course/assessment/submission/koditsu/test_cases_concern.rb",
    "chars": 882,
    "preview": "# frozen_string_literal: true\nmodule Course::Assessment::Submission::Koditsu::TestCasesConcern\n  extend ActiveSupport::C"
  },
  {
    "path": "app/controllers/concerns/course/assessment/submission/koditsu/users_concern.rb",
    "chars": 1366,
    "preview": "# frozen_string_literal: true\nmodule Course::Assessment::Submission::Koditsu::UsersConcern\n  extend ActiveSupport::Conce"
  },
  {
    "path": "app/controllers/concerns/course/assessment/submission/monitoring_concern.rb",
    "chars": 1439,
    "preview": "# frozen_string_literal: true\nmodule Course::Assessment::Submission::MonitoringConcern\n  extend ActiveSupport::Concern\n\n"
  },
  {
    "path": "app/controllers/concerns/course/assessment/submission/submissions_controller_service_concern.rb",
    "chars": 1461,
    "preview": "# frozen_string_literal: true\nmodule Course::Assessment::Submission::SubmissionsControllerServiceConcern\n  extend Active"
  },
  {
    "path": "app/controllers/concerns/course/assessment/submission_concern.rb",
    "chars": 1044,
    "preview": "# frozen_string_literal: true\nmodule Course::Assessment::SubmissionConcern\n  extend ActiveSupport::Concern\n\n  private\n\n "
  },
  {
    "path": "app/controllers/concerns/course/assessment_conditional_concern.rb",
    "chars": 412,
    "preview": "# frozen_string_literal: true\nmodule Course::AssessmentConditionalConcern\n  extend ActiveSupport::Concern\n\n  def success"
  },
  {
    "path": "app/controllers/concerns/course/cikgo_chats_concern.rb",
    "chars": 780,
    "preview": "# frozen_string_literal: true\nmodule Course::CikgoChatsConcern\n  extend ActiveSupport::Concern\n\n  def find_or_create_roo"
  },
  {
    "path": "app/controllers/concerns/course/cikgo_push_concern.rb",
    "chars": 922,
    "preview": "# frozen_string_literal: true\nmodule Course::CikgoPushConcern\n  extend ActiveSupport::Concern\n  include Cikgo::PushableI"
  },
  {
    "path": "app/controllers/concerns/course/discussion/posts_concern.rb",
    "chars": 1787,
    "preview": "# frozen_string_literal: true\nmodule Course::Discussion::PostsConcern\n  extend ActiveSupport::Concern\n\n  included do\n   "
  },
  {
    "path": "app/controllers/concerns/course/forum/auto_answering_concern.rb",
    "chars": 2588,
    "preview": "# frozen_string_literal: true\nmodule Course::Forum::AutoAnsweringConcern\n  extend ActiveSupport::Concern\n\n  def auto_ans"
  },
  {
    "path": "app/controllers/concerns/course/forum/topic_controller_hiding_concern.rb",
    "chars": 341,
    "preview": "# frozen_string_literal: true\nmodule Course::Forum::TopicControllerHidingConcern\n  extend ActiveSupport::Concern\n\n  def "
  },
  {
    "path": "app/controllers/concerns/course/forum/topic_controller_locking_concern.rb",
    "chars": 342,
    "preview": "# frozen_string_literal: true\nmodule Course::Forum::TopicControllerLockingConcern\n  extend ActiveSupport::Concern\n\n  def"
  },
  {
    "path": "app/controllers/concerns/course/forum/topic_controller_subscription_concern.rb",
    "chars": 561,
    "preview": "# frozen_string_literal: true\nmodule Course::Forum::TopicControllerSubscriptionConcern\n  extend ActiveSupport::Concern\n\n"
  },
  {
    "path": "app/controllers/concerns/course/group/group_manager_concern.rb",
    "chars": 364,
    "preview": "# frozen_string_literal: true\nmodule Course::Group::GroupManagerConcern\n  extend ActiveSupport::Concern\n  def manageable"
  },
  {
    "path": "app/controllers/concerns/course/koditsu_workspace_concern.rb",
    "chars": 386,
    "preview": "# frozen_string_literal: true\nmodule Course::KoditsuWorkspaceConcern\n  extend ActiveSupport::Concern\n\n  def setup_kodits"
  },
  {
    "path": "app/controllers/concerns/course/lesson_plan/acts_as_lesson_plan_item_concern.rb",
    "chars": 878,
    "preview": "# frozen_string_literal: true\nmodule Course::LessonPlan::ActsAsLessonPlanItemConcern\n  extend ActiveSupport::Concern\n\n  "
  },
  {
    "path": "app/controllers/concerns/course/lesson_plan/learning_rate_concern.rb",
    "chars": 7878,
    "preview": "# frozen_string_literal: true\nmodule Course::LessonPlan::LearningRateConcern\n  extend ActiveSupport::Concern\n\n  include "
  },
  {
    "path": "app/controllers/concerns/course/lesson_plan/personalization_concern.rb",
    "chars": 3275,
    "preview": "# frozen_string_literal: true\nmodule Course::LessonPlan::PersonalizationConcern\n  extend ActiveSupport::Concern\n\n  # Dis"
  },
  {
    "path": "app/controllers/concerns/course/lesson_plan/stories_concern.rb",
    "chars": 905,
    "preview": "# frozen_string_literal: true\nmodule Course::LessonPlan::StoriesConcern\n  extend ActiveSupport::Concern\n\n  def delete_al"
  },
  {
    "path": "app/controllers/concerns/course/lesson_plan/strategies/base_personalization_strategy.rb",
    "chars": 4049,
    "preview": "# frozen_string_literal: true\n# The BasePersonalizationStrategy declares operations common to all, if not most, personal"
  },
  {
    "path": "app/controllers/concerns/course/lesson_plan/strategies/fixed_personalization_strategy.rb",
    "chars": 1303,
    "preview": "# frozen_string_literal: true\nclass Course::LessonPlan::Strategies::FixedPersonalizationStrategy <\n  Course::LessonPlan:"
  },
  {
    "path": "app/controllers/concerns/course/lesson_plan/strategies/fomo_personalization_strategy.rb",
    "chars": 8185,
    "preview": "# frozen_string_literal: true\nclass Course::LessonPlan::Strategies::FomoPersonalizationStrategy <\n  Course::LessonPlan::"
  },
  {
    "path": "app/controllers/concerns/course/lesson_plan/strategies/otot_personalization_strategy.rb",
    "chars": 3157,
    "preview": "# frozen_string_literal: true\nclass Course::LessonPlan::Strategies::OtotPersonalizationStrategy <\n  Course::LessonPlan::"
  },
  {
    "path": "app/controllers/concerns/course/lesson_plan/strategies/stragglers_personalization_strategy.rb",
    "chars": 8964,
    "preview": "# frozen_string_literal: true\nclass Course::LessonPlan::Strategies::StragglersPersonalizationStrategy <\n  Course::Lesson"
  },
  {
    "path": "app/controllers/concerns/course/reminder_service_concern.rb",
    "chars": 656,
    "preview": "# frozen_string_literal: true\nmodule Course::ReminderServiceConcern\n  extend ActiveSupport::Concern\n\n  # Converts a set "
  },
  {
    "path": "app/controllers/concerns/course/scholaistic/concern.rb",
    "chars": 3715,
    "preview": "# frozen_string_literal: true\nmodule Course::Scholaistic::Concern\n  extend ActiveSupport::Concern\n\n  include Course::Use"
  },
  {
    "path": "app/controllers/concerns/course/ssid_folder_concern.rb",
    "chars": 867,
    "preview": "# frozen_string_literal: true\nmodule Course::SsidFolderConcern\n  extend ActiveSupport::Concern\n\n  def sync_course_ssid_f"
  },
  {
    "path": "app/controllers/concerns/course/statistics/counts_concern.rb",
    "chars": 4478,
    "preview": "# frozen_string_literal: true\nmodule Course::Statistics::CountsConcern\n  include Course::Statistics::ReferenceTimesConce"
  },
  {
    "path": "app/controllers/concerns/course/statistics/grades_concern.rb",
    "chars": 1653,
    "preview": "# frozen_string_literal: true\nmodule Course::Statistics::GradesConcern\n  private\n\n  def grade_statistics_hash\n    return"
  },
  {
    "path": "app/controllers/concerns/course/statistics/reference_times_concern.rb",
    "chars": 3413,
    "preview": "# frozen_string_literal: true\nmodule Course::Statistics::ReferenceTimesConcern\n  private\n\n  def personal_end_at_hash(ass"
  },
  {
    "path": "app/controllers/concerns/course/statistics/submissions_concern.rb",
    "chars": 4892,
    "preview": "# frozen_string_literal: true\nmodule Course::Statistics::SubmissionsConcern\n  include Course::Statistics::ReferenceTimes"
  },
  {
    "path": "app/controllers/concerns/course/statistics/times_concern.rb",
    "chars": 936,
    "preview": "# frozen_string_literal: true\nmodule Course::Statistics::TimesConcern\n  private\n\n  def duration_statistics_hash\n    retu"
  },
  {
    "path": "app/controllers/concerns/course/statistics/users_concern.rb",
    "chars": 1109,
    "preview": "# frozen_string_literal: true\nmodule Course::Statistics::UsersConcern\n  private\n\n  def group_names_hash\n    group_names "
  },
  {
    "path": "app/controllers/concerns/course/survey/reordering_concern.rb",
    "chars": 4102,
    "preview": "# frozen_string_literal: true\nmodule Course::Survey::ReorderingConcern\n  extend ActiveSupport::Concern\n\n  def reorder_se"
  },
  {
    "path": "app/controllers/concerns/course/unread_counts_concern.rb",
    "chars": 1998,
    "preview": "# frozen_string_literal: true\nmodule Course::UnreadCountsConcern\n  extend ActiveSupport::Concern\n\n  private\n\n  def unrea"
  },
  {
    "path": "app/controllers/concerns/course/users_controller_management_concern.rb",
    "chars": 6781,
    "preview": "# frozen_string_literal: true\nmodule Course::UsersControllerManagementConcern\n  extend ActiveSupport::Concern\n\n  include"
  },
  {
    "path": "app/controllers/concerns/signals/emission_concern.rb",
    "chars": 1000,
    "preview": "# frozen_string_literal: true\nmodule Signals::EmissionConcern\n  extend ActiveSupport::Concern\n\n  include ActiveSupport::"
  },
  {
    "path": "app/controllers/concerns/signals/slices/announcements.rb",
    "chars": 205,
    "preview": "# frozen_string_literal: true\nmodule Signals::Slices::Announcements\n  include Course::UnreadCountsConcern\n\n  def generat"
  },
  {
    "path": "app/controllers/concerns/signals/slices/assessment_submissions.rb",
    "chars": 242,
    "preview": "# frozen_string_literal: true\nmodule Signals::Slices::AssessmentSubmissions\n  include Course::UnreadCountsConcern\n\n  def"
  },
  {
    "path": "app/controllers/concerns/signals/slices/cikgo_mission_control.rb",
    "chars": 178,
    "preview": "# frozen_string_literal: true\nmodule Signals::Slices::CikgoMissionControl\n  def generate_sync_for_cikgo_mission_control\n"
  },
  {
    "path": "app/controllers/concerns/signals/slices/cikgo_open_threads_count.rb",
    "chars": 170,
    "preview": "# frozen_string_literal: true\nmodule Signals::Slices::CikgoOpenThreadsCount\n  def generate_sync_for_cikgo_open_threads_c"
  },
  {
    "path": "app/controllers/concerns/signals/slices/comments.rb",
    "chars": 194,
    "preview": "# frozen_string_literal: true\nmodule Signals::Slices::Comments\n  include Course::UnreadCountsConcern\n\n  def generate_syn"
  },
  {
    "path": "app/controllers/concerns/signals/slices/enrol_requests.rb",
    "chars": 207,
    "preview": "# frozen_string_literal: true\nmodule Signals::Slices::EnrolRequests\n  include Course::UnreadCountsConcern\n\n  def generat"
  },
  {
    "path": "app/controllers/concerns/signals/slices/forums.rb",
    "chars": 183,
    "preview": "# frozen_string_literal: true\nmodule Signals::Slices::Forums\n  include Course::UnreadCountsConcern\n\n  def generate_sync_"
  },
  {
    "path": "app/controllers/concerns/signals/slices/videos.rb",
    "chars": 180,
    "preview": "# frozen_string_literal: true\nmodule Signals::Slices::Videos\n  include Course::UnreadCountsConcern\n\n  def generate_sync_"
  },
  {
    "path": "app/controllers/course/achievement/achievements_controller.rb",
    "chars": 3582,
    "preview": "# frozen_string_literal: true\nclass Course::Achievement::AchievementsController < Course::Achievement::Controller\n  befo"
  },
  {
    "path": "app/controllers/course/achievement/condition/achievements_controller.rb",
    "chars": 189,
    "preview": "# frozen_string_literal: true\nclass Course::Achievement::Condition::AchievementsController <\n  Course::Condition::Achiev"
  },
  {
    "path": "app/controllers/course/achievement/condition/assessments_controller.rb",
    "chars": 187,
    "preview": "# frozen_string_literal: true\nclass Course::Achievement::Condition::AssessmentsController <\n  Course::Condition::Assessm"
  },
  {
    "path": "app/controllers/course/achievement/condition/levels_controller.rb",
    "chars": 175,
    "preview": "# frozen_string_literal: true\nclass Course::Achievement::Condition::LevelsController < Course::Condition::LevelsControll"
  },
  {
    "path": "app/controllers/course/achievement/condition/scholaistic_assessments_controller.rb",
    "chars": 209,
    "preview": "# frozen_string_literal: true\nclass Course::Achievement::Condition::ScholaisticAssessmentsController <\n  Course::Conditi"
  },
  {
    "path": "app/controllers/course/achievement/condition/surveys_controller.rb",
    "chars": 177,
    "preview": "# frozen_string_literal: true\nclass Course::Achievement::Condition::SurveysController < Course::Condition::SurveysContro"
  },
  {
    "path": "app/controllers/course/achievement/controller.rb",
    "chars": 416,
    "preview": "# frozen_string_literal: true\nclass Course::Achievement::Controller < Course::ComponentController\n  load_and_authorize_r"
  },
  {
    "path": "app/controllers/course/admin/admin_controller.rb",
    "chars": 2130,
    "preview": "# frozen_string_literal: true\nclass Course::Admin::AdminController < Course::Admin::Controller\n  def index\n    respond_t"
  },
  {
    "path": "app/controllers/course/admin/announcement_settings_controller.rb",
    "chars": 593,
    "preview": "# frozen_string_literal: true\nclass Course::Admin::AnnouncementSettingsController < Course::Admin::Controller\n  def edit"
  },
  {
    "path": "app/controllers/course/admin/assessment_settings_controller.rb",
    "chars": 2295,
    "preview": "# frozen_string_literal: true\nclass Course::Admin::AssessmentSettingsController < Course::Admin::Controller\n  def edit\n "
  },
  {
    "path": "app/controllers/course/admin/assessments/categories_controller.rb",
    "chars": 1258,
    "preview": "# frozen_string_literal: true\nclass Course::Admin::Assessments::CategoriesController < Course::Admin::Controller\n  load_"
  },
  {
    "path": "app/controllers/course/admin/assessments/tabs_controller.rb",
    "chars": 1288,
    "preview": "# frozen_string_literal: true\nclass Course::Admin::Assessments::TabsController < Course::Admin::Controller\n  load_and_au"
  },
  {
    "path": "app/controllers/course/admin/codaveri_settings_controller.rb",
    "chars": 2374,
    "preview": "# frozen_string_literal: true\nclass Course::Admin::CodaveriSettingsController < Course::Admin::Controller\n  def edit\n   "
  },
  {
    "path": "app/controllers/course/admin/component_settings_controller.rb",
    "chars": 1259,
    "preview": "# frozen_string_literal: true\nclass Course::Admin::ComponentSettingsController < Course::Admin::Controller\n  include Cou"
  },
  {
    "path": "app/controllers/course/admin/controller.rb",
    "chars": 399,
    "preview": "# frozen_string_literal: true\nclass Course::Admin::Controller < Course::ComponentController\n  before_action :authorize_a"
  },
  {
    "path": "app/controllers/course/admin/discussion/topic_settings_controller.rb",
    "chars": 594,
    "preview": "# frozen_string_literal: true\nclass Course::Admin::Discussion::TopicSettingsController < Course::Admin::Controller\n  def"
  },
  {
    "path": "app/controllers/course/admin/forum_settings_controller.rb",
    "chars": 631,
    "preview": "# frozen_string_literal: true\nclass Course::Admin::ForumSettingsController < Course::Admin::Controller\n  def edit\n    re"
  },
  {
    "path": "app/controllers/course/admin/leaderboard_settings_controller.rb",
    "chars": 667,
    "preview": "# frozen_string_literal: true\nclass Course::Admin::LeaderboardSettingsController < Course::Admin::Controller\n  def edit\n"
  },
  {
    "path": "app/controllers/course/admin/lesson_plan_settings_controller.rb",
    "chars": 1496,
    "preview": "# frozen_string_literal: true\nclass Course::Admin::LessonPlanSettingsController < Course::Admin::Controller\n  before_act"
  },
  {
    "path": "app/controllers/course/admin/material_settings_controller.rb",
    "chars": 573,
    "preview": "# frozen_string_literal: true\nclass Course::Admin::MaterialSettingsController < Course::Admin::Controller\n  def edit\n   "
  },
  {
    "path": "app/controllers/course/admin/notification_settings_controller.rb",
    "chars": 903,
    "preview": "# frozen_string_literal: true\nclass Course::Admin::NotificationSettingsController < Course::Admin::Controller\n  def edit"
  },
  {
    "path": "app/controllers/course/admin/rag_wise_settings_controller.rb",
    "chars": 3614,
    "preview": "# frozen_string_literal: true\nclass Course::Admin::RagWiseSettingsController < Course::Admin::Controller\n  before_action"
  },
  {
    "path": "app/controllers/course/admin/scholaistic_settings_controller.rb",
    "chars": 2102,
    "preview": "# frozen_string_literal: true\nclass Course::Admin::ScholaisticSettingsController < Course::Admin::Controller\n  skip_forg"
  },
  {
    "path": "app/controllers/course/admin/sidebar_settings_controller.rb",
    "chars": 683,
    "preview": "# frozen_string_literal: true\nclass Course::Admin::SidebarSettingsController < Course::Admin::Controller\n  before_action"
  },
  {
    "path": "app/controllers/course/admin/stories_settings_controller.rb",
    "chars": 1007,
    "preview": "# frozen_string_literal: true\nclass Course::Admin::StoriesSettingsController < Course::Admin::Controller\n  include Cours"
  },
  {
    "path": "app/controllers/course/admin/video_settings_controller.rb",
    "chars": 786,
    "preview": "# frozen_string_literal: true\nclass Course::Admin::VideoSettingsController < Course::Admin::Controller\n  def edit\n    re"
  },
  {
    "path": "app/controllers/course/admin/videos/tabs_controller.rb",
    "chars": 909,
    "preview": "# frozen_string_literal: true\nclass Course::Admin::Videos::TabsController < Course::Admin::Controller\n  load_and_authori"
  },
  {
    "path": "app/controllers/course/announcements_controller.rb",
    "chars": 1893,
    "preview": "# frozen_string_literal: true\nclass Course::AnnouncementsController < Course::ComponentController\n  include Course::User"
  },
  {
    "path": "app/controllers/course/assessment/assessments_controller.rb",
    "chars": 16403,
    "preview": "# frozen_string_literal: true\nclass Course::Assessment::AssessmentsController < Course::Assessment::Controller # rubocop"
  },
  {
    "path": "app/controllers/course/assessment/categories_controller.rb",
    "chars": 860,
    "preview": "# frozen_string_literal: true\nclass Course::Assessment::CategoriesController < Course::ComponentController\n  load_and_au"
  },
  {
    "path": "app/controllers/course/assessment/component_controller.rb",
    "chars": 113,
    "preview": "# frozen_string_literal: true\nclass Course::Assessment::ComponentController < Course::Assessment::Controller\nend\n"
  },
  {
    "path": "app/controllers/course/assessment/condition/achievements_controller.rb",
    "chars": 187,
    "preview": "# frozen_string_literal: true\nclass Course::Assessment::Condition::AchievementsController <\n  Course::Condition::Achieve"
  },
  {
    "path": "app/controllers/course/assessment/condition/assessments_controller.rb",
    "chars": 185,
    "preview": "# frozen_string_literal: true\nclass Course::Assessment::Condition::AssessmentsController <\n  Course::Condition::Assessme"
  },
  {
    "path": "app/controllers/course/assessment/condition/levels_controller.rb",
    "chars": 173,
    "preview": "# frozen_string_literal: true\nclass Course::Assessment::Condition::LevelsController < Course::Condition::LevelsControlle"
  },
  {
    "path": "app/controllers/course/assessment/condition/scholaistic_assessments_controller.rb",
    "chars": 207,
    "preview": "# frozen_string_literal: true\nclass Course::Assessment::Condition::ScholaisticAssessmentsController <\n  Course::Conditio"
  },
  {
    "path": "app/controllers/course/assessment/condition/surveys_controller.rb",
    "chars": 175,
    "preview": "# frozen_string_literal: true\nclass Course::Assessment::Condition::SurveysController < Course::Condition::SurveysControl"
  },
  {
    "path": "app/controllers/course/assessment/controller.rb",
    "chars": 978,
    "preview": "# frozen_string_literal: true\nclass Course::Assessment::Controller < Course::ComponentController\n  before_action :load_a"
  },
  {
    "path": "app/controllers/course/assessment/mock_answers_controller.rb",
    "chars": 564,
    "preview": "# frozen_string_literal: true\nclass Course::Assessment::MockAnswersController < Course::Assessment::QuestionsController\n"
  },
  {
    "path": "app/controllers/course/assessment/question/controller.rb",
    "chars": 2469,
    "preview": "# frozen_string_literal: true\nclass Course::Assessment::Question::Controller < Course::Assessment::ComponentController\n "
  },
  {
    "path": "app/controllers/course/assessment/question/forum_post_responses_controller.rb",
    "chars": 2246,
    "preview": "# frozen_string_literal: true\nclass Course::Assessment::Question::ForumPostResponsesController < Course::Assessment::Que"
  },
  {
    "path": "app/controllers/course/assessment/question/multiple_responses_controller.rb",
    "chars": 5906,
    "preview": "# frozen_string_literal: true\nclass Course::Assessment::Question::MultipleResponsesController < Course::Assessment::Ques"
  },
  {
    "path": "app/controllers/course/assessment/question/programming_controller.rb",
    "chars": 5534,
    "preview": "# frozen_string_literal: true\nclass Course::Assessment::Question::ProgrammingController < Course::Assessment::Question::"
  },
  {
    "path": "app/controllers/course/assessment/question/rubric_based_responses_controller.rb",
    "chars": 4521,
    "preview": "# frozen_string_literal: true\nclass Course::Assessment::Question::RubricBasedResponsesController < Course::Assessment::Q"
  },
  {
    "path": "app/controllers/course/assessment/question/scribing_controller.rb",
    "chars": 3278,
    "preview": "# frozen_string_literal: true\nclass Course::Assessment::Question::ScribingController < Course::Assessment::Question::Con"
  },
  {
    "path": "app/controllers/course/assessment/question/text_responses_controller.rb",
    "chars": 3434,
    "preview": "# frozen_string_literal: true\nclass Course::Assessment::Question::TextResponsesController < Course::Assessment::Question"
  },
  {
    "path": "app/controllers/course/assessment/question/voice_responses_controller.rb",
    "chars": 1958,
    "preview": "# frozen_string_literal: true\nclass Course::Assessment::Question::VoiceResponsesController < Course::Assessment::Questio"
  },
  {
    "path": "app/controllers/course/assessment/question_bundle_assignments_controller.rb",
    "chars": 3835,
    "preview": "# frozen_string_literal: true\nclass Course::Assessment::QuestionBundleAssignmentsController < Course::Assessment::Contro"
  },
  {
    "path": "app/controllers/course/assessment/question_bundle_questions_controller.rb",
    "chars": 1909,
    "preview": "# frozen_string_literal: true\nclass Course::Assessment::QuestionBundleQuestionsController < Course::Assessment::Controll"
  },
  {
    "path": "app/controllers/course/assessment/question_bundles_controller.rb",
    "chars": 1090,
    "preview": "# frozen_string_literal: true\nclass Course::Assessment::QuestionBundlesController < Course::Assessment::Controller\n  loa"
  },
  {
    "path": "app/controllers/course/assessment/question_groups_controller.rb",
    "chars": 1128,
    "preview": "# frozen_string_literal: true\nclass Course::Assessment::QuestionGroupsController < Course::Assessment::Controller\n  load"
  },
  {
    "path": "app/controllers/course/assessment/questions_controller.rb",
    "chars": 2197,
    "preview": "# frozen_string_literal: true\nclass Course::Assessment::QuestionsController < Course::Assessment::Controller\n  load_and_"
  },
  {
    "path": "app/controllers/course/assessment/rubrics_controller.rb",
    "chars": 5428,
    "preview": "# frozen_string_literal: true\nclass Course::Assessment::RubricsController < Course::Assessment::QuestionsController # ru"
  },
  {
    "path": "app/controllers/course/assessment/sessions_controller.rb",
    "chars": 1582,
    "preview": "# frozen_string_literal: true\nclass Course::Assessment::SessionsController < Course::Assessment::Controller\n  before_act"
  },
  {
    "path": "app/controllers/course/assessment/skill_branches_controller.rb",
    "chars": 1221,
    "preview": "# frozen_string_literal: true\nclass Course::Assessment::SkillBranchesController < Course::ComponentController\n  load_and"
  },
  {
    "path": "app/controllers/course/assessment/skills_controller.rb",
    "chars": 1531,
    "preview": "# frozen_string_literal: true\nclass Course::Assessment::SkillsController < Course::ComponentController\n  load_and_author"
  },
  {
    "path": "app/controllers/course/assessment/submission/answer/answers_controller.rb",
    "chars": 3390,
    "preview": "# frozen_string_literal: true\n\nclass Course::Assessment::Submission::Answer::AnswersController <\n  Course::Assessment::S"
  },
  {
    "path": "app/controllers/course/assessment/submission/answer/controller.rb",
    "chars": 440,
    "preview": "# frozen_string_literal: true\nclass Course::Assessment::Submission::Answer::Controller < \\\n  Course::Assessment::Submiss"
  },
  {
    "path": "app/controllers/course/assessment/submission/answer/forum_post_response/posts_controller.rb",
    "chars": 346,
    "preview": "# frozen_string_literal: true\nclass Course::Assessment::Submission::Answer::ForumPostResponse::PostsController < \\\n  Cou"
  },
  {
    "path": "app/controllers/course/assessment/submission/answer/programming/annotations_controller.rb",
    "chars": 2471,
    "preview": "# frozen_string_literal: true\nclass Course::Assessment::Submission::Answer::Programming::AnnotationsController < \\\n  Cou"
  },
  {
    "path": "app/controllers/course/assessment/submission/answer/programming/controller.rb",
    "chars": 282,
    "preview": "# frozen_string_literal: true\nclass Course::Assessment::Submission::Answer::Programming::Controller < \\\n  Course::Assess"
  },
  {
    "path": "app/controllers/course/assessment/submission/answer/programming/programming_controller.rb",
    "chars": 1456,
    "preview": "# frozen_string_literal: true\nclass Course::Assessment::Submission::Answer::Programming::ProgrammingController < \\\n  Cou"
  },
  {
    "path": "app/controllers/course/assessment/submission/answer/scribing/controller.rb",
    "chars": 448,
    "preview": "# frozen_string_literal: true\nclass Course::Assessment::Submission::Answer::Scribing::Controller < \\\n  Course::Assessmen"
  },
  {
    "path": "app/controllers/course/assessment/submission/answer/scribing/scribbles_controller.rb",
    "chars": 787,
    "preview": "# frozen_string_literal: true\nclass Course::Assessment::Submission::Answer::Scribing::ScribblesController < \\\n  Course::"
  }
]

// ... and 4209 more files (download for full content)

About this extraction

This page contains the full source code of the Coursemology/coursemology2 GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 4409 files (10.8 MB), approximately 3.1M tokens, and a symbol index with 10175 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!