studium 0.18.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +3310 -0
- data/bin/all_passed_exams +14 -0
- data/bin/check_description_of_these_lectures +7 -0
- data/bin/curriculum_module_displayer +7 -0
- data/bin/cycle +7 -0
- data/bin/d10 +7 -0
- data/bin/d100 +7 -0
- data/bin/d15 +7 -0
- data/bin/d150 +7 -0
- data/bin/d20 +7 -0
- data/bin/d25 +7 -0
- data/bin/d3 +7 -0
- data/bin/d30 +7 -0
- data/bin/d5 +7 -0
- data/bin/determine_curricula +7 -0
- data/bin/display_lecture_url +7 -0
- data/bin/exam_registration_at +7 -0
- data/bin/exam_statistics +7 -0
- data/bin/exams_per_month +9 -0
- data/bin/finished_exams_at_this_university +7 -0
- data/bin/flashcards +7 -0
- data/bin/from_curriculum_id_to_university +9 -0
- data/bin/location_to_this_exam_topic.rb +7 -0
- data/bin/mandatory_continuous_assessment +7 -0
- data/bin/mandatory_upcoming_courses +10 -0
- data/bin/n_ECTS +7 -0
- data/bin/n_exam_questions_already_answered +15 -0
- data/bin/names_of_all_solved_exams +7 -0
- data/bin/not_completed_exams +7 -0
- data/bin/nquestions +7 -0
- data/bin/nsolved +7 -0
- data/bin/open_last_exam_question_asked_file +7 -0
- data/bin/passed_exams +7 -0
- data/bin/passed_pr/303/274fungsimmanente_courses +7 -0
- data/bin/passed_this_exam_on +10 -0
- data/bin/pdf_for +7 -0
- data/bin/question_answer +7 -0
- data/bin/random_exam_topic +7 -0
- data/bin/registered_for_this_exam +15 -0
- data/bin/report_solved_topics +7 -0
- data/bin/return_n_ects_from_this_file +7 -0
- data/bin/return_n_questions_solved_in_total +7 -0
- data/bin/rti_conflict +7 -0
- data/bin/search_for_n_ects +7 -0
- data/bin/show_lectures_on_the_commandline +7 -0
- data/bin/show_passed_exams_having_this_grade +7 -0
- data/bin/show_themes +7 -0
- data/bin/solved +9 -0
- data/bin/solved_ects +7 -0
- data/bin/studienkennzahl +7 -0
- data/bin/studium +7 -0
- data/bin/studium_actions +7 -0
- data/bin/studium_skeleton +7 -0
- data/bin/ufind +7 -0
- data/bin/upcoming_exams +7 -0
- data/bin/week_parser +7 -0
- data/doc/ECTS_CONSIDERATIONS/ECTS_CONSIDERATIONS.md +85 -0
- data/doc/HOW_TO_DETERMINE_WHICH_PART_IS_THE_QUESTION_AND_WHICH_PART_IS_THE_ANSWER/HOW_TO_DETERMINE_WHICH_PART_IS_THE_QUESTION_AND_WHICH_PART_IS_THE_ANSWER.md +44 -0
- data/doc/README.gen +3263 -0
- data/doc/SQL_database_specification/SQL_database_specification.md +46 -0
- data/doc/deprecated_components/deprecated_components.md +46 -0
- data/doc/documentation_for_the_file_lecture_information/documentation_for_the_file_lecture_information.md +311 -0
- data/doc/elegant_colours/elegant_colours.md +21 -0
- data/doc/statistics/yearly_statistics.md +8 -0
- data/doc/todo/todo_for_the_graphical_parts_of_the_studium_gem_including_www_related_aspects.md +92 -0
- data/doc/todo/todo_for_the_studium_gem.md +55 -0
- data/img/STUDIES.png +0 -0
- data/lib/studium/actions/actions.rb +134 -0
- data/lib/studium/autoinclude.rb +7 -0
- data/lib/studium/base/base.rb +3554 -0
- data/lib/studium/base/commandline_arguments_module/commandline_arguments_module.rb +115 -0
- data/lib/studium/base/html_colours_module.rb +632 -0
- data/lib/studium/base/runmode_module/runmode_module.rb +103 -0
- data/lib/studium/c/README.md +2 -0
- data/lib/studium/c/a.out +0 -0
- data/lib/studium/c/obtain_random_entry.c +11 -0
- data/lib/studium/check_and_sanitize/README.md +15 -0
- data/lib/studium/check_and_sanitize/check_curriculum_for_correct_separation_of_bachelor_and_master.rb +141 -0
- data/lib/studium/check_and_sanitize/check_for_all_exam_topics_being_registered.rb +118 -0
- data/lib/studium/check_and_sanitize/check_for_correct_themes_of_each_course.rb +100 -0
- data/lib/studium/check_and_sanitize/check_for_existing_description_of_this_lecture.rb +194 -0
- data/lib/studium/check_and_sanitize/check_important_exams.rb +138 -0
- data/lib/studium/check_and_sanitize/check_the_lecture_information_file.rb +166 -0
- data/lib/studium/check_and_sanitize/correct_all_dates_in_the_file_lecture_information.rb +115 -0
- data/lib/studium/check_and_sanitize/date_sanitizer.rb +350 -0
- data/lib/studium/check_and_sanitize/find_duplicate_lectures.rb +124 -0
- data/lib/studium/check_and_sanitize/missing_priority_entry.rb +44 -0
- data/lib/studium/check_and_sanitize/sanitize_lecture_information.rb +434 -0
- data/lib/studium/colours/colours.rb +1711 -0
- data/lib/studium/commandline/commandline.rb +1848 -0
- data/lib/studium/constants/constants.rb +2063 -0
- data/lib/studium/css/project.css +273 -0
- data/lib/studium/curricula/attribute_lecture_to_curriculum/attribute_boku_lecture_to_curriculum.rb +384 -0
- data/lib/studium/curricula/attribute_lecture_to_curriculum/attribute_lecture_to_curriculum.rb +238 -0
- data/lib/studium/curricula/curricula_from_this_website/curricula_from_this_website.rb +141 -0
- data/lib/studium/curricula/curriculum.rb +213 -0
- data/lib/studium/curricula/curriculum_as_string.rb +280 -0
- data/lib/studium/curricula/curriculum_module_displayer/constants.rb +33 -0
- data/lib/studium/curricula/curriculum_module_displayer/curriculum_module_displayer.rb +417 -0
- data/lib/studium/curricula/curriculum_module_displayer/initialize.rb +25 -0
- data/lib/studium/curricula/curriculum_module_displayer/menu.rb +45 -0
- data/lib/studium/curricula/curriculum_module_displayer/reset.rb +74 -0
- data/lib/studium/curricula/curriculum_module_displayer/run.rb +20 -0
- data/lib/studium/curricula/curriculum_module_displayer/set_use_this_curriculum.rb +93 -0
- data/lib/studium/curricula/curriculum_module_displayer/show_and_report.rb +190 -0
- data/lib/studium/curricula/determine_curricula/constants.rb +11 -0
- data/lib/studium/curricula/determine_curricula/determine_curricula.rb +36 -0
- data/lib/studium/curricula/determine_curricula/help.rb +39 -0
- data/lib/studium/curricula/determine_curricula/initialize.rb +48 -0
- data/lib/studium/curricula/determine_curricula/menu.rb +151 -0
- data/lib/studium/curricula/determine_curricula/misc.rb +403 -0
- data/lib/studium/curricula/determine_curricula/report.rb +141 -0
- data/lib/studium/curricula/determine_curricula/reset.rb +59 -0
- data/lib/studium/curricula/determine_curricula/run.rb +19 -0
- data/lib/studium/curricula/determine_elective_courses_in_this_curriculum.rb +112 -0
- data/lib/studium/curricula/display_bachelor_curricula.rb +90 -0
- data/lib/studium/curricula/handle_curricula/README.md +9 -0
- data/lib/studium/curricula/handle_curricula/handle_curricula.rb +99 -0
- data/lib/studium/curricula/handle_curricula/misc.rb +798 -0
- data/lib/studium/curricula/mitteilungsbl/303/244tter/mitteilungsbl/303/244tter.rb +323 -0
- data/lib/studium/curricula/modules/display_on_the_commandline.rb +319 -0
- data/lib/studium/curricula/modules/return_n_ects_in_this_module.rb +74 -0
- data/lib/studium/curricula/n_percent_solved_in_this_curriculum.rb +73 -0
- data/lib/studium/curricula/prepare_individual_curriculum.rb +304 -0
- data/lib/studium/curricula/random_curriculum_creator/random_curriculum_creator.rb +164 -0
- data/lib/studium/curricula/show_all_unfinished_courses_of_this_curriculum/show_all_unfinished_courses_of_this_curriculum.rb +116 -0
- data/lib/studium/curricula/show_lectures_of_this_curriculum.rb +114 -0
- data/lib/studium/curricula/show_lectures_of_this_curriculum_id/show_lectures_of_this_curriculum_id.rb +554 -0
- data/lib/studium/curricula/show_solved_percentage_among_the_registered_curricula.rb +87 -0
- data/lib/studium/curricula/sorted_individual_curricula.rb +121 -0
- data/lib/studium/ects/boku_ects_splitter.rb +128 -0
- data/lib/studium/ects/ects_per_university/ects_per_university.rb +179 -0
- data/lib/studium/ects/ects_scanner.rb +141 -0
- data/lib/studium/ects/ects_to_university_parser.rb +142 -0
- data/lib/studium/ects/last_entry_is_curriculum.rb +150 -0
- data/lib/studium/ects/n_ects_in_these_lectures.rb +196 -0
- data/lib/studium/ects/n_ects_points_in_mandatory_presence_courses.rb +47 -0
- data/lib/studium/ects/return_n_ects_from_this_file.rb +59 -0
- data/lib/studium/ects/return_n_ects_from_this_url.rb +197 -0
- data/lib/studium/ects/search_for_n_ects/search_for_n_ects.rb +719 -0
- data/lib/studium/ects/show_completed_ects_in_all_curricula.rb +245 -0
- data/lib/studium/ects/show_passed_credits_per_curriculum.rb +276 -0
- data/lib/studium/ects/simple_total_ects_points.rb +135 -0
- data/lib/studium/ects/solved_ects/constants.rb +19 -0
- data/lib/studium/ects/solved_ects/reset.rb +50 -0
- data/lib/studium/ects/solved_ects/solved_ects.rb +325 -0
- data/lib/studium/ects/solved_ects_per_university/reset.rb +25 -0
- data/lib/studium/ects/solved_ects_per_university/solved_ects_per_university.rb +116 -0
- data/lib/studium/ects/still_missing.rb +129 -0
- data/lib/studium/ects/sum_of_ects.rb +144 -0
- data/lib/studium/encoding/encoding.rb +109 -0
- data/lib/studium/exam_topics/RNAi_siRNA_and_miRNA +100 -0
- data/lib/studium/exam_topics/abfall_als_ressource +86 -0
- data/lib/studium/exam_topics/advanced_biochemistry +937 -0
- data/lib/studium/exam_topics/advanced_biotechnology +234 -0
- data/lib/studium/exam_topics/advanced_cellbiology +251 -0
- data/lib/studium/exam_topics/advanced_chemistry +547 -0
- data/lib/studium/exam_topics/advanced_immunology +225 -0
- data/lib/studium/exam_topics/advanced_microbiology +49 -0
- data/lib/studium/exam_topics/advanced_topics_in_plant_sciences +117 -0
- data/lib/studium/exam_topics/advanced_virology +273 -0
- data/lib/studium/exam_topics/ageing +154 -0
- data/lib/studium/exam_topics/agrar_ecology +67 -0
- data/lib/studium/exam_topics/agrarmarkt +73 -0
- data/lib/studium/exam_topics/agrarphysik +35 -0
- data/lib/studium/exam_topics/alcohols +30 -0
- data/lib/studium/exam_topics/algorithms +104 -0
- data/lib/studium/exam_topics/allergie +76 -0
- data/lib/studium/exam_topics/allgemeine_genetik +1006 -0
- data/lib/studium/exam_topics/allgemeine_mikrobiologie +1012 -0
- data/lib/studium/exam_topics/aminoacids +469 -0
- data/lib/studium/exam_topics/analytische_chemie_1 +134 -0
- data/lib/studium/exam_topics/analytische_chemie_2 +31 -0
- data/lib/studium/exam_topics/anatomie +378 -0
- data/lib/studium/exam_topics/anorganische_chemie +357 -0
- data/lib/studium/exam_topics/anthropologie +239 -0
- data/lib/studium/exam_topics/antibodies_and_antigens +790 -0
- data/lib/studium/exam_topics/apoptosis +35 -0
- data/lib/studium/exam_topics/archaea +112 -0
- data/lib/studium/exam_topics/archaeo_viruses +7 -0
- data/lib/studium/exam_topics/archaeology +5 -0
- data/lib/studium/exam_topics/architecture +8 -0
- data/lib/studium/exam_topics/artificial_intelligence +90 -0
- data/lib/studium/exam_topics/atomemissionsspektrometrie +6 -0
- data/lib/studium/exam_topics/audio +11 -0
- data/lib/studium/exam_topics/bacteriophages +266 -0
- data/lib/studium/exam_topics/basic_biochemistry +1008 -0
- data/lib/studium/exam_topics/basic_biotechnology +1011 -0
- data/lib/studium/exam_topics/basic_chemistry +1007 -0
- data/lib/studium/exam_topics/basic_virology +1008 -0
- data/lib/studium/exam_topics/bauwesen +6 -0
- data/lib/studium/exam_topics/betriebssysteme +128 -0
- data/lib/studium/exam_topics/betriebswirtschaftslehre +29 -0
- data/lib/studium/exam_topics/bioanalytik_und_biosensoren +451 -0
- data/lib/studium/exam_topics/biochips +80 -0
- data/lib/studium/exam_topics/bioelektrochemie +57 -0
- data/lib/studium/exam_topics/biofilms +58 -0
- data/lib/studium/exam_topics/bioinformatics +523 -0
- data/lib/studium/exam_topics/biological_therapeutics +156 -0
- data/lib/studium/exam_topics/biologie +152 -0
- data/lib/studium/exam_topics/biomarkers +137 -0
- data/lib/studium/exam_topics/biomaterials +90 -0
- data/lib/studium/exam_topics/biomedical_studies +16 -0
- data/lib/studium/exam_topics/biomembranes +6 -0
- data/lib/studium/exam_topics/bionik +65 -0
- data/lib/studium/exam_topics/biophysik +34 -0
- data/lib/studium/exam_topics/biopolymers +10 -0
- data/lib/studium/exam_topics/bioprozesstechnik +149 -0
- data/lib/studium/exam_topics/bioressourcenmanagement +78 -0
- data/lib/studium/exam_topics/birds +5 -0
- data/lib/studium/exam_topics/bodenkunde +384 -0
- data/lib/studium/exam_topics/bodenmikrobiologie +40 -0
- data/lib/studium/exam_topics/cancerbiology +488 -0
- data/lib/studium/exam_topics/cell_cultures +229 -0
- data/lib/studium/exam_topics/cellbiology +1011 -0
- data/lib/studium/exam_topics/cellular_transport_and_protein_secretion +27 -0
- data/lib/studium/exam_topics/cellular_vesicles +11 -0
- data/lib/studium/exam_topics/cellulose +6 -0
- data/lib/studium/exam_topics/chemische_technologie_anorganischer_stoffe +210 -0
- data/lib/studium/exam_topics/chemische_technologie_organischer_stoffe +25 -0
- data/lib/studium/exam_topics/chemisches_labor +60 -0
- data/lib/studium/exam_topics/chemokines_and_cytokines +45 -0
- data/lib/studium/exam_topics/chemotaxis_quorum_sensing_and_motility_in_prokaryotes +116 -0
- data/lib/studium/exam_topics/citric_acid_cycle +84 -0
- data/lib/studium/exam_topics/clinical_microbiology +520 -0
- data/lib/studium/exam_topics/computer_science +309 -0
- data/lib/studium/exam_topics/computer_vision_and_computer_graphics +15 -0
- data/lib/studium/exam_topics/crispr +51 -0
- data/lib/studium/exam_topics/cyanobacteria +45 -0
- data/lib/studium/exam_topics/cytogenetics_and_chromosome_biology +598 -0
- data/lib/studium/exam_topics/databases_and_sql +126 -0
- data/lib/studium/exam_topics/dna_mutation_and_dna_repair +186 -0
- data/lib/studium/exam_topics/dna_replication +80 -0
- data/lib/studium/exam_topics/ecogenetics +26 -0
- data/lib/studium/exam_topics/ecological_agriculture +12 -0
- data/lib/studium/exam_topics/ecology +332 -0
- data/lib/studium/exam_topics/economy +226 -0
- data/lib/studium/exam_topics/electron_microscopy +7 -0
- data/lib/studium/exam_topics/elektronenmikroskopie +356 -0
- data/lib/studium/exam_topics/elektrophorese +132 -0
- data/lib/studium/exam_topics/elektrotechnik_und_elektrizit/303/244t +42 -0
- data/lib/studium/exam_topics/elisa +55 -0
- data/lib/studium/exam_topics/embryologie_und_entwicklung +657 -0
- data/lib/studium/exam_topics/endospores_and_spores +104 -0
- data/lib/studium/exam_topics/enzymes_and_cofactors +395 -0
- data/lib/studium/exam_topics/epigenetik +188 -0
- data/lib/studium/exam_topics/erste_hilfe +414 -0
- data/lib/studium/exam_topics/ethik +143 -0
- data/lib/studium/exam_topics/evolution_and_evolutionary_genetics +372 -0
- data/lib/studium/exam_topics/excel +7 -0
- data/lib/studium/exam_topics/fish +19 -0
- data/lib/studium/exam_topics/fluorescence_microscopy +10 -0
- data/lib/studium/exam_topics/food_microbiology_and_food_biotechnology +92 -0
- data/lib/studium/exam_topics/forensik +65 -0
- data/lib/studium/exam_topics/forstwirtschaft +53 -0
- data/lib/studium/exam_topics/fortgeschrittene_genetik +692 -0
- data/lib/studium/exam_topics/fortgeschrittene_gentechnik +221 -0
- data/lib/studium/exam_topics/fortgeschrittene_physik +6 -0
- data/lib/studium/exam_topics/fungi +119 -0
- data/lib/studium/exam_topics/genetische_krankheiten +209 -0
- data/lib/studium/exam_topics/genexpression +1008 -0
- data/lib/studium/exam_topics/genomics_and_metagenomics +290 -0
- data/lib/studium/exam_topics/gentechnik_und_praktische_biochemie +961 -0
- data/lib/studium/exam_topics/geochemistry +67 -0
- data/lib/studium/exam_topics/geography +9 -0
- data/lib/studium/exam_topics/geologie_und_mineralogie +624 -0
- data/lib/studium/exam_topics/geometrie +56 -0
- data/lib/studium/exam_topics/geschichte +95 -0
- data/lib/studium/exam_topics/gluconeogenesis +72 -0
- data/lib/studium/exam_topics/glycogen +45 -0
- data/lib/studium/exam_topics/glycolysis +118 -0
- data/lib/studium/exam_topics/glykomik +131 -0
- data/lib/studium/exam_topics/glyoxylatzyklus +31 -0
- data/lib/studium/exam_topics/grassland_cultivation +32 -0
- data/lib/studium/exam_topics/hormone +152 -0
- data/lib/studium/exam_topics/html +8 -0
- data/lib/studium/exam_topics/human_ecology +8 -0
- data/lib/studium/exam_topics/hygiene +224 -0
- data/lib/studium/exam_topics/imaging_and_microscopy +270 -0
- data/lib/studium/exam_topics/immunanalytik +94 -0
- data/lib/studium/exam_topics/immunologie +1011 -0
- data/lib/studium/exam_topics/informatik +117 -0
- data/lib/studium/exam_topics/innate_immunity +52 -0
- data/lib/studium/exam_topics/insekten +66 -0
- data/lib/studium/exam_topics/insulin_and_diabetes +57 -0
- data/lib/studium/exam_topics/java +624 -0
- data/lib/studium/exam_topics/javascript +29 -0
- data/lib/studium/exam_topics/klima +6 -0
- data/lib/studium/exam_topics/kryptographie +10 -0
- data/lib/studium/exam_topics/landtechnik +26 -0
- data/lib/studium/exam_topics/lebensmittel_und_getr/303/244nke +224 -0
- data/lib/studium/exam_topics/lebensmitteltechnologie +16 -0
- data/lib/studium/exam_topics/light_microscopy +19 -0
- data/lib/studium/exam_topics/linux_and_unix +36 -0
- data/lib/studium/exam_topics/lipids +145 -0
- data/lib/studium/exam_topics/macroeconomics +39 -0
- data/lib/studium/exam_topics/marketing +53 -0
- data/lib/studium/exam_topics/mathematics +311 -0
- data/lib/studium/exam_topics/medizin_und_biomedizinische_technik +254 -0
- data/lib/studium/exam_topics/medizinische_chemie_und_pharmazie +441 -0
- data/lib/studium/exam_topics/messtechnik_und_regeltechnik +104 -0
- data/lib/studium/exam_topics/metabolismus +482 -0
- data/lib/studium/exam_topics/meteorologie_und_atmosph/303/244re +120 -0
- data/lib/studium/exam_topics/microbial_ecology +37 -0
- data/lib/studium/exam_topics/microcontrollers +11 -0
- data/lib/studium/exam_topics/mikrobielle_lebensgemeinschaften +58 -0
- data/lib/studium/exam_topics/mikrobielle_physiologie +313 -0
- data/lib/studium/exam_topics/mitochondria +57 -0
- data/lib/studium/exam_topics/mixed +287 -0
- data/lib/studium/exam_topics/molecular_biology_of_plants +281 -0
- data/lib/studium/exam_topics/molekulare_medizin +133 -0
- data/lib/studium/exam_topics/nanotechnologie +456 -0
- data/lib/studium/exam_topics/nature_conservation_and_biodiversity +247 -0
- data/lib/studium/exam_topics/naturstoffe +9 -0
- data/lib/studium/exam_topics/netzwerke +63 -0
- data/lib/studium/exam_topics/neuroanatomie +25 -0
- data/lib/studium/exam_topics/neurobiology +356 -0
- data/lib/studium/exam_topics/nucleotide_sequencing +41 -0
- data/lib/studium/exam_topics/nutztierethologie +11 -0
- data/lib/studium/exam_topics/object_oriented_modeling +15 -0
- data/lib/studium/exam_topics/obstbau +249 -0
- data/lib/studium/exam_topics/organische_chemie +1007 -0
- data/lib/studium/exam_topics/organische_chemie_2 +137 -0
- data/lib/studium/exam_topics/paleobiology +39 -0
- data/lib/studium/exam_topics/parasitic_diseases_and_molecular_infection_biology +336 -0
- data/lib/studium/exam_topics/patent_law +55 -0
- data/lib/studium/exam_topics/pathologie +761 -0
- data/lib/studium/exam_topics/pcr +155 -0
- data/lib/studium/exam_topics/pentosephosphatweg +61 -0
- data/lib/studium/exam_topics/peroxisomes_glycosomes_and_lysosomes +66 -0
- data/lib/studium/exam_topics/pflanzenanatomie +262 -0
- data/lib/studium/exam_topics/pflanzenbau +24 -0
- data/lib/studium/exam_topics/pflanzenschutz +35 -0
- data/lib/studium/exam_topics/pflanzenwissenschaften +1009 -0
- data/lib/studium/exam_topics/pharmaceutical_biotechnology +252 -0
- data/lib/studium/exam_topics/physik +449 -1
- data/lib/studium/exam_topics/physikalische_chemie +79 -0
- data/lib/studium/exam_topics/physiology_and_histology +592 -0
- data/lib/studium/exam_topics/phytochemie +33 -0
- data/lib/studium/exam_topics/plant_biotechnology +132 -0
- data/lib/studium/exam_topics/plant_breeding +64 -0
- data/lib/studium/exam_topics/plant_development +50 -0
- data/lib/studium/exam_topics/populationsgenetik +143 -0
- data/lib/studium/exam_topics/posttranslationale_modifikation_von_proteinen +198 -0
- data/lib/studium/exam_topics/programming +41 -0
- data/lib/studium/exam_topics/projektmanagement +226 -0
- data/lib/studium/exam_topics/prokaryote_genetics +587 -0
- data/lib/studium/exam_topics/protein_engineering +35 -0
- data/lib/studium/exam_topics/proteolyse +39 -0
- data/lib/studium/exam_topics/proteomik +42 -0
- data/lib/studium/exam_topics/protozoans +24 -0
- data/lib/studium/exam_topics/prozesstechnik +95 -0
- data/lib/studium/exam_topics/psychologie +21 -0
- data/lib/studium/exam_topics/python +391 -0
- data/lib/studium/exam_topics/quality_management +266 -0
- data/lib/studium/exam_topics/rechtsgrundlagen +126 -0
- data/lib/studium/exam_topics/research_topics_in_immunobiology +42 -0
- data/lib/studium/exam_topics/rna_and_dna +535 -0
- data/lib/studium/exam_topics/rna_seq +13 -0
- data/lib/studium/exam_topics/robotics +12 -0
- data/lib/studium/exam_topics/ruby +240 -0
- data/lib/studium/exam_topics/ruby_on_rails +63 -0
- data/lib/studium/exam_topics/scientific_writing_and_publishing +38 -0
- data/lib/studium/exam_topics/semisynthese_von_proteinen_und_nukleotiden +120 -0
- data/lib/studium/exam_topics/sexualbiologie +327 -0
- data/lib/studium/exam_topics/signal_transduction_and_laser_systems +215 -0
- data/lib/studium/exam_topics/sozialbiologie +17 -0
- data/lib/studium/exam_topics/soziologie +5 -0
- data/lib/studium/exam_topics/splicing_exons_and_introns +67 -0
- data/lib/studium/exam_topics/sport_und_sportverletzungen +6 -0
- data/lib/studium/exam_topics/statistik +306 -0
- data/lib/studium/exam_topics/stemcells +182 -0
- data/lib/studium/exam_topics/stickstofffixierung +91 -0
- data/lib/studium/exam_topics/structural_bioinformatics +54 -0
- data/lib/studium/exam_topics/strukturbiologie +445 -0
- data/lib/studium/exam_topics/system_biology_and_synthetic_biology +108 -0
- data/lib/studium/exam_topics/systematische_zoologie +446 -0
- data/lib/studium/exam_topics/technical_ecology +144 -0
- data/lib/studium/exam_topics/technik +5 -0
- data/lib/studium/exam_topics/technische_chemie +208 -0
- data/lib/studium/exam_topics/technische_grundlagen_der_informatik +43 -0
- data/lib/studium/exam_topics/technische_mikrobiologie +393 -0
- data/lib/studium/exam_topics/technisches_zeichnen +5 -0
- data/lib/studium/exam_topics/the_bacterial_cell_wall +98 -0
- data/lib/studium/exam_topics/the_c_plus_plus_programming_language +531 -0
- data/lib/studium/exam_topics/the_c_programming_language +133 -0
- data/lib/studium/exam_topics/the_cellcycle +102 -0
- data/lib/studium/exam_topics/the_european_union +121 -0
- data/lib/studium/exam_topics/the_interferon_system +40 -0
- data/lib/studium/exam_topics/the_microbiome +164 -0
- data/lib/studium/exam_topics/the_universe +32 -0
- data/lib/studium/exam_topics/theoretische_chemie +5 -0
- data/lib/studium/exam_topics/theoretische_informatik +161 -0
- data/lib/studium/exam_topics/thermodynamics +21 -0
- data/lib/studium/exam_topics/tierzucht +139 -0
- data/lib/studium/exam_topics/toxikologie +508 -0
- data/lib/studium/exam_topics/transcription +188 -0
- data/lib/studium/exam_topics/translation_ribosomes_and_translational_control +155 -0
- data/lib/studium/exam_topics/umweltbiotechnologie +64 -0
- data/lib/studium/exam_topics/umweltchemie +233 -0
- data/lib/studium/exam_topics/urbanism_and_traffic +19 -0
- data/lib/studium/exam_topics/urea_cycle +56 -0
- data/lib/studium/exam_topics/vaccines_and_vaccination +253 -0
- data/lib/studium/exam_topics/vectors_and_gene_therapy +247 -0
- data/lib/studium/exam_topics/verfahrenstechnik +37 -0
- data/lib/studium/exam_topics/verhaltensbiologie +79 -0
- data/lib/studium/exam_topics/veterinary_medicine +10 -0
- data/lib/studium/exam_topics/vitamine +32 -0
- data/lib/studium/exam_topics/wasserkunde +144 -0
- data/lib/studium/exam_topics/weinbau +86 -0
- data/lib/studium/exam_topics/wissenschaft +20 -0
- data/lib/studium/exam_topics/yeast +104 -0
- data/lib/studium/exam_topics/zoologie +338 -0
- data/lib/studium/exams/afterburn/afterburn.rb +304 -0
- data/lib/studium/exams/ask_exam_from_the_upcoming_exams_pool.rb +150 -0
- data/lib/studium/exams/ask_exam_topic_question.rb +112 -0
- data/lib/studium/exams/ask_question_from_alias.rb +141 -0
- data/lib/studium/exams/ask_question_from_any_of_the_still_missing_lectures.rb +130 -0
- data/lib/studium/exams/ask_question_from_grouped_themes.rb +141 -0
- data/lib/studium/exams/ask_question_from_last_topic.rb +91 -0
- data/lib/studium/exams/ask_random_question.rb +195 -0
- data/lib/studium/exams/autoinclude.rb +7 -0
- data/lib/studium/exams/average_grade/average_grade.rb +404 -0
- data/lib/studium/exams/csv/create_csv_passed_exams_file.rb +217 -0
- data/lib/studium/exams/cycle.rb +291 -0
- data/lib/studium/exams/dataset/dataset.rb +126 -0
- data/lib/studium/exams/designate_ten_random_exam_topics/designate_ten_random_exam_topics.rb +88 -0
- data/lib/studium/exams/exam/exam.rb +130 -0
- data/lib/studium/exams/exam_bubble/exam_bubble.rb +444 -0
- data/lib/studium/exams/exam_bubble/menu_for_the_main_loop.rb +111 -0
- data/lib/studium/exams/exam_question/README.md +3 -0
- data/lib/studium/exams/exam_question/exam_question.rb +434 -0
- data/lib/studium/exams/exam_registration_at/constants.rb +49 -0
- data/lib/studium/exams/exam_registration_at/exam_registration_at.rb +242 -0
- data/lib/studium/exams/exam_registration_at/help.rb +46 -0
- data/lib/studium/exams/exam_registration_at/menu.rb +81 -0
- data/lib/studium/exams/exam_registration_at/report_and_show.rb +133 -0
- data/lib/studium/exams/exam_registration_at/reset.rb +54 -0
- data/lib/studium/exams/exam_statistics_from_this_file/exam_statistics_from_this_file.rb +119 -0
- data/lib/studium/exams/exam_topics.rb +194 -0
- data/lib/studium/exams/exams.rb +20 -0
- data/lib/studium/exams/exams_per_month/exams_per_month.rb +2442 -0
- data/lib/studium/exams/exams_this_week.rb +182 -0
- data/lib/studium/exams/fix_exam_dates.rb +121 -0
- data/lib/studium/exams/frozen.rb +36 -0
- data/lib/studium/exams/last_exams/last_exams.rb +479 -0
- data/lib/studium/exams/lectures_without_exam_entry.rb +137 -0
- data/lib/studium/exams/mandatory_continuous_assessment/mandatory_continuous_assessment.rb +1358 -0
- data/lib/studium/exams/move_all_unsolved_exam_questions_to_the_top_of_the_file.rb +173 -0
- data/lib/studium/exams/move_the_last_exam_question_to_the_top_of_the_file/move_the_last_exam_question_to_the_top_of_the_file.rb +111 -0
- data/lib/studium/exams/n_exams_in_these_topics.rb +477 -0
- data/lib/studium/exams/next_exam.rb +106 -0
- data/lib/studium/exams/next_exams.rb +378 -0
- data/lib/studium/exams/not_completed/README.md +5 -0
- data/lib/studium/exams/not_completed/not_completed.rb +143 -0
- data/lib/studium/exams/open_exam_associated_url/open_exam_associated_url.rb +154 -0
- data/lib/studium/exams/open_last_exam_question_asked_file/constants.rb +15 -0
- data/lib/studium/exams/open_last_exam_question_asked_file/initialize.rb +29 -0
- data/lib/studium/exams/open_last_exam_question_asked_file/open_last_exam_question_asked_file.rb +110 -0
- data/lib/studium/exams/push_solved_questions_on_top.rb +180 -0
- data/lib/studium/exams/question_answer/question_answer.rb +2936 -0
- data/lib/studium/exams/questions_solved_from_day_to_day/questions_solved_from_day_to_day.rb +379 -0
- data/lib/studium/exams/remote_ftp_url.rb +52 -0
- data/lib/studium/exams/repeat_last_question.rb +78 -0
- data/lib/studium/exams/report_total_amount_of_questions_and_answers_for.rb +116 -0
- data/lib/studium/exams/show_all_passed_exams_of_this_university.rb +252 -0
- data/lib/studium/exams/show_backlog_of_exams/show_backlog_of_exams.rb +114 -0
- data/lib/studium/exams/show_exams_for/show_exams_for.rb +172 -0
- data/lib/studium/exams/show_themes/constants.rb +28 -0
- data/lib/studium/exams/show_themes/menu.rb +61 -0
- data/lib/studium/exams/show_themes/misc.rb +538 -0
- data/lib/studium/exams/show_themes/reset.rb +62 -0
- data/lib/studium/exams/show_themes/show_themes.rb +27 -0
- data/lib/studium/exams/show_upcoming_exams/show_upcoming_exams.rb +1537 -0
- data/lib/studium/exams/solve_all_questions_from_this_topic.rb +114 -0
- data/lib/studium/exams/solved/solved.rb +434 -0
- data/lib/studium/exams/timetable/constants.rb +142 -0
- data/lib/studium/exams/timetable/timetable.rb +448 -0
- data/lib/studium/exams/unsolve_all_questions_from_this_topic.rb +163 -0
- data/lib/studium/exams/upcoming_exams/upcoming_exams.rb +555 -0
- data/lib/studium/exams/upcoming_exams_at_the_boku/constants.rb +23 -0
- data/lib/studium/exams/upcoming_exams_at_the_boku/html.rb +64 -0
- data/lib/studium/exams/upcoming_exams_at_the_boku/upcoming_exams_at_the_boku.rb +194 -0
- data/lib/studium/exams/upcoming_exams_dataset.rb +247 -0
- data/lib/studium/exams/upcoming_registered_exams/upcoming_registered_exams.rb +257 -0
- data/lib/studium/exams/upload_exam_topics.rb +360 -0
- data/lib/studium/graphviz/README.md +4 -0
- data/lib/studium/graphviz/bachelor_vector_based_strategies.dot +160 -0
- data/lib/studium/graphviz/master_vector_based_strategies.dot +46 -0
- data/lib/studium/gui/gtk3/control_panel/control_panel.rb +40 -0
- data/lib/studium/gui/gtk3/lecture_information/lecture_information.rb +191 -0
- data/lib/studium/gui/java/exam_question/ExamQuestion$1.class +0 -0
- data/lib/studium/gui/java/exam_question/ExamQuestion.class +0 -0
- data/lib/studium/gui/java/exam_question/ExamQuestion.java +215 -0
- data/lib/studium/gui/javafx/exam_question_widget/exam_question_widget.rb +58 -0
- data/lib/studium/gui/jruby/exam_trainer/exam_trainer.rb +637 -0
- data/lib/studium/gui/jruby/show_upcoming_exams/show_upcoming_exams.rb +85 -0
- data/lib/studium/gui/libui/ask_exam_question/ask_exam_question.rb +347 -0
- data/lib/studium/gui/shared_code/control_panel/control_panel_module.rb +305 -0
- data/lib/studium/gui/shared_code/exam_trainer/exam_trainer_widget_module.rb +0 -0
- data/lib/studium/gui/shared_code/information_about_a_lecture/information_about_a_lecture_module.rb +0 -0
- data/lib/studium/gui/shared_code/show_upcoming_exams/show_upcoming_exams_module.rb +129 -0
- data/lib/studium/gui/universal_widgets/curriculum_viewer/curriculum_viewer.rb +549 -0
- data/lib/studium/gui/universal_widgets/ects_per_university/ects_per_university.rb +302 -0
- data/lib/studium/gui/universal_widgets/exam_trainer/exam_trainer.config +6 -0
- data/lib/studium/gui/universal_widgets/exam_trainer/exam_trainer.rb +3266 -0
- data/lib/studium/gui/universal_widgets/exam_trainer/manifest.yml +12 -0
- data/lib/studium/gui/universal_widgets/expand_time_range/expand_time_range.rb +309 -0
- data/lib/studium/gui/universal_widgets/information_about_a_lecture/information_about_a_lecture.rb +242 -0
- data/lib/studium/gui/universal_widgets/show_upcoming_exams/show_upcoming_exams.rb +252 -0
- data/lib/studium/images/libui_ask_exam_question.png +0 -0
- data/lib/studium/images/outdated.png +0 -0
- data/lib/studium/images/small_logos/DNA.png +0 -0
- data/lib/studium/images/small_logos/README.md +2 -0
- data/lib/studium/images/small_logos/solved.png +0 -0
- data/lib/studium/images/studies_favicon.png +0 -0
- data/lib/studium/java/README.md +5 -0
- data/lib/studium/java/studium/AskExamQuestion.java +461 -0
- data/lib/studium/java/studium/Base.java +123 -0
- data/lib/studium/java/studium/Constants.java +122 -0
- data/lib/studium/java/studium/EnsureThatTheLogDirectoryExists.java +57 -0
- data/lib/studium/java/studium/Mkdir.java +13 -0
- data/lib/studium/java/studium/OpenLastExamQuestionurlLinkViaTheBrowser.java +90 -0
- data/lib/studium/java/studium/ReturnNQuestionsSolvedInTotal.java +69 -0
- data/lib/studium/java/studium/Solved.java +112 -0
- data/lib/studium/java/studium/Test.java +60 -0
- data/lib/studium/java/studium/studium/AskExamQuestion.class +0 -0
- data/lib/studium/java/studium/studium/Base.class +0 -0
- data/lib/studium/java/studium/studium/Constants.class +0 -0
- data/lib/studium/java/studium/studium/EnsureThatTheLogDirectoryExists.class +0 -0
- data/lib/studium/java/studium/studium/Mkdir.class +0 -0
- data/lib/studium/java/studium/studium/OpenLastExamQuestionurlLinkViaTheBrowser.class +0 -0
- data/lib/studium/java/studium/studium/ReturnNQuestionsSolvedInTotal.class +0 -0
- data/lib/studium/java/studium/studium/Solved.class +0 -0
- data/lib/studium/java/studium/studium/Test.class +0 -0
- data/lib/studium/jobs/jobs.rb +80 -0
- data/lib/studium/logging/README.md +2 -0
- data/lib/studium/logging/ensure_that_the_log_directory_exists.rb +58 -0
- data/lib/studium/logging/html_log_directory.rb +42 -0
- data/lib/studium/logging/log_directory.rb +112 -0
- data/lib/studium/logging/store_last_question_asked_into_file.rb +138 -0
- data/lib/studium/parsers/README.md +2 -0
- data/lib/studium/parsers/custom_exam_results_parser.rb +209 -0
- data/lib/studium/parsers/parse_remote_lecture.rb +331 -0
- data/lib/studium/project/project.rb +88 -0
- data/lib/studium/requires/common_popular_requires.rb +37 -0
- data/lib/studium/requires/commonly_used_requires.rb +14 -0
- data/lib/studium/requires/require_class_exams_solved.rb +7 -0
- data/lib/studium/requires/require_ects_scripts.rb +27 -0
- data/lib/studium/requires/require_encoding.rb +7 -0
- data/lib/studium/requires/require_the_check_and_sanitize_files.rb +31 -0
- data/lib/studium/requires/require_the_curricula_files.rb +28 -0
- data/lib/studium/requires/require_the_exam_question_class.rb +7 -0
- data/lib/studium/requires/require_the_exams_files.rb +46 -0
- data/lib/studium/requires/require_the_logging_files.rb +23 -0
- data/lib/studium/requires/require_the_parsers.rb +28 -0
- data/lib/studium/requires/require_the_studium_constants.rb +7 -0
- data/lib/studium/requires/require_the_studium_project.rb +72 -0
- data/lib/studium/requires/require_the_toplevel_methods.rb +27 -0
- data/lib/studium/requires/require_the_utility_scripts.rb +34 -0
- data/lib/studium/requires/require_upcoming_exams.rb +7 -0
- data/lib/studium/requires/require_yaml.rb +7 -0
- data/lib/studium/requires/return_remote_homepage_of_this_lecture.rb +7 -0
- data/lib/studium/requires/with_GUI.rb +13 -0
- data/lib/studium/requires/www_mode.rb +17 -0
- data/lib/studium/statistics/README.md +4 -0
- data/lib/studium/statistics/best_exam_months.rb +92 -0
- data/lib/studium/statistics/curriculum_comparer/curriculum_comparer.rb +423 -0
- data/lib/studium/statistics/determine_exam_statistics_from_this_file.rb +142 -0
- data/lib/studium/statistics/exam_topics_that_are_about_to_be_completed.rb +117 -0
- data/lib/studium/statistics/max_stats.rb +169 -0
- data/lib/studium/statistics/new_questions_per_year.rb +147 -0
- data/lib/studium/statistics/report_how_many_ects_points_per_curriculum_were_completed.rb +167 -0
- data/lib/studium/statistics/report_how_many_exam_questions_were_answered.rb +473 -0
- data/lib/studium/statistics/show_exam_statistics.rb +75 -0
- data/lib/studium/statistics/show_which_courses_are_in_a_bachelor_or_master_curriculum_respectively.rb +104 -0
- data/lib/studium/statistics/top_stats.rb +126 -0
- data/lib/studium/toplevel_methods/e_and_esystem.rb +34 -0
- data/lib/studium/toplevel_methods/find_exam_topic_and_exam_title.rb +3986 -0
- data/lib/studium/toplevel_methods/install_the_project_on_the_given_hostsystem.rb +31 -0
- data/lib/studium/toplevel_methods/return_remote_homepage_of_this_lecture.rb +11611 -0
- data/lib/studium/toplevel_methods/return_remote_moodle_link_of_this_lecture.rb +2405 -0
- data/lib/studium/toplevel_methods/roebe.rb +16 -0
- data/lib/studium/toplevel_methods/runmode.rb +45 -0
- data/lib/studium/toplevel_methods/toplevel_methods.rb +7295 -0
- data/lib/studium/universities_in_austria/README.md +2 -0
- data/lib/studium/universities_in_austria/boku/README.md +4 -0
- data/lib/studium/universities_in_austria/boku/boku_/303/266ffnungszeiten.rb +28 -0
- data/lib/studium/universities_in_austria/boku/show_three_pillars_of_these_lectures.rb +110 -0
- data/lib/studium/universities_in_austria/boku/three_pillars.rb +237 -0
- data/lib/studium/universities_in_austria/tu_vienna/README.md +6 -0
- data/lib/studium/universities_in_austria/tu_vienna/tu_ferien.rb +42 -0
- data/lib/studium/universities_in_austria/tu_vienna/tu_/303/266ffnungszeiten.rb +34 -0
- data/lib/studium/university_course/university_course.rb +409 -0
- data/lib/studium/utility_scripts/attribute_lectures_to_university/attribute_lectures_to_university.rb +375 -0
- data/lib/studium/utility_scripts/audio_stats.rb +171 -0
- data/lib/studium/utility_scripts/auto_stud/auto_stud.rb +252 -0
- data/lib/studium/utility_scripts/auto_stud/constants.rb +18 -0
- data/lib/studium/utility_scripts/auto_stud/initialize.rb +23 -0
- data/lib/studium/utility_scripts/auto_stud/misc.rb +18 -0
- data/lib/studium/utility_scripts/autogeneration/autogeneration.rb +158 -0
- data/lib/studium/utility_scripts/autopurge_this_lecture_date.rb +100 -0
- data/lib/studium/utility_scripts/average_grade_of_this_curriculum.rb +153 -0
- data/lib/studium/utility_scripts/blocked_courses.rb +146 -0
- data/lib/studium/utility_scripts/calendar/README.md +2 -0
- data/lib/studium/utility_scripts/calendar/calendar.rb +251 -0
- data/lib/studium/utility_scripts/calendar/misc.rb +35 -0
- data/lib/studium/utility_scripts/check_description_of_these_lectures.rb +221 -0
- data/lib/studium/utility_scripts/course_registrations/course_registrations.rb +98 -0
- data/lib/studium/utility_scripts/courses/courses.rb +177 -0
- data/lib/studium/utility_scripts/create/README.md +2 -0
- data/lib/studium/utility_scripts/create/webpage_of_university.rb +129 -0
- data/lib/studium/utility_scripts/create/webpage_of_university_BOKU.rb +61 -0
- data/lib/studium/utility_scripts/create/webpage_of_university_TU.rb +60 -0
- data/lib/studium/utility_scripts/create/webpage_of_university_UniWien.rb +60 -0
- data/lib/studium/utility_scripts/create_database/create_database.rb +126 -0
- data/lib/studium/utility_scripts/current_lectures_belonging_to_both_bachelor_and_master_curriculum.rb +113 -0
- data/lib/studium/utility_scripts/currently_participating_in_these_lectures/currently_participating_in_these_lectures.rb +104 -0
- data/lib/studium/utility_scripts/display_lecture_url/display_lecture_url.rb +176 -0
- data/lib/studium/utility_scripts/expand_time_range/expand_time_range.rb +521 -0
- data/lib/studium/utility_scripts/finished_exams_at_this_university/finished_exams_at_this_university.rb +171 -0
- data/lib/studium/utility_scripts/foreign_language_percentage/constants.rb +23 -0
- data/lib/studium/utility_scripts/foreign_language_percentage/foreign_language_percentage.rb +149 -0
- data/lib/studium/utility_scripts/foreign_language_percentage/help.rb +31 -0
- data/lib/studium/utility_scripts/foreign_language_percentage/initialize.rb +25 -0
- data/lib/studium/utility_scripts/foreign_language_percentage/menu.rb +158 -0
- data/lib/studium/utility_scripts/foreign_language_percentage/report.rb +62 -0
- data/lib/studium/utility_scripts/foreign_language_percentage/reset.rb +50 -0
- data/lib/studium/utility_scripts/foreign_language_percentage/run.rb +19 -0
- data/lib/studium/utility_scripts/generate_spreadsheet/generate_spreadsheet.rb +353 -0
- data/lib/studium/utility_scripts/generate_spreadsheet/misc.rb +144 -0
- data/lib/studium/utility_scripts/holidays/holidays.rb +154 -0
- data/lib/studium/utility_scripts/homepage_of_these_courses/homepage_of_these_courses.rb +125 -0
- data/lib/studium/utility_scripts/lectures_attributed_to_universities/lectures_attributed_to_universities.rb +336 -0
- data/lib/studium/utility_scripts/lva_dates_of_the_important_courses.rb +111 -0
- data/lib/studium/utility_scripts/lva_nummer/lva_nummer.rb +427 -0
- data/lib/studium/utility_scripts/mandatory_lectures_in_this_month/mandatory_lectures_in_this_month.rb +316 -0
- data/lib/studium/utility_scripts/moodle/moodle.rb +214 -0
- data/lib/studium/utility_scripts/name_of_this_lva_id/name_of_this_lva_id.rb +110 -0
- data/lib/studium/utility_scripts/new_stud.rb +324 -0
- data/lib/studium/utility_scripts/next_week/next_week.rb +103 -0
- data/lib/studium/utility_scripts/not_yet_registered/not_yet_registered.rb +120 -0
- data/lib/studium/utility_scripts/open_last_exam_question_url_link_via_the_browser.rb +76 -0
- data/lib/studium/utility_scripts/passed_ects_per_year/passed_ects_per_year.rb +313 -0
- data/lib/studium/utility_scripts/passed_pr/303/274fungsimmanente_courses/passed_pr/303/274fungsimmanente_courses.rb +181 -0
- data/lib/studium/utility_scripts/pdf/README.md +2 -0
- data/lib/studium/utility_scripts/pdf/create_pdf_file_for_this_exam_topic.rb +352 -0
- data/lib/studium/utility_scripts/pdf/hexapdf_support.rb +50 -0
- data/lib/studium/utility_scripts/preparatory_meetings/preparatory_meetings.rb +317 -0
- data/lib/studium/utility_scripts/priority/priority.rb +164 -0
- data/lib/studium/utility_scripts/priority_points/priority_points.rb +261 -0
- data/lib/studium/utility_scripts/publish_my_exams/publish_my_exams.rb +174 -0
- data/lib/studium/utility_scripts/regexes/README.md +1 -0
- data/lib/studium/utility_scripts/regexes/generate_regex.rb +314 -0
- data/lib/studium/utility_scripts/regexes/generate_regexes_for_the_available_moodle_links.rb +55 -0
- data/lib/studium/utility_scripts/regexes/generate_regexes_for_the_registered_lectures.rb +48 -0
- data/lib/studium/utility_scripts/report_outdated_timetable_entries/report_outdated_timetable_entries.rb +142 -0
- data/lib/studium/utility_scripts/report_whether_this_lecture_is_registered_in_the_file_lecture_information/report_whether_this_lecture_is_registered_in_the_file_lecture_information.rb +129 -0
- data/lib/studium/utility_scripts/resolve_practical_courses_date_conflicts/individual_resolve_practical_courses_date_conflicts.rb +254 -0
- data/lib/studium/utility_scripts/resolve_practical_courses_date_conflicts/resolve_practical_courses_date_conflicts.rb +265 -0
- data/lib/studium/utility_scripts/scrape_remote_university_url.rb +138 -0
- data/lib/studium/utility_scripts/semester_schedule_creator/semester_container.rb +144 -0
- data/lib/studium/utility_scripts/semester_schedule_creator/semester_schedule_creator.rb +373 -0
- data/lib/studium/utility_scripts/semesterplaner/semesterplaner.rb +311 -0
- data/lib/studium/utility_scripts/set_aliases_based_on_this_file.rb +96 -0
- data/lib/studium/utility_scripts/show_all_passed_master_lectures/show_all_passed_master_lectures.rb +126 -0
- data/lib/studium/utility_scripts/show_conflicting_lva_lectures/show_conflicting_lva_lectures.rb +1385 -0
- data/lib/studium/utility_scripts/show_descriptions_of_lectures_belonging_to_this_module/constants.rb +23 -0
- data/lib/studium/utility_scripts/show_descriptions_of_lectures_belonging_to_this_module/menu.rb +63 -0
- data/lib/studium/utility_scripts/show_descriptions_of_lectures_belonging_to_this_module/reset.rb +33 -0
- data/lib/studium/utility_scripts/show_descriptions_of_lectures_belonging_to_this_module/run.rb +50 -0
- data/lib/studium/utility_scripts/show_descriptions_of_lectures_belonging_to_this_module/show_descriptions_of_lectures_belonging_to_this_module.rb +145 -0
- data/lib/studium/utility_scripts/show_lecturers/show_lecturers.rb +147 -0
- data/lib/studium/utility_scripts/show_lectures/show_lectures.rb +906 -0
- data/lib/studium/utility_scripts/show_lectures_fitting_to_this_language/show_lectures_fitting_to_this_language.rb +121 -0
- data/lib/studium/utility_scripts/show_lectures_fitting_to_this_theme/show_lectures_fitting_to_this_theme.rb +105 -0
- data/lib/studium/utility_scripts/show_lectures_on_the_commandline/show_lectures_on_the_commandline.rb +3160 -0
- data/lib/studium/utility_scripts/show_lectures_on_this_day/show_lectures_on_this_day.rb +150 -0
- data/lib/studium/utility_scripts/show_lva_dates_of_this_lecture/show_lva_dates_of_this_lecture.rb +182 -0
- data/lib/studium/utility_scripts/show_mixed_bachelor_master_courses/show_mixed_bachelor_master_courses.rb +92 -0
- data/lib/studium/utility_scripts/show_outdated_lva_dates/show_outdated_lva_dates.rb +214 -0
- data/lib/studium/utility_scripts/show_passed_exams_having_this_grade/show_passed_exams_having_this_grade.rb +91 -0
- data/lib/studium/utility_scripts/show_solved_english_lectures/show_solved_english_lectures.rb +139 -0
- data/lib/studium/utility_scripts/steop/README.md +4 -0
- data/lib/studium/utility_scripts/steop/show_all_steop_lectures.rb +93 -0
- data/lib/studium/utility_scripts/steop/steop_lectures_in_this_curriculum.rb +284 -0
- data/lib/studium/utility_scripts/steop/steop_lva_dates.rb +119 -0
- data/lib/studium/utility_scripts/studienkennzahl/studienkennzahl.rb +116 -0
- data/lib/studium/utility_scripts/studium_skeleton/studium_skeleton.rb +241 -0
- data/lib/studium/utility_scripts/stundenplan.rb +600 -0
- data/lib/studium/utility_scripts/sync_studium_relevant_entries_one_level_downwards.rb +217 -0
- data/lib/studium/utility_scripts/ufind/ufind.rb +106 -0
- data/lib/studium/utility_scripts/upcoming_mandatory_presence_courses/constants.rb +26 -0
- data/lib/studium/utility_scripts/upcoming_mandatory_presence_courses/run.rb +20 -0
- data/lib/studium/utility_scripts/upcoming_mandatory_presence_courses/upcoming_mandatory_presence_courses.rb +187 -0
- data/lib/studium/utility_scripts/video_lecture_downloader/video_lecture_downloader.rb +107 -0
- data/lib/studium/utility_scripts/week_parser/constants.rb +23 -0
- data/lib/studium/utility_scripts/week_parser/help.rb +32 -0
- data/lib/studium/utility_scripts/week_parser/menu.rb +59 -0
- data/lib/studium/utility_scripts/week_parser/misc.rb +373 -0
- data/lib/studium/utility_scripts/week_parser/reset.rb +65 -0
- data/lib/studium/utility_scripts/week_parser/run.rb +18 -0
- data/lib/studium/utility_scripts/week_parser/show.rb +236 -0
- data/lib/studium/utility_scripts/week_parser/week_parser.rb +49 -0
- data/lib/studium/utility_scripts/weekday_parser.rb +155 -0
- data/lib/studium/utility_scripts/weekly_schedule.rb +198 -0
- data/lib/studium/utility_scripts/wochenplanung/wochenplanung.rb +267 -0
- data/lib/studium/version/version.rb +46 -0
- data/lib/studium/www/exams/exams.cgi +54 -0
- data/lib/studium/www/fast_ask_exam_question/fast_ask_exam_question.cgi +156 -0
- data/lib/studium/www/handle_curricula/handle_curricula.cgi +154 -0
- data/lib/studium/www/next_generation_exam_question_trainer/next_generation_exam_question_trainer.cgi +112 -0
- data/lib/studium/www/next_generation_exam_question_trainer/solved.cgi +26 -0
- data/lib/studium/www/sinatra/app.rb +231 -0
- data/lib/studium/www/sinatra/curriculum_displayer/curriculum_displayer.rb +162 -0
- data/lib/studium/www/sinatra/misc.rb +115 -0
- data/lib/studium/www/statistics/statistics.cgi +82 -0
- data/lib/studium/www/upcoming_exams/upcoming_exams.cgi +36 -0
- data/lib/studium/yaml/ad_hoc_trainer/README.md +2 -0
- data/lib/studium/yaml/ad_hoc_trainer/exam_topics.md +22 -0
- data/lib/studium/yaml/allowed_themes_for_courses/allowed_themes_for_courses.yml +348 -0
- data/lib/studium/yaml/array_allowed_entries_for_the_file_lecture_information/array_allowed_entries_for_the_file_lecture_information.yml +71 -0
- data/lib/studium/yaml/available_exam_topics/available_exam_topics.yml +234 -0
- data/lib/studium/yaml/backlog_of_exams.yml +37 -0
- data/lib/studium/yaml/colours/custom_colours.yml +50 -0
- data/lib/studium/yaml/colours/use_colours.yml +1 -0
- data/lib/studium/yaml/current_exams.yml +30 -0
- data/lib/studium/yaml/curricula/README.md +39 -0
- data/lib/studium/yaml/curricula/bachelor/bachelor_agrarwissenschaften_033255.yml +147 -0
- data/lib/studium/yaml/curricula/bachelor/bachelor_biologie_basisblock_033630.yml +71 -0
- data/lib/studium/yaml/curricula/bachelor/bachelor_biologie_botanik_033630.yml +100 -0
- data/lib/studium/yaml/curricula/bachelor/bachelor_biologie_ecology_033630.yml +74 -0
- data/lib/studium/yaml/curricula/bachelor/bachelor_biologie_mikrobiologie_und_genetik_033630.yml +122 -0
- data/lib/studium/yaml/curricula/bachelor/bachelor_biologie_molekulare_biologie_033630.yml +106 -0
- data/lib/studium/yaml/curricula/bachelor/bachelor_biologie_zoologie_033630.yml +87 -0
- data/lib/studium/yaml/curricula/bachelor/bachelor_chemie_033662.yml +165 -0
- data/lib/studium/yaml/curricula/bachelor/bachelor_dummy_curriculum.yml +182 -0
- data/lib/studium/yaml/curricula/bachelor/bachelor_elektrotechnik_und_informationstechnik_033235.yml +13 -0
- data/lib/studium/yaml/curricula/bachelor/bachelor_forstwirtschaft_033225.yml +115 -0
- data/lib/studium/yaml/curricula/bachelor/bachelor_informatik_033521.yml +134 -0
- data/lib/studium/yaml/curricula/bachelor/bachelor_ktww_033231.yml +84 -0
- data/lib/studium/yaml/curricula/bachelor/bachelor_lmbt_033217.yml +121 -0
- data/lib/studium/yaml/curricula/bachelor/bachelor_medizinische_informatik_033533.yml +283 -0
- data/lib/studium/yaml/curricula/bachelor/bachelor_molekularbiologie_033665.yml +95 -0
- data/lib/studium/yaml/curricula/bachelor/bachelor_nutrition_science_033638.yml +119 -0
- data/lib/studium/yaml/curricula/bachelor/bachelor_pharmazie_033305.yml +170 -0
- data/lib/studium/yaml/curricula/bachelor/bachelor_technische_chemie_033290.yml +131 -0
- data/lib/studium/yaml/curricula/bachelor/bachelor_technische_informatik_033535.yml +23 -0
- data/lib/studium/yaml/curricula/bachelor/bachelor_ubrm_033227.yml +142 -0
- data/lib/studium/yaml/curricula/bachelor/bachelor_verfahrenstechnik_033273.yml +167 -0
- data/lib/studium/yaml/curricula/bachelor/bachelor_wirtschaftsinformatik_033526.yml +29 -0
- data/lib/studium/yaml/curricula/experimental/bachelor_informatik_in_den_lebenswissenschaften.yml +137 -0
- data/lib/studium/yaml/curricula/individual/bachelor_formale_logik.yml +88 -0
- data/lib/studium/yaml/curricula/individual/bachelor_informatik_und_molekulare_biologie.yml +1161 -0
- data/lib/studium/yaml/curricula/individual/bachelor_vector_based_strategies_in_life_sciences_molecular_medicine_and_biotechnology.yml +1157 -0
- data/lib/studium/yaml/curricula/individual/master_bioinformatics_and_nanobiotechnology_in_molecular_medicine.yml +306 -0
- data/lib/studium/yaml/curricula/individual/master_vector_based_strategies_in_life_sciences_molecular_medicine_and_biotechnology.yml +741 -0
- data/lib/studium/yaml/curricula/master/master_bioinformatik_066875.yml +75 -0
- data/lib/studium/yaml/curricula/master/master_biologie_molekulare_mikrobiologie_mikrobielle_oekologie_und_immunbiologie_066830.yml +78 -0
- data/lib/studium/yaml/curricula/master/master_biologische_chemie_066863.yml +66 -0
- data/lib/studium/yaml/curricula/master/master_dummy_curriculum.yml +197 -0
- data/lib/studium/yaml/curricula/master/master_genetik_und_entwicklungsbiologie_066877.yml +89 -0
- data/lib/studium/yaml/curricula/master/master_lmbt_066418.yml +112 -0
- data/lib/studium/yaml/curricula/master/master_molecular_biology_066865.yml +72 -0
- data/lib/studium/yaml/curricula/master/master_molekulare_biologie_066834.yml +151 -0
- data/lib/studium/yaml/curricula/master/master_pharmazie_066605.yml +176 -0
- data/lib/studium/yaml/curricula/master/master_technische_chemie_066490.yml +123 -0
- data/lib/studium/yaml/curricula/outdated/master_bioinformatics_and_molecular_biotechnology_including_aspects_from_molecular_medicine.yml +438 -0
- data/lib/studium/yaml/curricula/outdated/master_food_science_and_plant_biotechnology.yml +31 -0
- data/lib/studium/yaml/curricula.yml +562 -0
- data/lib/studium/yaml/daily_questions_solved/daily_questions_solved.yml +2019 -0
- data/lib/studium/yaml/daily_questions_solved/daily_questions_solved.yml~ +1983 -0
- data/lib/studium/yaml/default_delay.yml +4 -0
- data/lib/studium/yaml/default_encoding.yml +1 -0
- data/lib/studium/yaml/directory_to_the_exam_topics.yml +0 -0
- data/lib/studium/yaml/editor.yml +1 -0
- data/lib/studium/yaml/exams/next_exams_to_do.md +9 -0
- data/lib/studium/yaml/file_for_exam_questions.yml +1 -0
- data/lib/studium/yaml/german/README.md +2 -0
- data/lib/studium/yaml/german/german_to_english_month_names.yml +16 -0
- data/lib/studium/yaml/grouped_themes/grouped_themes.yml +264 -0
- data/lib/studium/yaml/holidays/holidays.yml +201 -0
- data/lib/studium/yaml/important_exams.yml +286 -0
- data/lib/studium/yaml/inscription_dates_of_universities.yml +60 -0
- data/lib/studium/yaml/lecture_aliases.yml +138 -0
- data/lib/studium/yaml/lecture_information/lecture_information.yml +66145 -0
- data/lib/studium/yaml/log_dir.yml +1 -0
- data/lib/studium/yaml/main_topic/main_topic.yml +11 -0
- data/lib/studium/yaml/max_stats/max_stats.yml +262 -0
- data/lib/studium/yaml/max_stats.yml +263 -0
- data/lib/studium/yaml/meta_themes +1 -0
- data/lib/studium/yaml/mitbelegung/README.md +4 -0
- data/lib/studium/yaml/mitbelegung/mitbelegung.yml +21 -0
- data/lib/studium/yaml/mitteilungsbl/303/244tter/mitteilungsbl/303/244tter.yml +363 -0
- data/lib/studium/yaml/n_total_questions.yml +1 -0
- data/lib/studium/yaml/rename_konsole_tab.yml +1 -0
- data/lib/studium/yaml/roebe/ad_hoc_exam_topics.md +19 -0
- data/lib/studium/yaml/roebe/sommersemester_2024_opportunities.md +441 -0
- data/lib/studium/yaml/semester_planner/README.md +4 -0
- data/lib/studium/yaml/semester_planner/semester_planner.yml +189 -0
- data/lib/studium/yaml/show_topic.yml +1 -0
- data/lib/studium/yaml/statistics/lecture_information.yml +1 -0
- data/lib/studium/yaml/statistics/max_stats.yml +239 -0
- data/lib/studium/yaml/statistics/statistics.yml +77 -0
- data/lib/studium/yaml/week/01_monday.yml +25 -0
- data/lib/studium/yaml/week/02_tuesday.yml +68 -0
- data/lib/studium/yaml/week/03_wednesday.yml +63 -0
- data/lib/studium/yaml/week/04_thursday.yml +20 -0
- data/lib/studium/yaml/week/05_friday.yml +31 -0
- data/lib/studium/yaml/week/06_saturday.yml +16 -0
- data/lib/studium/yaml/week/07_sunday.yml +0 -0
- data/lib/studium/yaml/week/README.md +10 -0
- data/lib/studium.rb +5 -0
- data/studium.gemspec +82 -0
- data/test/testing_colourized_question_and_answer.rb +18 -0
- data/test/testing_studium.rb +244 -0
- data/test/testing_studium_base_class.rb +31 -0
- data/test/testing_the_file_lecture_information.rb +18 -0
- data/test/testing_time_component.rb +29 -0
- metadata +1042 -0
@@ -0,0 +1,3266 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# Encoding: UTF-8
|
3
|
+
# frozen_string_literal: true
|
4
|
+
# =========================================================================== #
|
5
|
+
# === Studium::GUI::UniversalWidgets::ExamTrainer
|
6
|
+
#
|
7
|
+
# This widget can be used to ask exam questions.
|
8
|
+
#
|
9
|
+
# For SQL we could use this:
|
10
|
+
#
|
11
|
+
# result = `sqlite3 #{SQLITE_DATABASE_FILE} "SELECT * FROM #{current_exam_topic?} ORDER BY RANDOM() LIMIT 1;"`
|
12
|
+
# e result
|
13
|
+
#
|
14
|
+
# Usage example:
|
15
|
+
#
|
16
|
+
# Studium::GUI::UniversalWidgets::ExamTrainer.new(ARGV)
|
17
|
+
#
|
18
|
+
# =========================================================================== #
|
19
|
+
# require 'studium/gui/universal_widgets/exam_trainer/exam_trainer.rb'
|
20
|
+
# =========================================================================== #
|
21
|
+
require 'universal_widgets/base/base.rb'
|
22
|
+
|
23
|
+
module Studium
|
24
|
+
|
25
|
+
module GUI
|
26
|
+
|
27
|
+
module UniversalWidgets
|
28
|
+
|
29
|
+
class ExamTrainer < ::UniversalWidgets::Base # === Studium::GUI::UniversalWidgets::ExamTrainer
|
30
|
+
|
31
|
+
require 'universal_widgets/base_module/base_module.rb'
|
32
|
+
include ::UniversalWidgets::BaseModule
|
33
|
+
|
34
|
+
require 'studium/exams/question_answer/question_answer.rb'
|
35
|
+
|
36
|
+
begin
|
37
|
+
require 'roebe/toplevel_methods/rinstall2.rb'
|
38
|
+
rescue LoadError; end
|
39
|
+
|
40
|
+
require 'studium/toplevel_methods/toplevel_methods.rb'
|
41
|
+
require 'studium/toplevel_methods/find_exam_topic_and_exam_title.rb'
|
42
|
+
require 'studium/statistics/report_how_many_exam_questions_were_answered.rb'
|
43
|
+
require 'studium/requires/require_class_exams_solved.rb'
|
44
|
+
require 'studium/exams/exam_question/exam_question.rb'
|
45
|
+
# ========================================================================= #
|
46
|
+
# === TITLE
|
47
|
+
# ========================================================================= #
|
48
|
+
TITLE = 'Simple Exam Trainer'
|
49
|
+
|
50
|
+
# ========================================================================= #
|
51
|
+
# === WIDTH
|
52
|
+
# ========================================================================= #
|
53
|
+
WIDTH = '95% or minimum 2250px'
|
54
|
+
|
55
|
+
# ========================================================================= #
|
56
|
+
# === Studium::GUI::UniversalWidgets::ExamTrainer::HEIGHT
|
57
|
+
#
|
58
|
+
# 1080px is the highest for my large monitor, so I set this below.
|
59
|
+
# ========================================================================= #
|
60
|
+
HEIGHT = '90% or minimum 1060px'
|
61
|
+
|
62
|
+
# ========================================================================= #
|
63
|
+
# === DEFAULT_DELAY
|
64
|
+
#
|
65
|
+
# This constant specifies how long to wait before the answer is
|
66
|
+
# revealed, if the user has set the checkbutton to "automatically
|
67
|
+
# answer the question".
|
68
|
+
# ========================================================================= #
|
69
|
+
DEFAULT_DELAY = '15.0' # This is currently hardcoded.
|
70
|
+
|
71
|
+
# ========================================================================= #
|
72
|
+
# === Studium::GUI::UniversalWidgets::ExamTrainer::N_EXAM_QUESTIONS_IN_TOTAL
|
73
|
+
# ========================================================================= #
|
74
|
+
N_EXAM_QUESTIONS_IN_TOTAL = 'n exam-questions in total'
|
75
|
+
|
76
|
+
# ========================================================================= #
|
77
|
+
# === Studium::GUI::UniversalWidgets::N_ANSWERED_EXAM_QUESTIONS
|
78
|
+
# ========================================================================= #
|
79
|
+
N_ANSWERED_EXAM_QUESTIONS = 'n answered exam-questions'
|
80
|
+
|
81
|
+
# ========================================================================= #
|
82
|
+
# === Studium::GUI::UniversalWidgets::N_UNANSWERED_EXAM_QUESTIONS
|
83
|
+
# ========================================================================= #
|
84
|
+
N_UNANSWERED_EXAM_QUESTIONS = 'n unanswered exam-questions'
|
85
|
+
|
86
|
+
# ========================================================================= #
|
87
|
+
# === Studium::GUI::UniversalWidgets::N_PERCENT_SOLVED
|
88
|
+
#
|
89
|
+
# An alternative name would be 'percentage solved'.
|
90
|
+
# ========================================================================= #
|
91
|
+
N_PERCENT_SOLVED = 'n % solved'
|
92
|
+
|
93
|
+
# ========================================================================= #
|
94
|
+
# === Studium::GUI::UniversalWidgets::SLEEP_N_SECONDS
|
95
|
+
# ========================================================================= #
|
96
|
+
SLEEP_N_SECONDS = 'sleep n seconds'
|
97
|
+
|
98
|
+
# ========================================================================= #
|
99
|
+
# === PANEL_TOOLTIP_TEXT
|
100
|
+
# ========================================================================= #
|
101
|
+
PANEL_TOOLTIP_TEXT = 'Exam Trainer Widget'
|
102
|
+
|
103
|
+
# ========================================================================= #
|
104
|
+
# === SQLITE_DATABASE_FILE
|
105
|
+
#
|
106
|
+
# This is experimental - one day we may want to query from a sqlite
|
107
|
+
# database rather than flat files. Or, at the least, offer this as
|
108
|
+
# a possibility.
|
109
|
+
# ========================================================================= #
|
110
|
+
SQLITE_DATABASE_FILE = '/Depot/jjjj/exam_questions.db'
|
111
|
+
|
112
|
+
# ========================================================================= #
|
113
|
+
# === USE_THIS_FONT
|
114
|
+
#
|
115
|
+
# The older font was :dejavu_condensed_20 and the oldest font
|
116
|
+
# was :deja_vu_sans_25. Before December 2023 the font was :hack_20,
|
117
|
+
# but now it is :hack_22.
|
118
|
+
#
|
119
|
+
# It is recommended to use the method main_font? rather than this
|
120
|
+
# constant directly.
|
121
|
+
# ========================================================================= #
|
122
|
+
USE_THIS_FONT = :hack_22
|
123
|
+
|
124
|
+
# ========================================================================= #
|
125
|
+
# === LARGER_FONT
|
126
|
+
# ========================================================================= #
|
127
|
+
LARGER_FONT = :hack_26
|
128
|
+
|
129
|
+
# ========================================================================= #
|
130
|
+
# === SMALLER_FONT
|
131
|
+
#
|
132
|
+
# This one should be matched onto the larger font defined above.
|
133
|
+
# ========================================================================= #
|
134
|
+
SMALLER_FONT = :hack_20
|
135
|
+
|
136
|
+
# ========================================================================= #
|
137
|
+
# === SMALLEST_FONT
|
138
|
+
# ========================================================================= #
|
139
|
+
SMALLEST_FONT = :hack_15
|
140
|
+
|
141
|
+
# ========================================================================= #
|
142
|
+
# === WORD_WRAP_AT_N_CHARACTERS
|
143
|
+
#
|
144
|
+
# Specify after n characters a given text has to be wrapped via
|
145
|
+
# newlines, e. g. "\n".
|
146
|
+
# ========================================================================= #
|
147
|
+
WORD_WRAP_AT_N_CHARACTERS = 76
|
148
|
+
|
149
|
+
# ========================================================================= #
|
150
|
+
# === DEFAULT_PLACEHOLDER_TEXT
|
151
|
+
# ========================================================================= #
|
152
|
+
DEFAULT_PLACEHOLDER_TEXT =
|
153
|
+
'You can input your answer to the exam question here.'
|
154
|
+
|
155
|
+
# ========================================================================= #
|
156
|
+
# === USE_THIS_MARGIN
|
157
|
+
# ========================================================================= #
|
158
|
+
USE_THIS_MARGIN = 12
|
159
|
+
|
160
|
+
# ========================================================================= #
|
161
|
+
# === USE_THIS_AS_THE_DEFAULT_EXAM_TOPIC
|
162
|
+
#
|
163
|
+
# This constant can be used to specify the default exam topic to be
|
164
|
+
# used on startup of this application.
|
165
|
+
# ========================================================================= #
|
166
|
+
USE_THIS_AS_THE_DEFAULT_EXAM_TOPIC =
|
167
|
+
'toxikologie' # bioinformatics' # 'virus' # stemcells' # chem1' #anatomy'
|
168
|
+
|
169
|
+
# ========================================================================= #
|
170
|
+
# === HASH_DESIGNATED_KEY_COMBINATIONS
|
171
|
+
# ========================================================================= #
|
172
|
+
HASH_DESIGNATED_KEY_COMBINATIONS = {
|
173
|
+
'strg+s': 'save_the_buffer',
|
174
|
+
'alt+y': 'activate_the_third_textview'
|
175
|
+
}
|
176
|
+
|
177
|
+
# ========================================================================= #
|
178
|
+
# === initialize
|
179
|
+
# ========================================================================= #
|
180
|
+
def initialize(
|
181
|
+
commandline_arguments = nil,
|
182
|
+
run_already = true
|
183
|
+
)
|
184
|
+
# ======================================================================= #
|
185
|
+
# We first have to determine the GUI that is to be used, even before
|
186
|
+
# calling reset(). The reason is that this will also require some
|
187
|
+
# files, such as the Gdk namespace, which may be used by the GUI
|
188
|
+
# related parts for ruby-gtk3, for instance.
|
189
|
+
# ======================================================================= #
|
190
|
+
determine_the_GUI_to_be_used(commandline_arguments)
|
191
|
+
# super(:vertical) This should be for ruby-gtk3, for a BaseModuleBox.
|
192
|
+
reset
|
193
|
+
set_commandline_arguments(
|
194
|
+
commandline_arguments
|
195
|
+
)
|
196
|
+
run if run_already
|
197
|
+
end
|
198
|
+
|
199
|
+
# ========================================================================= #
|
200
|
+
# === reset (reset tag)
|
201
|
+
# ========================================================================= #
|
202
|
+
def reset
|
203
|
+
super() if respond_to?(:super)
|
204
|
+
reset_the_internal_variables
|
205
|
+
reset_the_base_module # This must come after reset_the_internal_variables().
|
206
|
+
reset_the_shared_module
|
207
|
+
infer_the_namespace
|
208
|
+
reset_the_shared_variables
|
209
|
+
Studium.set_runmode :gui # Make it known that we use the gui-runmode in this case.
|
210
|
+
# ======================================================================= #
|
211
|
+
# === @configuration
|
212
|
+
# ======================================================================= #
|
213
|
+
@configuration = [true, __dir__, namespace?]
|
214
|
+
# ======================================================================= #
|
215
|
+
# === Set the title; this must come after we delegate to the
|
216
|
+
# @configuration object
|
217
|
+
# ======================================================================= #
|
218
|
+
set_title(
|
219
|
+
return_the_title_from_the_config_file(true, @configuration)
|
220
|
+
)
|
221
|
+
# ======================================================================= #
|
222
|
+
# === Set the title, width, height and the font in use.
|
223
|
+
# ======================================================================= #
|
224
|
+
title_width_height_font(title?, WIDTH, HEIGHT, USE_THIS_FONT)
|
225
|
+
handle_CSS if use_gtk3?
|
226
|
+
enable_all_key_combinations # This should come after CSS was handled.
|
227
|
+
infer_the_size_automatically
|
228
|
+
# ======================================================================= #
|
229
|
+
# === @delay_to_use
|
230
|
+
# ======================================================================= #
|
231
|
+
set_delay_to_use(DEFAULT_DELAY)
|
232
|
+
# ======================================================================= #
|
233
|
+
# === @internal_hash[:may_we_reveal_the_answer]
|
234
|
+
# ======================================================================= #
|
235
|
+
@internal_hash[:may_we_reveal_the_answer] = true
|
236
|
+
# ======================================================================= #
|
237
|
+
# === :prefer_emoji_or_images
|
238
|
+
#
|
239
|
+
# This variable can have two different states:
|
240
|
+
#
|
241
|
+
# :emoji
|
242
|
+
# :images
|
243
|
+
#
|
244
|
+
# If :emoji is active then we will use emojis to enhance the
|
245
|
+
# user interface. If :images is active then we will use different
|
246
|
+
# images from the main icon theme in use instead.
|
247
|
+
#
|
248
|
+
# The reason why this was added in May 2021 was because the host
|
249
|
+
# system may not support this or that emoji. If the emoji is
|
250
|
+
# not supported then the user will see only garbage, which isn't
|
251
|
+
# great. Thus, the default is now for :images since as of May
|
252
|
+
# 2021, but with the intended goal to retain support for emojis
|
253
|
+
# as well, should a user ever want to change this.
|
254
|
+
# ======================================================================= #
|
255
|
+
@internal_hash[:prefer_emoji_or_images] = :images
|
256
|
+
# ======================================================================= #
|
257
|
+
# === :use_this_editor
|
258
|
+
#
|
259
|
+
# The value of this variable may be :bluefish or :internal usually.
|
260
|
+
# ======================================================================= #
|
261
|
+
@internal_hash[:use_this_editor] = :bluefish # :internal
|
262
|
+
# ======================================================================= #
|
263
|
+
# === :show_ten_aliases
|
264
|
+
#
|
265
|
+
# This is only in use if the roebe-gem is available. Many users of this
|
266
|
+
# class won't need it though.
|
267
|
+
# ======================================================================= #
|
268
|
+
@internal_hash[:show_ten_aliases] = nil
|
269
|
+
# ======================================================================= #
|
270
|
+
# === @internal_hash[:colour_to_use_for_the_notebook_labels]
|
271
|
+
# ======================================================================= #
|
272
|
+
@internal_hash[:colour_to_use_for_the_notebook_labels] = 'darkblue'
|
273
|
+
# ======================================================================= #
|
274
|
+
# === @internal_hash[:smaller_font]
|
275
|
+
# ======================================================================= #
|
276
|
+
@internal_hash[:smaller_font] = SMALLER_FONT
|
277
|
+
consider_making_available_the_show_ten_aliases_widget
|
278
|
+
upon_delete_event_quit_the_application
|
279
|
+
end
|
280
|
+
|
281
|
+
# ========================================================================= #
|
282
|
+
# === reset_the_shared_variables
|
283
|
+
# ========================================================================= #
|
284
|
+
def reset_the_shared_variables
|
285
|
+
# ======================================================================= #
|
286
|
+
# === :hash_dataset_of_all_lectures
|
287
|
+
#
|
288
|
+
# This is the Hash that looks like this:
|
289
|
+
#
|
290
|
+
# :biopolymers => {:n_total_questions=>4, :n_questions_answered=>0, :percentage_of_questions_answered=>0.0},
|
291
|
+
# :biophysik => {:n_total_questions=>28, :n_questions_answered=>0, :percentage_of_questions_answered=>0.0},
|
292
|
+
#
|
293
|
+
# In other words: it will keep track of how many exam questions and
|
294
|
+
# exam answers are in that Hash.
|
295
|
+
# ======================================================================= #
|
296
|
+
@internal_hash[:hash_dataset_of_all_lectures] =
|
297
|
+
Studium::Statistics::ReportHowManyExamQuestionsWereAnswered.new { :be_quiet }.internal_dataset
|
298
|
+
end
|
299
|
+
|
300
|
+
# ========================================================================= #
|
301
|
+
# === border_size?
|
302
|
+
# ========================================================================= #
|
303
|
+
def border_size?
|
304
|
+
0
|
305
|
+
end
|
306
|
+
|
307
|
+
# ========================================================================= #
|
308
|
+
# === padding?
|
309
|
+
# ========================================================================= #
|
310
|
+
def padding?
|
311
|
+
8
|
312
|
+
end
|
313
|
+
|
314
|
+
# ========================================================================= #
|
315
|
+
# === update_hash_dataset_of_all_lectures
|
316
|
+
# ========================================================================= #
|
317
|
+
def update_hash_dataset_of_all_lectures
|
318
|
+
@internal_hash[:hash_dataset_of_all_lectures] =
|
319
|
+
Studium::Statistics::ReportHowManyExamQuestionsWereAnswered.new { :be_quiet }.internal_dataset
|
320
|
+
end
|
321
|
+
|
322
|
+
# ========================================================================= #
|
323
|
+
# === find_completion_for_the_entry_for_the_current_exam_topic
|
324
|
+
# ========================================================================= #
|
325
|
+
def find_completion_for_the_entry_for_the_current_exam_topic
|
326
|
+
_ = entry_for_the_current_exam_topic?
|
327
|
+
current_text = _.text?
|
328
|
+
new_text = Studium.exam_topic_completion(current_text) { :be_quiet } # Expand it here.
|
329
|
+
if new_text
|
330
|
+
unless new_text == current_text
|
331
|
+
set_exam_topic(new_text)
|
332
|
+
end
|
333
|
+
one_two_three # The old call was: do_update_the_entry_n_questions
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
# ========================================================================= #
|
338
|
+
# === do_update_the_entry_n_questions
|
339
|
+
# ========================================================================= #
|
340
|
+
def do_update_the_entry_n_questions(
|
341
|
+
current_exam_topic =
|
342
|
+
current_exam_topic?
|
343
|
+
)
|
344
|
+
set_n_exam_questions(
|
345
|
+
return_n_questions_from_the_currently_selected_topic(current_exam_topic).to_s
|
346
|
+
)
|
347
|
+
end
|
348
|
+
|
349
|
+
# ========================================================================= #
|
350
|
+
# === let_the_scrolled_window_for_the_answer_parse_URLs
|
351
|
+
# ========================================================================= #
|
352
|
+
def let_the_scrolled_window_for_the_answer_parse_URLs(
|
353
|
+
scrolled_window_for_the_answer = scrolled_window_for_the_answer?
|
354
|
+
)
|
355
|
+
# ======================================================================= #
|
356
|
+
# The scrolled-window for the answer allows the user to click on
|
357
|
+
# hyperlinks - or at the least this is the idea. It does not
|
358
|
+
# work 100% yet because we need to get the selection first
|
359
|
+
# rather than select the whole entry.
|
360
|
+
# ======================================================================= #
|
361
|
+
scrolled_window_for_the_answer.on_button_release_event {
|
362
|
+
parse_for_URL(text_view_for_the_answer?.text?)
|
363
|
+
} if scrolled_window_for_the_answer
|
364
|
+
end
|
365
|
+
|
366
|
+
# ========================================================================= #
|
367
|
+
# === scrolled_window2?
|
368
|
+
# ========================================================================= #
|
369
|
+
def scrolled_window2?
|
370
|
+
@scrolled_window_containing_the_textarea2
|
371
|
+
end; alias return_scrolled_window_containing_the_text_view_for_the_answer scrolled_window2? # === return_scrolled_window_containing_the_text_view_for_the_answer
|
372
|
+
alias scrolled_window_for_the_answer? scrolled_window2? # === scrolled_window_for_the_answer?
|
373
|
+
alias scrolled_window_containing_the_textarea2? scrolled_window2? # === scrolled_window_containing_the_textarea2?
|
374
|
+
|
375
|
+
# ========================================================================= #
|
376
|
+
# === return_wikipedia_widget (wikipedia tag)
|
377
|
+
#
|
378
|
+
# This method will return the widget that, upon user-mouse-button-click
|
379
|
+
# event, will open the corresponding wikipedia entry. This defaults
|
380
|
+
# to the german wikipedia entry right now; if others want to change
|
381
|
+
# the default then this could be changed easily.
|
382
|
+
# ========================================================================= #
|
383
|
+
def return_wikipedia_widget
|
384
|
+
begin
|
385
|
+
require 'roebe/classes/wikipedia.rb'
|
386
|
+
rescue LoadError; end
|
387
|
+
|
388
|
+
hbox = create_hbox
|
389
|
+
wikipedia_entry = entry
|
390
|
+
wikipedia_entry.clear_background
|
391
|
+
wikipedia_entry.bblack1
|
392
|
+
wikipedia_entry.center
|
393
|
+
wikipedia_entry.pad3px
|
394
|
+
wikipedia_entry.lightgreen_background
|
395
|
+
wikipedia_entry.width_height(650, 30)
|
396
|
+
wikipedia_entry.hint =
|
397
|
+
'Click the "<b>enter</b>" key to open the assorted keyword in the '\
|
398
|
+
'german-wikipedia. Simply replace <b>de</b> with <b>en</b> in '\
|
399
|
+
'the URL to have the english wikipedia.'
|
400
|
+
wikipedia_entry.on_enter {
|
401
|
+
if Object.const_defined?(:Roebe) and
|
402
|
+
Roebe.const_defined?(:Wikipedia)
|
403
|
+
Roebe::Wikipedia.new(wikipedia_entry.text?) # Instantiate a new wrapper.
|
404
|
+
else
|
405
|
+
e 'You need to install the '+steelblue('roebe')+
|
406
|
+
' gem for this functionality.'
|
407
|
+
end
|
408
|
+
}
|
409
|
+
hbox.minimal(wikipedia_entry, 2)
|
410
|
+
return hbox
|
411
|
+
end
|
412
|
+
|
413
|
+
# ========================================================================= #
|
414
|
+
# === larger_font?
|
415
|
+
# ========================================================================= #
|
416
|
+
def larger_font?
|
417
|
+
LARGER_FONT
|
418
|
+
end
|
419
|
+
|
420
|
+
# ========================================================================= #
|
421
|
+
# === do_jump_into_the_entry_containing_the_current_exam_topic
|
422
|
+
# ========================================================================= #
|
423
|
+
def do_jump_into_the_entry_containing_the_current_exam_topic
|
424
|
+
entry_for_the_current_exam_topic?.do_focus_on_it
|
425
|
+
end
|
426
|
+
|
427
|
+
# ========================================================================= #
|
428
|
+
# === debug
|
429
|
+
# ========================================================================= #
|
430
|
+
def debug
|
431
|
+
pp array_all_exam_questions?
|
432
|
+
pp array_all_exam_questions?.size
|
433
|
+
end
|
434
|
+
|
435
|
+
# ========================================================================= #
|
436
|
+
# === rinstall2
|
437
|
+
# ========================================================================= #
|
438
|
+
def rinstall2
|
439
|
+
Roebe.rinstall2(
|
440
|
+
use_this_directory: Studium.ruby_src_dir_at_home?+
|
441
|
+
'studium/'
|
442
|
+
)
|
443
|
+
end; alias r2 rinstall2 # === r2
|
444
|
+
|
445
|
+
# ========================================================================= #
|
446
|
+
# === main_font?
|
447
|
+
# ========================================================================= #
|
448
|
+
def main_font?
|
449
|
+
USE_THIS_FONT
|
450
|
+
end
|
451
|
+
|
452
|
+
# ========================================================================= #
|
453
|
+
# === default_exam_topic?
|
454
|
+
# ========================================================================= #
|
455
|
+
def default_exam_topic?
|
456
|
+
USE_THIS_AS_THE_DEFAULT_EXAM_TOPIC
|
457
|
+
end
|
458
|
+
|
459
|
+
# ========================================================================= #
|
460
|
+
# === clear_the_exam_answer (clear tag)
|
461
|
+
#
|
462
|
+
# This method may only ever call set_exam_answer() - no other method
|
463
|
+
# is allowed to be called here.
|
464
|
+
# ========================================================================= #
|
465
|
+
def clear_the_exam_answer
|
466
|
+
set_exam_answer('') # Simply set the answer to an empty String here.
|
467
|
+
end; alias clear_reveal_the_answer clear_the_exam_answer # === clear_reveal_the_answer
|
468
|
+
alias clear_answers clear_the_exam_answer # === clear_answers
|
469
|
+
alias clear_answers_buffer clear_the_exam_answer # === clear_answers_buffer
|
470
|
+
alias clear_answer_buffer clear_the_exam_answer # === clear_answer_buffer
|
471
|
+
alias clear_the_answer_buffer clear_the_exam_answer # === clear_the_answer_buffer
|
472
|
+
|
473
|
+
# ========================================================================= #
|
474
|
+
# === use_the_internal_editor?
|
475
|
+
# ========================================================================= #
|
476
|
+
def use_the_internal_editor?
|
477
|
+
@internal_hash[:use_this_editor] == :internal
|
478
|
+
end
|
479
|
+
|
480
|
+
# ========================================================================= #
|
481
|
+
# === use_this_editor?
|
482
|
+
# ========================================================================= #
|
483
|
+
def use_this_editor?
|
484
|
+
@internal_hash[:use_this_editor]
|
485
|
+
end
|
486
|
+
|
487
|
+
# ========================================================================= #
|
488
|
+
# === all_textviews?
|
489
|
+
# ========================================================================= #
|
490
|
+
def all_textviews?
|
491
|
+
[
|
492
|
+
textview1?,
|
493
|
+
textview2?,
|
494
|
+
textview3?
|
495
|
+
]
|
496
|
+
end
|
497
|
+
|
498
|
+
# ========================================================================= #
|
499
|
+
# === set_editor_buffer
|
500
|
+
# ========================================================================= #
|
501
|
+
def set_editor_buffer(i)
|
502
|
+
editor?.set_buffer(i.to_s)
|
503
|
+
end
|
504
|
+
|
505
|
+
# ========================================================================= #
|
506
|
+
# === handle_CSS (CSS tag)
|
507
|
+
# ========================================================================= #
|
508
|
+
def handle_CSS
|
509
|
+
use_gtk_paradise_project_css_file
|
510
|
+
append_project_css_file(
|
511
|
+
Studium.project_base_directory?+'css/project.css'
|
512
|
+
)
|
513
|
+
apply_the_CSS_rules
|
514
|
+
end
|
515
|
+
|
516
|
+
# ========================================================================= #
|
517
|
+
# === do_interactively_change_the_font
|
518
|
+
#
|
519
|
+
# This does not work. :(
|
520
|
+
# ========================================================================= #
|
521
|
+
def do_interactively_change_the_font
|
522
|
+
require 'gtk_paradise/widgets/gtk3/text_entry_widget/text_entry_widget.rb'
|
523
|
+
require 'gtk_paradise/examples/gtk3/gtk_dialog_sample.rb'
|
524
|
+
_ = ::Gtk::TextEntryWidget.run
|
525
|
+
::Gtk::DialogSample.new(_)
|
526
|
+
::Gtk.main
|
527
|
+
e 'The selection was:'
|
528
|
+
e
|
529
|
+
pp _.selection?
|
530
|
+
e
|
531
|
+
end
|
532
|
+
|
533
|
+
# ========================================================================= #
|
534
|
+
# === context_menu?
|
535
|
+
# ========================================================================= #
|
536
|
+
def context_menu?
|
537
|
+
@context_menu
|
538
|
+
end
|
539
|
+
|
540
|
+
# ========================================================================= #
|
541
|
+
# === button_reveal_the_answer?
|
542
|
+
# ========================================================================= #
|
543
|
+
def button_reveal_the_answer?
|
544
|
+
@internal_hash[:button_reveal_the_answer]
|
545
|
+
end
|
546
|
+
|
547
|
+
# ========================================================================= #
|
548
|
+
# === create_text_buffer_for_the_answer
|
549
|
+
# ========================================================================= #
|
550
|
+
def create_text_buffer_for_the_answer
|
551
|
+
# ======================================================================= #
|
552
|
+
# === @text_buffer_for_the_answer
|
553
|
+
# ======================================================================= #
|
554
|
+
@text_buffer_for_the_answer = create_text_buffer
|
555
|
+
end
|
556
|
+
|
557
|
+
# ========================================================================= #
|
558
|
+
# === sanitize_the_answer
|
559
|
+
#
|
560
|
+
# This is called from within set_exam_answer().
|
561
|
+
# ========================================================================= #
|
562
|
+
def sanitize_the_answer(
|
563
|
+
i,
|
564
|
+
apply_these_filters = []
|
565
|
+
)
|
566
|
+
i = i.to_s
|
567
|
+
if apply_these_filters.is_a? Symbol
|
568
|
+
apply_these_filters = [apply_these_filters]
|
569
|
+
end
|
570
|
+
if apply_these_filters and !apply_these_filters.empty?
|
571
|
+
apply_these_filters.each {|this_filter|
|
572
|
+
case this_filter
|
573
|
+
# =================================================================== #
|
574
|
+
# === :remove_tags
|
575
|
+
# =================================================================== #
|
576
|
+
when :remove_tags,
|
577
|
+
:filter_away_tags
|
578
|
+
i = Studium.remove_tags_from_this_input(i)
|
579
|
+
end
|
580
|
+
}
|
581
|
+
end
|
582
|
+
if i.include? 'URL: '
|
583
|
+
i.gsub!(/URL: /,"\nURL: ")
|
584
|
+
end
|
585
|
+
if i.include?('(2)')
|
586
|
+
i.gsub!(/\(1\)/, "\n (1)")
|
587
|
+
i.gsub!(/\(2\)/, "\n (2)")
|
588
|
+
i.gsub!(/\(3\)/, "\n (3)")
|
589
|
+
i.gsub!(/\(4\)/, "\n (4)")
|
590
|
+
i.gsub!(/\(5\)/, "\n (5)")
|
591
|
+
i.gsub!(/\(6\)/, "\n (6)")
|
592
|
+
i.gsub!(/\(7\)/, "\n (7)")
|
593
|
+
i.gsub!(/\(8\)/, "\n (8)")
|
594
|
+
end
|
595
|
+
i = Studium.remove_html(i)
|
596
|
+
i = word_wrap(i, threshold: WORD_WRAP_AT_N_CHARACTERS)
|
597
|
+
return i.rstrip
|
598
|
+
end; alias sanitize_this_answer sanitize_the_answer # === sanitize_this_answer
|
599
|
+
|
600
|
+
# ========================================================================= #
|
601
|
+
# === consider_running_rinstall2
|
602
|
+
# ========================================================================= #
|
603
|
+
def consider_running_rinstall2
|
604
|
+
if is_on_roebe? and Object.const_defined?(:Roebe)
|
605
|
+
rinstall2 # Run rinstall2 here, to update the local copy.
|
606
|
+
end
|
607
|
+
end
|
608
|
+
|
609
|
+
# ========================================================================= #
|
610
|
+
# === top_textbuffer?
|
611
|
+
# ========================================================================= #
|
612
|
+
def top_textbuffer?
|
613
|
+
text_view_for_the_question?.buffer
|
614
|
+
end
|
615
|
+
|
616
|
+
# ========================================================================= #
|
617
|
+
# === smallest_font?
|
618
|
+
# ========================================================================= #
|
619
|
+
def smallest_font?
|
620
|
+
SMALLEST_FONT
|
621
|
+
end
|
622
|
+
|
623
|
+
# ========================================================================= #
|
624
|
+
# === original_return_available_exam_topics
|
625
|
+
#
|
626
|
+
# This variant is probably no longer necessary, but it is retained for now.
|
627
|
+
# ========================================================================= #
|
628
|
+
def original_return_available_exam_topics
|
629
|
+
Studium.return_available_exam_topics
|
630
|
+
end
|
631
|
+
|
632
|
+
# ========================================================================= #
|
633
|
+
# === create_the_context_menu
|
634
|
+
#
|
635
|
+
# This is the context-menu which will appear on a right-mouse
|
636
|
+
# click event. It currently only works on ruby-gtk3.
|
637
|
+
# ========================================================================= #
|
638
|
+
def create_the_context_menu
|
639
|
+
# ======================================================================= #
|
640
|
+
# === @context_menu
|
641
|
+
# ======================================================================= #
|
642
|
+
@context_menu = create_context_menu(self) {{
|
643
|
+
numbered_actions: {
|
644
|
+
'Ask an exam question': :ask_an_exam_question,
|
645
|
+
'Reveal the answer to the exam question': :reveal_the_answer_to_the_exam_question,
|
646
|
+
'Mark the exam question as solved': :mark_the_exam_question_as_solved,
|
647
|
+
'Pick a new font (show the widget)': :popup_pick_a_new_font,
|
648
|
+
'Debug': :debug
|
649
|
+
#'Change the font in use': :do_interactively_change_the_font,
|
650
|
+
}
|
651
|
+
}}
|
652
|
+
@context_menu.make_bold
|
653
|
+
@context_menu.set_font(:hack_18)
|
654
|
+
end
|
655
|
+
|
656
|
+
# ========================================================================= #
|
657
|
+
# === instantiate_the_control_panel
|
658
|
+
#
|
659
|
+
# This only works for ruby-gtk3.
|
660
|
+
# ========================================================================= #
|
661
|
+
def instantiate_the_control_panel
|
662
|
+
require 'studium/gui/gtk3/control_panel/control_panel.rb'
|
663
|
+
# ======================================================================= #
|
664
|
+
# === @control_panel
|
665
|
+
# ======================================================================= #
|
666
|
+
@control_panel = ::Studium::GUI::Gtk::ControlPanel.new(self)
|
667
|
+
@control_panel.use_this_font(main_font?)
|
668
|
+
end
|
669
|
+
|
670
|
+
# ========================================================================= #
|
671
|
+
# === use_emoji?
|
672
|
+
# ========================================================================= #
|
673
|
+
def use_emoji?
|
674
|
+
@internal_hash[:prefer_emoji_or_images] == :emoji
|
675
|
+
end
|
676
|
+
|
677
|
+
# ========================================================================= #
|
678
|
+
# === set_save_into_this_local_file
|
679
|
+
#
|
680
|
+
# This method will only be in use if the internal editor is used.
|
681
|
+
# ========================================================================= #
|
682
|
+
def set_save_into_this_local_file(i)
|
683
|
+
editor?.set_save_into_this_local_file(i.to_s)
|
684
|
+
end
|
685
|
+
|
686
|
+
# ========================================================================= #
|
687
|
+
# === create_the_button_use_random_entry_from_the_ten_aliases
|
688
|
+
# ========================================================================= #
|
689
|
+
def create_the_button_use_random_entry_from_the_ten_aliases
|
690
|
+
# ======================================================================= #
|
691
|
+
# === @internal_hash[:button_use_random_entry_from_the_ten_aliases]
|
692
|
+
#
|
693
|
+
# This is an eventbox rather than a button, but I think this is still
|
694
|
+
# fine. The unicode character "🕵" (U+1F575) is the spy character.
|
695
|
+
# ======================================================================= #
|
696
|
+
if use_emoji?
|
697
|
+
label = create_label('🕵️')
|
698
|
+
else
|
699
|
+
# label = image_avatar_default # This will be a gtk-image for ruby-gtk3.
|
700
|
+
# In December 2023, the above was changed to an image.
|
701
|
+
label = create_image(
|
702
|
+
Gtk.project_base_directory?+'images/misc/investigate.png'
|
703
|
+
)
|
704
|
+
end
|
705
|
+
# ======================================================================= #
|
706
|
+
# === @internal_hash[:button_use_random_entry_from_the_ten_aliases]
|
707
|
+
# ======================================================================= #
|
708
|
+
_ = create_eventbox(label)
|
709
|
+
_.on_clicked {
|
710
|
+
if show_ten_aliases?
|
711
|
+
set_exam_topic(
|
712
|
+
show_ten_aliases?.return_random_entry
|
713
|
+
)
|
714
|
+
one_two_three
|
715
|
+
end
|
716
|
+
}
|
717
|
+
_.set_size_request(40, 40)
|
718
|
+
_.on_hover_lightblue
|
719
|
+
# Provide some helpful message to help the user make use of this
|
720
|
+
# button.
|
721
|
+
_.hint =
|
722
|
+
'Click on this small widget to randomly assign one of '\
|
723
|
+
'the 10 exam-topics currently being studied as the '\
|
724
|
+
'new main exam-topic in use.'
|
725
|
+
# This is actually an event box rather than a button.
|
726
|
+
@internal_hash[:button_use_random_entry_from_the_ten_aliases] = _ # And assign it here too.
|
727
|
+
return _
|
728
|
+
end
|
729
|
+
|
730
|
+
# ========================================================================= #
|
731
|
+
# === button_use_random_entry_from_the_ten_aliases?
|
732
|
+
# ========================================================================= #
|
733
|
+
def button_use_random_entry_from_the_ten_aliases?
|
734
|
+
@internal_hash[:button_use_random_entry_from_the_ten_aliases]
|
735
|
+
end
|
736
|
+
|
737
|
+
# ========================================================================= #
|
738
|
+
# === do_update_the_entries_n_answered_and_n_unanswered
|
739
|
+
# ========================================================================= #
|
740
|
+
def do_update_the_entries_n_answered_and_n_unanswered
|
741
|
+
do_update_the_entry_n_unanswered_questions
|
742
|
+
update_n_unanswered
|
743
|
+
end
|
744
|
+
|
745
|
+
# ========================================================================= #
|
746
|
+
# === set_delay_to_use
|
747
|
+
# ========================================================================= #
|
748
|
+
def set_delay_to_use(
|
749
|
+
i = DEFAULT_DELAY
|
750
|
+
)
|
751
|
+
@internal_hash[:delay_to_use] = i.to_f
|
752
|
+
end
|
753
|
+
|
754
|
+
# ========================================================================= #
|
755
|
+
# === reset_the_shared_module
|
756
|
+
# ========================================================================= #
|
757
|
+
def reset_the_shared_module
|
758
|
+
# ======================================================================= #
|
759
|
+
# === :array_all_exam_questions
|
760
|
+
# ======================================================================= #
|
761
|
+
@internal_hash[:array_all_exam_questions] = []
|
762
|
+
end
|
763
|
+
|
764
|
+
# ========================================================================= #
|
765
|
+
# === enable_alt_1_key_combination
|
766
|
+
# ========================================================================= #
|
767
|
+
def enable_alt_1_key_combination
|
768
|
+
# ======================================================================= #
|
769
|
+
# Add alt+1 key combination:
|
770
|
+
# ======================================================================= #
|
771
|
+
use_this_key = Gdk::Keyval::KEY_1
|
772
|
+
@accel_group.connect(use_this_key, :mod1_mask, :visible) { # alt+1
|
773
|
+
entry_ask_questions?.set_focus(true)
|
774
|
+
}
|
775
|
+
end
|
776
|
+
|
777
|
+
# ========================================================================= #
|
778
|
+
# === enable_alt_y_key_combination
|
779
|
+
# ========================================================================= #
|
780
|
+
def enable_alt_y_key_combination
|
781
|
+
# ======================================================================= #
|
782
|
+
# Add alt+y key combination, to assign a new exam topic:
|
783
|
+
# ======================================================================= #
|
784
|
+
use_this_key = Gdk::Keyval::KEY_Y
|
785
|
+
@accel_group.connect(use_this_key, :mod1_mask, :visible) { # alt+y
|
786
|
+
do_assign_a_new_exam_topic
|
787
|
+
}
|
788
|
+
end
|
789
|
+
|
790
|
+
# ========================================================================= #
|
791
|
+
# === popup_pick_a_new_font
|
792
|
+
# ========================================================================= #
|
793
|
+
def popup_pick_a_new_font
|
794
|
+
_ = create_hbox
|
795
|
+
_.minimal(text(' → '))
|
796
|
+
file_chooser_widget = button('Choose font here')
|
797
|
+
file_chooser_widget.set_size_request(800, 660)
|
798
|
+
file_chooser_widget.bblack2
|
799
|
+
file_chooser_widget.disallow_resizing
|
800
|
+
_.minimal(file_chooser_widget) # Add the file-chooser widget here.
|
801
|
+
file_chooser_widget.on_click {
|
802
|
+
result = gtk_font_chooser_dialog
|
803
|
+
set_use_this_font(::Gtk.main_file?)
|
804
|
+
result.destroy
|
805
|
+
}
|
806
|
+
# ======================================================================= #
|
807
|
+
# Next create the popup for the font-choosing.
|
808
|
+
# ======================================================================= #
|
809
|
+
popup_widget = popup_over_this_widget(
|
810
|
+
text_view_for_the_question?,
|
811
|
+
'',
|
812
|
+
_
|
813
|
+
)
|
814
|
+
# popup_widget.no_arrow # ← This will only work on gtk4, I think.
|
815
|
+
popup_widget.popup
|
816
|
+
end
|
817
|
+
|
818
|
+
# ========================================================================= #
|
819
|
+
# === textview3?
|
820
|
+
# ========================================================================= #
|
821
|
+
def textview3?
|
822
|
+
@internal_hash[:textview3]
|
823
|
+
end; alias text_view_for_the_freeform_input? textview3? # === free_form_textarea?
|
824
|
+
alias text_view_for_the_freeform_input textview3? # === text_view_for_the_freeform_input
|
825
|
+
alias return_widget_for_the_freeform_textview textview3? # === return_widget_for_the_freeform_textview
|
826
|
+
alias free_form_textarea? textview3? # === free_form_textarea?
|
827
|
+
alias return_textarea_number_three textview3? # === return_textarea_number_three
|
828
|
+
|
829
|
+
# ========================================================================= #
|
830
|
+
# === create_the_entry_percentage
|
831
|
+
# ========================================================================= #
|
832
|
+
def create_the_entry_percentage(
|
833
|
+
use_this_font = smaller_font?
|
834
|
+
)
|
835
|
+
# ======================================================================= #
|
836
|
+
# === Next create the percentage-entry
|
837
|
+
# ======================================================================= #
|
838
|
+
_ = entry('', 12)
|
839
|
+
@internal_hash[:entry_percentage] = _
|
840
|
+
enhance_the_entry_percentage(use_this_font) # This has to happen after the ^^^ above.
|
841
|
+
return _
|
842
|
+
end
|
843
|
+
|
844
|
+
# ========================================================================= #
|
845
|
+
# === save_the_buffer
|
846
|
+
# ========================================================================= #
|
847
|
+
def save_the_buffer
|
848
|
+
editor?.save_the_buffer
|
849
|
+
# ======================================================================= #
|
850
|
+
# Check whether we use the internal editor or not.
|
851
|
+
# ======================================================================= #
|
852
|
+
if use_the_internal_editor? and is_on_roebe?
|
853
|
+
# ===================================================================== #
|
854
|
+
# In this case jump to the first tab.
|
855
|
+
# ===================================================================== #
|
856
|
+
@notebook_tab.focus_on_this_tab(0)
|
857
|
+
rinstall2
|
858
|
+
end
|
859
|
+
end
|
860
|
+
|
861
|
+
# ========================================================================= #
|
862
|
+
# === control_panel?
|
863
|
+
# ========================================================================= #
|
864
|
+
def control_panel?
|
865
|
+
@control_panel
|
866
|
+
end
|
867
|
+
|
868
|
+
# ========================================================================= #
|
869
|
+
# === create_the_entries (entries tag, entry tag)
|
870
|
+
# ========================================================================= #
|
871
|
+
def create_the_entries(
|
872
|
+
use_this_font = :default_font
|
873
|
+
)
|
874
|
+
# ======================================================================= #
|
875
|
+
# The entry "n percentage" will be created first:
|
876
|
+
# ======================================================================= #
|
877
|
+
create_the_entry_percentage
|
878
|
+
# ======================================================================= #
|
879
|
+
# === The entry for n exam questions in total comes next
|
880
|
+
# ======================================================================= #
|
881
|
+
create_the_entry_containing_n_questions
|
882
|
+
create_the_entry_for_the_current_exam_topic
|
883
|
+
create_the_entry_n_unanswered_questions
|
884
|
+
# ======================================================================= #
|
885
|
+
# === :entry_for_sleeping_n_seconds
|
886
|
+
# ======================================================================= #
|
887
|
+
create_the_entry_for_sleeping_n_seconds
|
888
|
+
create_the_entry_n_answered_exam_questions(use_this_font)
|
889
|
+
end
|
890
|
+
|
891
|
+
# ========================================================================= #
|
892
|
+
# === textview2?
|
893
|
+
# ========================================================================= #
|
894
|
+
def textview2?
|
895
|
+
@internal_hash[:textview2]
|
896
|
+
end; alias return_widget_for_the_answers textview2? # === return_widget_for_the_answers
|
897
|
+
alias text_view_for_the_answer textview2? # === text_view_for_the_answer
|
898
|
+
alias text_view_for_the_answer? textview2? # === text_view_for_the_answer?
|
899
|
+
alias textarea2? textview2? # === textarea2?
|
900
|
+
alias answer_buffer? textview2? # === answer_buffer?
|
901
|
+
alias answer_buffer textview2? # === answer_buffer
|
902
|
+
|
903
|
+
# ========================================================================= #
|
904
|
+
# === do_clear_the_question_buffer
|
905
|
+
#
|
906
|
+
# Clear the question-buffer via this method.
|
907
|
+
# ========================================================================= #
|
908
|
+
def do_clear_the_question_buffer
|
909
|
+
text_buffer_for_the_question?.set_text('')
|
910
|
+
end; alias clear_question_buffer do_clear_the_question_buffer # === clear_question_buffer
|
911
|
+
alias clear_questions_buffer do_clear_the_question_buffer # === clear_questions_buffer
|
912
|
+
|
913
|
+
# ========================================================================= #
|
914
|
+
# === update_n_answered
|
915
|
+
# ========================================================================= #
|
916
|
+
def update_n_answered(
|
917
|
+
i = :infer
|
918
|
+
)
|
919
|
+
case i
|
920
|
+
# ======================================================================= #
|
921
|
+
# === :infer
|
922
|
+
# ======================================================================= #
|
923
|
+
when :infer
|
924
|
+
current_exam_topic = current_exam_topic_from_the_entry?
|
925
|
+
hash = hash_dataset_of_all_lectures? # Always update it here in this case.
|
926
|
+
_ = hash[current_exam_topic.tr(' ','_').to_sym]
|
927
|
+
i = _[:n_questions_answered]
|
928
|
+
end
|
929
|
+
set_n_exam_questions_were_already_answered(i)
|
930
|
+
end; alias do_update_the_entry_n_answered update_n_answered # === update_n_answered
|
931
|
+
|
932
|
+
# ========================================================================= #
|
933
|
+
# === return_event_box_with_face_glasses
|
934
|
+
#
|
935
|
+
# This one belongs close to the top of the widget.
|
936
|
+
# ========================================================================= #
|
937
|
+
def return_event_box_with_face_glasses
|
938
|
+
event_box = create_event_box
|
939
|
+
image = create_icon('face-glasses')
|
940
|
+
event_box.add(image)
|
941
|
+
event_box.on_clicked {
|
942
|
+
do_popup_the_array_of_all_exam_questions
|
943
|
+
}
|
944
|
+
return event_box
|
945
|
+
end
|
946
|
+
|
947
|
+
# ========================================================================= #
|
948
|
+
# === do_assign_a_new_exam_topic
|
949
|
+
# ========================================================================= #
|
950
|
+
def do_assign_a_new_exam_topic
|
951
|
+
clear_reveal_the_answer
|
952
|
+
this_topic = select_not_yet_completed_exam_topics(
|
953
|
+
available_exam_topics?
|
954
|
+
).sample # Obtain a random exam topic here.
|
955
|
+
entry_for_the_current_exam_topic?.set_text(this_topic.to_s)
|
956
|
+
sync_entry_holding_all_exam_topics_onto_the_combo_box
|
957
|
+
do_ask_an_exam_question
|
958
|
+
end
|
959
|
+
|
960
|
+
# ========================================================================= #
|
961
|
+
# === sync_entry_holding_all_exam_topics_onto_the_combo_box
|
962
|
+
# ========================================================================= #
|
963
|
+
def sync_entry_holding_all_exam_topics_onto_the_combo_box(
|
964
|
+
value = Studium.find_corresponding_exam_topic(
|
965
|
+
entry_for_the_current_exam_topic?.text?
|
966
|
+
)
|
967
|
+
)
|
968
|
+
# ======================================================================= #
|
969
|
+
# Next find the correct index:
|
970
|
+
# ======================================================================= #
|
971
|
+
# index = array.find_index {|entry| entry.delete('_').include?(value) }
|
972
|
+
# if index
|
973
|
+
# combo_box_available_exam_topics?.set_active(index)
|
974
|
+
# else
|
975
|
+
# e 'The index was not found. Input was '+steelblue(value)+'.'
|
976
|
+
# end
|
977
|
+
end; alias sync_entry_holding_all_exam_topics_onto_the_main_combo_box sync_entry_holding_all_exam_topics_onto_the_combo_box # === sync_entry_holding_all_exam_topics_onto_the_main_combo_box
|
978
|
+
|
979
|
+
# ========================================================================= #
|
980
|
+
# === return_event_box_for_asking_a_random_exam_topic
|
981
|
+
#
|
982
|
+
# This event-box can be used for asking a question from a random exam
|
983
|
+
# topic.
|
984
|
+
# ========================================================================= #
|
985
|
+
def return_event_box_for_asking_a_random_exam_topic
|
986
|
+
# ======================================================================= #
|
987
|
+
# Next create the actual event box:
|
988
|
+
# ======================================================================= #
|
989
|
+
event_box_for_image_view_refresh_symbolic_symbolic = create_event_box(
|
990
|
+
image_view_refresh_symbolic_symbolic
|
991
|
+
)
|
992
|
+
# ======================================================================= #
|
993
|
+
# Provide useful hints how to use this event-box:
|
994
|
+
# ======================================================================= #
|
995
|
+
event_box_for_image_view_refresh_symbolic_symbolic.hint =
|
996
|
+
'Click on this icon to <span weight="bold" foreground="lightgreen">set a random exam topic</span>, '\
|
997
|
+
"and then ask an exam question from this topic.\n\n"\
|
998
|
+
'Note that since as of <b>August 2022</b> this will ignore '\
|
999
|
+
'exam topics that were already solved.'
|
1000
|
+
# ======================================================================= #
|
1001
|
+
# Let the event-box respond to an on-click event.
|
1002
|
+
# ======================================================================= #
|
1003
|
+
event_box_for_image_view_refresh_symbolic_symbolic.on_clicked {
|
1004
|
+
do_assign_a_new_exam_topic
|
1005
|
+
}
|
1006
|
+
return event_box_for_image_view_refresh_symbolic_symbolic
|
1007
|
+
end
|
1008
|
+
|
1009
|
+
# ========================================================================= #
|
1010
|
+
# === create_the_thumbs_up_emoji
|
1011
|
+
# ========================================================================= #
|
1012
|
+
def create_the_thumbs_up_emoji
|
1013
|
+
# ======================================================================= #
|
1014
|
+
# Add the thumbs-up emoji, but only if we use emojis.
|
1015
|
+
# ======================================================================= #
|
1016
|
+
if use_emoji?
|
1017
|
+
event_box_for_the_thumbs_up_emoji = create_event_box(label(' 👍'))
|
1018
|
+
else
|
1019
|
+
event_box_for_the_thumbs_up_emoji = create_event_box(image_trophy_gold)
|
1020
|
+
end
|
1021
|
+
@thumbs_up_emoji = event_box_for_the_thumbs_up_emoji.on_clicked {
|
1022
|
+
do_ask_a_new_exam_question
|
1023
|
+
}
|
1024
|
+
end
|
1025
|
+
|
1026
|
+
# ========================================================================= #
|
1027
|
+
# === parse_for_URL
|
1028
|
+
#
|
1029
|
+
# This method can be used to return all URLs in a given text.
|
1030
|
+
# ========================================================================= #
|
1031
|
+
def parse_for_URL(
|
1032
|
+
i = text_view_for_the_answer?.buffer.text
|
1033
|
+
)
|
1034
|
+
array = ::Studium.return_all_URLs_from(i)
|
1035
|
+
if array.size > 0
|
1036
|
+
first_entry = array.first
|
1037
|
+
# ===================================================================== #
|
1038
|
+
# We first have to assign it to the GUI part. Note that the "browser"
|
1039
|
+
# is part of the control-panel since the rewrite in January 2021.
|
1040
|
+
# ===================================================================== #
|
1041
|
+
if respond_to?(:control_panel?) and control_panel?.respond_to?(:browser?)
|
1042
|
+
control_panel?.browser?.assign_this_text(first_entry)
|
1043
|
+
end
|
1044
|
+
::Studium.open_this_remote_url(first_entry)
|
1045
|
+
end
|
1046
|
+
end
|
1047
|
+
|
1048
|
+
# ========================================================================= #
|
1049
|
+
# === create_the_widget_for_the_freeform_textview
|
1050
|
+
# ========================================================================= #
|
1051
|
+
def create_the_widget_for_the_freeform_textview
|
1052
|
+
# ======================================================================= #
|
1053
|
+
# === @internal_hash[:textview3]
|
1054
|
+
# ======================================================================= #
|
1055
|
+
_ = create_textview
|
1056
|
+
_.bblack1
|
1057
|
+
_.set_left_right_margin(USE_THIS_MARGIN)
|
1058
|
+
# ======================================================================= #
|
1059
|
+
# The next code sets up a default placeholder text. Upon a focus-in-event
|
1060
|
+
# that default placeholder text is removed.
|
1061
|
+
# ======================================================================= #
|
1062
|
+
_.buffer.set_placeholder_text(
|
1063
|
+
DEFAULT_PLACEHOLDER_TEXT
|
1064
|
+
)
|
1065
|
+
_.buffer.sync_placeholder_text
|
1066
|
+
_.word_wrap
|
1067
|
+
_.focus_in_event {
|
1068
|
+
if _.buffer.text? == DEFAULT_PLACEHOLDER_TEXT
|
1069
|
+
_.buffer.clear # Remove that placeholder text in this case.
|
1070
|
+
end
|
1071
|
+
}
|
1072
|
+
@internal_hash[:textview3] = _
|
1073
|
+
return _
|
1074
|
+
end
|
1075
|
+
|
1076
|
+
# ========================================================================= #
|
1077
|
+
# === create_scrolled_window3
|
1078
|
+
#
|
1079
|
+
# This method will return the textarea-widget that can be used for
|
1080
|
+
# "free typing" by the user - in other words, where the user can
|
1081
|
+
# simply write whatever he/she wants to.
|
1082
|
+
# ========================================================================= #
|
1083
|
+
def create_scrolled_window3(
|
1084
|
+
i = textview3?
|
1085
|
+
)
|
1086
|
+
# ======================================================================= #
|
1087
|
+
# The next scrolled-window is called "textview3", as it is the third
|
1088
|
+
# textarea to be seen in the main widget. The rationale for this
|
1089
|
+
# method was briefly mentioned above.
|
1090
|
+
# ======================================================================= #
|
1091
|
+
_ = create_scrolled_window(i) { :only_top_to_bottom }
|
1092
|
+
_.set_name('textview3')
|
1093
|
+
_.width_height(900, 180)
|
1094
|
+
_.pad4px
|
1095
|
+
_.do_show_the_scrollbars
|
1096
|
+
_.min_content_width = 80
|
1097
|
+
_.min_content_height = 120
|
1098
|
+
# ======================================================================= #
|
1099
|
+
# Next, enable select-all-on-click events:
|
1100
|
+
# ======================================================================= #
|
1101
|
+
_.signal_connect(:event) {|widget, event|
|
1102
|
+
case event.event_type.name.to_s
|
1103
|
+
when 'GDK_BUTTON_PRESS'
|
1104
|
+
# e 'The left mouse-button was clicked! Selecting everything next.'
|
1105
|
+
# @text_view_for_simply_typing_anything.signal_emit(:select_all, event)
|
1106
|
+
i.select_everything(event)
|
1107
|
+
end
|
1108
|
+
}
|
1109
|
+
@scrolled_window3 = _
|
1110
|
+
return _ # And return it here as well, just in case.
|
1111
|
+
end
|
1112
|
+
|
1113
|
+
# ========================================================================= #
|
1114
|
+
# === scrolled_window3?
|
1115
|
+
# ========================================================================= #
|
1116
|
+
def scrolled_window3?
|
1117
|
+
@scrolled_window3
|
1118
|
+
end; alias scrolled_window_containing_the_textarea3 scrolled_window3? # === scrolled_window_containing_the_textarea3
|
1119
|
+
alias return_scrolled_window3 scrolled_window3? # === scrolled_window_containing_the_textarea3
|
1120
|
+
alias return_scrolled_window_containing_the_textarea3 scrolled_window3? # === return_scrolled_window_containing_the_textarea3
|
1121
|
+
alias return_widget_for_the_freeform_textview scrolled_window3? # === return_widget_for_the_freeform_textview
|
1122
|
+
|
1123
|
+
# ========================================================================= #
|
1124
|
+
# === button_clear_was_clicked
|
1125
|
+
# ========================================================================= #
|
1126
|
+
def button_clear_was_clicked
|
1127
|
+
all_textviews?.each {|entry|
|
1128
|
+
entry.clear
|
1129
|
+
}
|
1130
|
+
@internal_hash[:may_we_reveal_the_answer_after_a_delay] = false
|
1131
|
+
end
|
1132
|
+
|
1133
|
+
# ========================================================================= #
|
1134
|
+
# === notify_the_user_that_all_questions_have_been_answered_in_this_topic
|
1135
|
+
# ========================================================================= #
|
1136
|
+
def notify_the_user_that_all_questions_have_been_answered_in_this_topic(
|
1137
|
+
this_topic = current_exam_topic?,
|
1138
|
+
this_widget = button_reveal_the_answer?
|
1139
|
+
)
|
1140
|
+
bold_popover_message = create_bold_label(
|
1141
|
+
'All questions have been answered for '+this_topic+'. \o/'
|
1142
|
+
)
|
1143
|
+
popover_message(
|
1144
|
+
bold_popover_message,
|
1145
|
+
this_widget
|
1146
|
+
).popup
|
1147
|
+
end
|
1148
|
+
|
1149
|
+
# ========================================================================= #
|
1150
|
+
# === create_the_entry_n_unanswered_questions
|
1151
|
+
# ========================================================================= #
|
1152
|
+
def create_the_entry_n_unanswered_questions
|
1153
|
+
# ======================================================================= #
|
1154
|
+
# === @entry_n_unanswered_questions
|
1155
|
+
# ======================================================================= #
|
1156
|
+
@entry_n_unanswered_questions = create_entry
|
1157
|
+
enhance_entry_containing_n_unanswered_questions(
|
1158
|
+
:default_font,
|
1159
|
+
@entry_n_unanswered_questions
|
1160
|
+
)
|
1161
|
+
end; alias create_the_entry_containing_n_unanswered_questions create_the_entry_n_unanswered_questions # === create_the_entry_containing_n_unanswered_questions
|
1162
|
+
alias create_the_entry_containing_n_unanswered_exam_questions create_the_entry_n_unanswered_questions # === create_the_entry_containing_n_unanswered_exam_questions
|
1163
|
+
|
1164
|
+
# ========================================================================= #
|
1165
|
+
# === entry_n_answered_exam_questions?
|
1166
|
+
# ========================================================================= #
|
1167
|
+
def entry_n_answered_exam_questions?
|
1168
|
+
@internal_hash[:entry_n_answered_exam_questions]
|
1169
|
+
end; alias entry_containing_n_answers? entry_n_answered_exam_questions? # === entry_containing_n_answers?
|
1170
|
+
|
1171
|
+
# ========================================================================= #
|
1172
|
+
# === create_the_entry_for_sleeping_n_seconds
|
1173
|
+
# ========================================================================= #
|
1174
|
+
def create_the_entry_for_sleeping_n_seconds
|
1175
|
+
# ======================================================================= #
|
1176
|
+
# === :entry_for_sleeping_n_seconds
|
1177
|
+
#
|
1178
|
+
# Next create the delay-entry that keeps track how many seconds to wait,
|
1179
|
+
# before revealing the answer (IF the user has decided to make use of
|
1180
|
+
# that functionality).
|
1181
|
+
# ======================================================================= #
|
1182
|
+
_ = entry('', 5) # entry('', 5) is primarily for jruby.
|
1183
|
+
_ << default_delay?.to_s.dup # Default delay.
|
1184
|
+
@internal_hash[:entry_for_sleeping_n_seconds] = _
|
1185
|
+
enhance_the_entry_for_sleeping_n_seconds
|
1186
|
+
return @internal_hash[:entry_for_sleeping_n_seconds]
|
1187
|
+
end
|
1188
|
+
|
1189
|
+
# ========================================================================= #
|
1190
|
+
# === entry_percentage?
|
1191
|
+
# ========================================================================= #
|
1192
|
+
def entry_percentage?
|
1193
|
+
@internal_hash[:entry_percentage]
|
1194
|
+
end; alias return_entry_percentage entry_percentage? # === return_entry_percentage
|
1195
|
+
|
1196
|
+
# ========================================================================= #
|
1197
|
+
# === return_hbox_containing_two_icons_and_instructions_what_to_do_with_the_free_form_textarea
|
1198
|
+
#
|
1199
|
+
# This widget returned by this method here, should come before the
|
1200
|
+
# free-form widget is added.
|
1201
|
+
# ========================================================================= #
|
1202
|
+
def return_hbox_containing_two_icons_and_instructions_what_to_do_with_the_free_form_textarea
|
1203
|
+
hbox_with_two_icons = create_hbox
|
1204
|
+
first_eventbox = create_event_box(image_accessories_text_editor)
|
1205
|
+
first_eventbox.on_clicked {
|
1206
|
+
do_clear_the_free_form_textarea
|
1207
|
+
}
|
1208
|
+
hbox_with_two_icons.minimal(first_eventbox, 2)
|
1209
|
+
text = text(
|
1210
|
+
'Below this text you can input your assumed '\
|
1211
|
+
'answer to the exam question at hand.'
|
1212
|
+
)
|
1213
|
+
text.left_align
|
1214
|
+
text.make_selectable
|
1215
|
+
text.set_font(:hack_18)
|
1216
|
+
hbox_with_two_icons.maximal(text, 4)
|
1217
|
+
event_box_for_image_accessories_text_editor = create_event_box(image_accessories_text_editor)
|
1218
|
+
event_box_for_image_accessories_text_editor.hint =
|
1219
|
+
'Click here to empty the free-form textarea below this icon.'
|
1220
|
+
event_box_for_image_accessories_text_editor.on_clicked {
|
1221
|
+
do_clear_the_free_form_textarea
|
1222
|
+
}
|
1223
|
+
hbox_with_two_icons.minimal(event_box_for_image_accessories_text_editor, 2)
|
1224
|
+
return hbox_with_two_icons
|
1225
|
+
end
|
1226
|
+
|
1227
|
+
# ========================================================================= #
|
1228
|
+
# === create_entry_n_total_exam_questions
|
1229
|
+
# ========================================================================= #
|
1230
|
+
def create_entry_n_total_exam_questions
|
1231
|
+
# ======================================================================= #
|
1232
|
+
# === @entry_n_total_exam_questions
|
1233
|
+
# ======================================================================= #
|
1234
|
+
@internal_hash[:entry_n_total_exam_questions] = entry('', 12) # The 12 is for jruby specifically.
|
1235
|
+
enhance_the_entry_containing_n_questions
|
1236
|
+
return @internal_hash[:entry_n_total_exam_questions]
|
1237
|
+
end; alias create_the_entry_containing_n_questions create_entry_n_total_exam_questions # === create_the_entry_containing_n_questions
|
1238
|
+
|
1239
|
+
# ========================================================================= #
|
1240
|
+
# === do_style_all_buttons_uniformly (style tag)
|
1241
|
+
# ========================================================================= #
|
1242
|
+
def do_style_all_buttons_uniformly(
|
1243
|
+
i = return_all_buttons
|
1244
|
+
)
|
1245
|
+
# ======================================================================= #
|
1246
|
+
# Style all buttons uniformly next, via CSS.
|
1247
|
+
# ======================================================================= #
|
1248
|
+
i.each {|this_button|
|
1249
|
+
# ===================================================================== #
|
1250
|
+
# Use the same CSS rule for each button.
|
1251
|
+
# ===================================================================== #
|
1252
|
+
this_button.clear_background
|
1253
|
+
this_button.bblack2
|
1254
|
+
this_button.set_size_request(75, 28)
|
1255
|
+
this_button.set_name('button_hover_transition')
|
1256
|
+
}
|
1257
|
+
end
|
1258
|
+
|
1259
|
+
# ========================================================================= #
|
1260
|
+
# === all_questions_have_been_answered_in_this_topic?
|
1261
|
+
#
|
1262
|
+
# This method has to determine how many questions have been answered
|
1263
|
+
# in the current exam topic.
|
1264
|
+
# ========================================================================= #
|
1265
|
+
def all_questions_have_been_answered_in_this_topic?(
|
1266
|
+
this_topic = current_exam_topic?
|
1267
|
+
)
|
1268
|
+
(Studium.return_n_percent_solved_from_this_topic(this_topic).to_i == 100)
|
1269
|
+
end
|
1270
|
+
|
1271
|
+
# ========================================================================= #
|
1272
|
+
# === textview1?
|
1273
|
+
# ========================================================================= #
|
1274
|
+
def textview1?
|
1275
|
+
@internal_hash[:textview1]
|
1276
|
+
end; alias widget_for_the_questions? textview1? # === widget_for_the_questions?
|
1277
|
+
alias text_view_for_the_question? textview1? # === text_view_for_the_question?
|
1278
|
+
alias return_widget_for_the_questions textview1? # === return_widget_for_the_questions
|
1279
|
+
alias return_text_view_for_the_question textview1? # === return_text_view_for_the_question
|
1280
|
+
alias return_scrolled_window_for_the_text_view_for_the_question textview1? # === return_scrolled_window_for_the_text_view_for_the_question
|
1281
|
+
alias text_view_containing_the_current_question? textview1? # === text_view_containing_the_current_question?
|
1282
|
+
alias text_buffer_for_the_question? textview1? # === text_buffer_for_the_question?
|
1283
|
+
alias textarea1? textview1? # === textare1?
|
1284
|
+
alias question_buffer textview1? # === question_buffer
|
1285
|
+
alias question_buffer? textview1? # === question_buffer?
|
1286
|
+
|
1287
|
+
# ========================================================================= #
|
1288
|
+
# === create_the_textview_that_will_contain_the_exam_question
|
1289
|
+
# ========================================================================= #
|
1290
|
+
def create_the_textview_that_will_contain_the_exam_question(
|
1291
|
+
text_buffer_for_the_question = :default_buffer
|
1292
|
+
)
|
1293
|
+
# ======================================================================= #
|
1294
|
+
# === @internal_hash[:textview1]
|
1295
|
+
# ======================================================================= #
|
1296
|
+
_ = create_textview(text_buffer_for_the_question)
|
1297
|
+
_.set_left_right_margin(USE_THIS_MARGIN)
|
1298
|
+
_.word_wrap
|
1299
|
+
scrolled_window_containing_the_textarea1 = create_scrolled_window(
|
1300
|
+
_
|
1301
|
+
) { :only_up_and_bottom }
|
1302
|
+
scrolled_window_containing_the_textarea1.set_name('textview1_for_the_studium_gem') # Contains the question.
|
1303
|
+
scrolled_window_containing_the_textarea1.set_size_request(920, 180)
|
1304
|
+
@internal_hash[:textview1] = _
|
1305
|
+
@internal_hash[:scrolled_window_containing_the_textarea1] = scrolled_window_containing_the_textarea1
|
1306
|
+
end
|
1307
|
+
|
1308
|
+
# ========================================================================= #
|
1309
|
+
# === hash_dataset_of_all_lectures?
|
1310
|
+
# ========================================================================= #
|
1311
|
+
def hash_dataset_of_all_lectures?
|
1312
|
+
@internal_hash[:hash_dataset_of_all_lectures]
|
1313
|
+
end
|
1314
|
+
|
1315
|
+
# ======================================================================= #
|
1316
|
+
# === do_assign_the_default_exam_topic_to_the_correct_entry
|
1317
|
+
# ======================================================================= #
|
1318
|
+
def do_assign_the_default_exam_topic_to_the_correct_entry
|
1319
|
+
set_exam_topic(USE_THIS_AS_THE_DEFAULT_EXAM_TOPIC)
|
1320
|
+
end
|
1321
|
+
|
1322
|
+
# ========================================================================= #
|
1323
|
+
# === deselect_the_entry_containing_the_exam_topic
|
1324
|
+
# ========================================================================= #
|
1325
|
+
def deselect_the_entry_containing_the_exam_topic(
|
1326
|
+
i = entry_for_the_current_exam_topic?
|
1327
|
+
)
|
1328
|
+
i.deselect
|
1329
|
+
text_view_containing_the_current_question?.set_focus(true)
|
1330
|
+
end
|
1331
|
+
|
1332
|
+
# ========================================================================= #
|
1333
|
+
# === scrolled_window1?
|
1334
|
+
# ========================================================================= #
|
1335
|
+
def scrolled_window1?
|
1336
|
+
@internal_hash[:scrolled_window_containing_the_textarea1]
|
1337
|
+
end
|
1338
|
+
|
1339
|
+
# ========================================================================= #
|
1340
|
+
# === create_the_textviews
|
1341
|
+
# ========================================================================= #
|
1342
|
+
def create_the_textviews
|
1343
|
+
create_the_textview_that_will_contain_the_exam_question
|
1344
|
+
# ======================================================================= #
|
1345
|
+
# === @internal_hash[:textview2]
|
1346
|
+
# ======================================================================= #
|
1347
|
+
create_the_widget_for_the_exam_answer
|
1348
|
+
# ======================================================================= #
|
1349
|
+
# === @internal_hash[:textview3]
|
1350
|
+
# ======================================================================= #
|
1351
|
+
create_the_widget_for_the_freeform_textview
|
1352
|
+
create_scrolled_window3 # And create the scrolled-window3 here as well.
|
1353
|
+
end
|
1354
|
+
|
1355
|
+
# ========================================================================= #
|
1356
|
+
# === create_the_widget_for_the_exam_answer (answer tag, answers tags)
|
1357
|
+
# ========================================================================= #
|
1358
|
+
def create_the_widget_for_the_exam_answer(
|
1359
|
+
use_this_text_buffer = @text_buffer_for_the_answer
|
1360
|
+
)
|
1361
|
+
_ = create_textview(use_this_text_buffer)
|
1362
|
+
_.set_left_right_margin(USE_THIS_MARGIN)
|
1363
|
+
_.word_wrap
|
1364
|
+
@internal_hash[:textview2] = _
|
1365
|
+
scrolled_window = create_scrolled_window(
|
1366
|
+
_
|
1367
|
+
) { :only_up_and_bottom }
|
1368
|
+
scrolled_window.set_name('textview2_for_the_studium_gem') # Contains the answer.
|
1369
|
+
scrolled_window.set_size_request(1000, 150)
|
1370
|
+
scrolled_window.min_content_width = 100
|
1371
|
+
scrolled_window.min_content_height = 200
|
1372
|
+
scrolled_window.do_show_the_scrollbars
|
1373
|
+
@scrolled_window_containing_the_textarea2 = scrolled_window
|
1374
|
+
return _ # And return it too, just in case.
|
1375
|
+
end; alias create_text_view_for_the_answer create_the_widget_for_the_exam_answer # === create_text_view_for_the_answer
|
1376
|
+
|
1377
|
+
# ========================================================================= #
|
1378
|
+
# === create_the_button_solve_the_question
|
1379
|
+
# ========================================================================= #
|
1380
|
+
def create_the_button_solve_the_question
|
1381
|
+
# ======================================================================= #
|
1382
|
+
# === @button_solve_the_question
|
1383
|
+
# ======================================================================= #
|
1384
|
+
@button_solve_the_exam_question = return_button_solve_the_question
|
1385
|
+
end
|
1386
|
+
|
1387
|
+
# ========================================================================= #
|
1388
|
+
# === button_ask_the_exam_question?
|
1389
|
+
# ========================================================================= #
|
1390
|
+
def button_ask_the_exam_question?
|
1391
|
+
@internal_hash[:button_ask_the_exam_question]
|
1392
|
+
end; alias question_button? button_ask_the_exam_question? # === question_button?
|
1393
|
+
alias button_ask_the_question? button_ask_the_exam_question? # === button_ask_the_question?
|
1394
|
+
|
1395
|
+
# ========================================================================= #
|
1396
|
+
# === create_the_button_ask_the_exam_question
|
1397
|
+
# ========================================================================= #
|
1398
|
+
def create_the_button_ask_the_exam_question
|
1399
|
+
# ======================================================================= #
|
1400
|
+
# === @internal_hash[:button_ask_the_exam_question]
|
1401
|
+
# ======================================================================= #
|
1402
|
+
@internal_hash[:button_ask_the_exam_question] = return_button_ask_the_exam_question(use_emoji?)
|
1403
|
+
end; alias create_the_ask_the_exam_question_button create_the_button_ask_the_exam_question # === create_the_ask_the_exam_question_button
|
1404
|
+
|
1405
|
+
# ========================================================================= #
|
1406
|
+
# === set_exam_question
|
1407
|
+
#
|
1408
|
+
# The second argument can be a filter. For instance, if the Symbol
|
1409
|
+
# :remove_tags is passed, then all HTML tags will be removed from
|
1410
|
+
# the given input at hand. This is actually the default behaviour.
|
1411
|
+
# ========================================================================= #
|
1412
|
+
def set_exam_question(
|
1413
|
+
i = exam_question_object?.question?,
|
1414
|
+
apply_these_filters = [:remove_tags]
|
1415
|
+
)
|
1416
|
+
i = i.to_s.dup
|
1417
|
+
i[0,2] = '' if i.start_with?('- ') # We don't ever want leading '-' here.
|
1418
|
+
if apply_these_filters.is_a? Symbol
|
1419
|
+
apply_these_filters = [apply_these_filters]
|
1420
|
+
end
|
1421
|
+
# ======================================================================= #
|
1422
|
+
# Replace all URL entries with <a href> entries next:
|
1423
|
+
# ======================================================================= #
|
1424
|
+
if i
|
1425
|
+
i = ::Gtk.replace_all_URL_entries_in_this_string(i)
|
1426
|
+
end
|
1427
|
+
# ======================================================================= #
|
1428
|
+
# The following line may have to be re-evaluated again in the future -
|
1429
|
+
# in the past, in 2021, this had a bug and things crashed, but this
|
1430
|
+
# may no longer be the case - let's see, eventually.
|
1431
|
+
#
|
1432
|
+
# editor?.update_the_main_buffer(dataset)
|
1433
|
+
#
|
1434
|
+
# ======================================================================= #
|
1435
|
+
if apply_these_filters and !apply_these_filters.empty?
|
1436
|
+
apply_these_filters.each {|this_filter|
|
1437
|
+
case this_filter
|
1438
|
+
# =================================================================== #
|
1439
|
+
# === :remove_tags
|
1440
|
+
# =================================================================== #
|
1441
|
+
when :remove_tags,
|
1442
|
+
:no_tags,
|
1443
|
+
:default
|
1444
|
+
i = Studium.remove_tags_from_this_input(i)
|
1445
|
+
end
|
1446
|
+
}
|
1447
|
+
end
|
1448
|
+
@internal_hash[:exam_question] = i
|
1449
|
+
textview1?.set_text(i) # This is the widget for the exam-questions.
|
1450
|
+
end; alias set_question set_exam_question # === set_question
|
1451
|
+
|
1452
|
+
# ========================================================================= #
|
1453
|
+
# === create_the_emoji_toggle_widget
|
1454
|
+
#
|
1455
|
+
# Note that in order to use EmojiToggleWidget, we have to pull in the
|
1456
|
+
# right file, either ruby-gtk3 or ruby-gtk2.
|
1457
|
+
# ========================================================================= #
|
1458
|
+
def create_the_emoji_toggle_widget
|
1459
|
+
require 'gtk_paradise/widgets/gtk3/emoji_toggle_widget/emoji_toggle_widget.rb'
|
1460
|
+
@a_thinking_smiley_emoji = ::Gtk::EmojiToggleWidget.new(
|
1461
|
+
:use_two_smileys
|
1462
|
+
)
|
1463
|
+
@a_thinking_smiley_emoji.make_selectable
|
1464
|
+
end
|
1465
|
+
|
1466
|
+
# ========================================================================= #
|
1467
|
+
# === return_n_questions_from_the_currently_selected_topic
|
1468
|
+
#
|
1469
|
+
# This method will return how many exam questions exist in the
|
1470
|
+
# selected exam topic.
|
1471
|
+
#
|
1472
|
+
# This method is no longer that important as of December 2023.
|
1473
|
+
# ========================================================================= #
|
1474
|
+
def return_n_questions_from_the_currently_selected_topic(
|
1475
|
+
i = current_exam_topic?
|
1476
|
+
)
|
1477
|
+
::Studium.n_questions_available_in_this_topic(i)
|
1478
|
+
end
|
1479
|
+
|
1480
|
+
# ========================================================================= #
|
1481
|
+
# === do_clear_the_free_form_textarea
|
1482
|
+
# ========================================================================= #
|
1483
|
+
def do_clear_the_free_form_textarea
|
1484
|
+
free_form_textarea?.set_text('')
|
1485
|
+
end
|
1486
|
+
|
1487
|
+
# ========================================================================= #
|
1488
|
+
# === create_the_buttons (buttons tag, button tag)
|
1489
|
+
# ========================================================================= #
|
1490
|
+
def create_the_buttons
|
1491
|
+
create_the_button_ask_the_exam_question
|
1492
|
+
# ======================================================================= #
|
1493
|
+
# === @button_solve_the_exam_question
|
1494
|
+
# ======================================================================= #
|
1495
|
+
create_the_button_solve_the_question
|
1496
|
+
# ======================================================================= #
|
1497
|
+
# === @button_clear
|
1498
|
+
# ======================================================================= #
|
1499
|
+
@button_clear = bold_button('_Clear all entries', self, :use_mnemonic) {
|
1500
|
+
:button_clear_was_clicked
|
1501
|
+
}
|
1502
|
+
create_the_button_update_n_questions_were_answered
|
1503
|
+
create_the_reveal_the_answer_button
|
1504
|
+
# ======================================================================= #
|
1505
|
+
# Next style these four buttons uniformly
|
1506
|
+
# ======================================================================= #
|
1507
|
+
[
|
1508
|
+
button_ask_the_exam_question?,
|
1509
|
+
button_reveal_the_answer?,
|
1510
|
+
button_solve_the_exam_question?,
|
1511
|
+
@button_clear,
|
1512
|
+
button_update_n_questions_were_answered?
|
1513
|
+
].each {|this_button|
|
1514
|
+
this_button.clear_background
|
1515
|
+
this_button.bblack2
|
1516
|
+
this_button.on_hover(:lightgreen)
|
1517
|
+
}
|
1518
|
+
create_the_button_use_random_entry_from_the_ten_aliases # This one should come last here.
|
1519
|
+
end
|
1520
|
+
|
1521
|
+
# ========================================================================= #
|
1522
|
+
# === create_the_editor (editor tag)
|
1523
|
+
#
|
1524
|
+
# This method only makes sense for ruby-gtk3.
|
1525
|
+
# ========================================================================= #
|
1526
|
+
def create_the_editor
|
1527
|
+
if shall_we_create_the_gtk_editor?
|
1528
|
+
require 'gtk_paradise/widgets/gtk3/editor/editor.rb'
|
1529
|
+
# ===================================================================== #
|
1530
|
+
# === @editor
|
1531
|
+
# ===================================================================== #
|
1532
|
+
@editor = ::Gtk::Editor.new { :do_not_use_the_colour_box_widget }
|
1533
|
+
else
|
1534
|
+
@editor = nil
|
1535
|
+
end
|
1536
|
+
end
|
1537
|
+
|
1538
|
+
# ========================================================================= #
|
1539
|
+
# === add_the_status_icon
|
1540
|
+
# ========================================================================= #
|
1541
|
+
def add_the_status_icon
|
1542
|
+
if use_gtk3?
|
1543
|
+
status_icon = return_status_icon
|
1544
|
+
status_icon.favicon = Studium.project_base_directory?+
|
1545
|
+
'images/studies_favicon.png'
|
1546
|
+
status_icon.hint = 'Exam-question widget: train your brain!'
|
1547
|
+
begin # Need to fix this later.
|
1548
|
+
menu = create_menu
|
1549
|
+
button_hello_world = create_image_menu_item(stock: ::Gtk::Stock::FIND)
|
1550
|
+
button_hello_world.signal_connect(:activate) {
|
1551
|
+
e 'A click-event has been detected.'
|
1552
|
+
}
|
1553
|
+
menu << button_hello_world
|
1554
|
+
quit_button = create_image_menu_item(stock: ::Gtk::Stock::QUIT)
|
1555
|
+
quit_button.signal_connect(:activate) { ::Gtk.main_quit }
|
1556
|
+
menu.append(quit_button)
|
1557
|
+
menu.show_all
|
1558
|
+
status_icon.signal_connect(:popup_menu) { |icon, button, time|
|
1559
|
+
menu.popup(nil, nil, button, time)
|
1560
|
+
}
|
1561
|
+
rescue Exception => error
|
1562
|
+
pp error
|
1563
|
+
end
|
1564
|
+
end
|
1565
|
+
end
|
1566
|
+
|
1567
|
+
# ========================================================================= #
|
1568
|
+
# === allow_external_applications?
|
1569
|
+
#
|
1570
|
+
# This is mostly useful when the main application allows add-ons, such
|
1571
|
+
# as the TenAliases widget. It is not so important for standalone
|
1572
|
+
# widgets.
|
1573
|
+
# ========================================================================= #
|
1574
|
+
def allow_external_applications?
|
1575
|
+
true
|
1576
|
+
end
|
1577
|
+
|
1578
|
+
# ========================================================================= #
|
1579
|
+
# === available_exam_topics_in_short_form?
|
1580
|
+
# ========================================================================= #
|
1581
|
+
def available_exam_topics_in_short_form?
|
1582
|
+
array = Studium.available_exam_topics_in_short_form?
|
1583
|
+
array = array.sort_by {|entry| entry.downcase }
|
1584
|
+
return array
|
1585
|
+
end; alias return_available_exam_topics available_exam_topics_in_short_form? # === return_available_exam_topics
|
1586
|
+
alias available_exam_topics? available_exam_topics_in_short_form? # === available_exam_topics?
|
1587
|
+
alias exam_topics_short_form? available_exam_topics_in_short_form? # === exam_topics_short_form?
|
1588
|
+
|
1589
|
+
# ========================================================================= #
|
1590
|
+
# === enable_all_key_combinations
|
1591
|
+
# ========================================================================= #
|
1592
|
+
def enable_all_key_combinations
|
1593
|
+
# ======================================================================= #
|
1594
|
+
# === @accel_group
|
1595
|
+
# ======================================================================= #
|
1596
|
+
@accel_group = create_and_add_gtk_accel_group
|
1597
|
+
enable_alt_w_key_combination
|
1598
|
+
enable_alt_y_key_combination
|
1599
|
+
enable_alt_1_key_combination
|
1600
|
+
end
|
1601
|
+
|
1602
|
+
# ========================================================================= #
|
1603
|
+
# === return_frame_containing_the_label_exam_topic
|
1604
|
+
# ========================================================================= #
|
1605
|
+
def return_frame_containing_the_label_exam_topic
|
1606
|
+
# ======================================================================= #
|
1607
|
+
# Create the exam-topic label next, showing a watermelon emoji on the
|
1608
|
+
# left-hand side. The watermelon emoji used to be 🍉️; but it was
|
1609
|
+
# replaced with the electric light bulb emoji in January 2021, which
|
1610
|
+
# is 💡️. Unfortunately this does not work on every system, so it
|
1611
|
+
# was decided to replace this with an image that is determined by
|
1612
|
+
# the icon theme at hand.
|
1613
|
+
# ======================================================================= #
|
1614
|
+
label_exam_topic = bold_text(' Exam topic ')
|
1615
|
+
label_emoji = right_arrow_emoji
|
1616
|
+
label_emoji.set_size_request(22, 22)
|
1617
|
+
label_emoji.align_right
|
1618
|
+
event_box_for_the_label_emoji = create_event_box(label_emoji)
|
1619
|
+
event_box_for_the_label_emoji.on_clicked {
|
1620
|
+
do_jump_into_the_entry_containing_the_current_exam_topic
|
1621
|
+
}
|
1622
|
+
tiny_hbox = create_hbox
|
1623
|
+
tiny_hbox.minimal(label_exam_topic)
|
1624
|
+
tiny_hbox.maximal(event_box_for_the_label_emoji)
|
1625
|
+
tiny_hbox.minimal(text(' ')) # Just a "spacer".
|
1626
|
+
frame_containing_the_label_exam_topic = create_frame(tiny_hbox)
|
1627
|
+
frame_containing_the_label_exam_topic.modify_background(:normal, :oldlace)
|
1628
|
+
frame_containing_the_label_exam_topic.bblack1
|
1629
|
+
# frame_containing_the_label_exam_topic.set_font(smaller_font?)
|
1630
|
+
label_exam_topic.hint = 'Denote <b>the current exam </b> topic '\
|
1631
|
+
'to the <b>right</b> of this text.'
|
1632
|
+
return frame_containing_the_label_exam_topic
|
1633
|
+
end
|
1634
|
+
|
1635
|
+
# ========================================================================= #
|
1636
|
+
# === entry_n_total_exam_questions?
|
1637
|
+
# ========================================================================= #
|
1638
|
+
def entry_n_total_exam_questions?
|
1639
|
+
@internal_hash[:entry_n_total_exam_questions]
|
1640
|
+
end; alias entry_containing_n_questions? entry_n_total_exam_questions? # === entry_containing_n_questions?
|
1641
|
+
|
1642
|
+
# ========================================================================= #
|
1643
|
+
# === Studium::GUI::UniversalWidgets::ExamTrainer.gtk_accel_group
|
1644
|
+
# ========================================================================= #
|
1645
|
+
def self.gtk_accel_group
|
1646
|
+
::Gtk::AccelGroup.new
|
1647
|
+
end
|
1648
|
+
|
1649
|
+
# ========================================================================= #
|
1650
|
+
# === button_clear?
|
1651
|
+
# ========================================================================= #
|
1652
|
+
def button_clear?
|
1653
|
+
@button_clear
|
1654
|
+
end
|
1655
|
+
|
1656
|
+
# ========================================================================= #
|
1657
|
+
# === parse_the_commandline_arguments
|
1658
|
+
# ========================================================================= #
|
1659
|
+
def parse_the_commandline_arguments
|
1660
|
+
_ = commandline_arguments?
|
1661
|
+
unless _.empty?
|
1662
|
+
new_topic = _.first
|
1663
|
+
# ===================================================================== #
|
1664
|
+
# === Handle numbers given as input here:
|
1665
|
+
#
|
1666
|
+
# Example:
|
1667
|
+
#
|
1668
|
+
# ruby misc.rb 5
|
1669
|
+
#
|
1670
|
+
# ===================================================================== #
|
1671
|
+
if new_topic =~ /^\d+$/ # A number - and only a number - was given to this class here.
|
1672
|
+
new_topic = new_topic.to_i
|
1673
|
+
new_topic = Studium.exam_topic_number?(new_topic).to_s
|
1674
|
+
end
|
1675
|
+
new_topic = Studium.find_corresponding_exam_topic(new_topic)
|
1676
|
+
entry_for_the_current_exam_topic?.set_text(new_topic)
|
1677
|
+
# ===================================================================== #
|
1678
|
+
# Next, we must also update the combo-box.
|
1679
|
+
# This is currently not enabled:
|
1680
|
+
# _.find_and_try_to_select_this_entry(new_topic)
|
1681
|
+
# simply_assign_this_as_the_new_exam_topic_onto_the_primary_combobox(new_topic)
|
1682
|
+
# ===================================================================== #
|
1683
|
+
one_two_three
|
1684
|
+
end
|
1685
|
+
end
|
1686
|
+
|
1687
|
+
# ========================================================================= #
|
1688
|
+
# === entry_n_unanswered_questions?
|
1689
|
+
# ========================================================================= #
|
1690
|
+
def entry_n_unanswered_questions?
|
1691
|
+
@entry_n_unanswered_questions
|
1692
|
+
end; alias entry_containing_n_unanswered_questions? entry_n_unanswered_questions? # === entry_containing_n_unanswered_questions?
|
1693
|
+
alias entry_containing_n_unanswered_questions entry_n_unanswered_questions? # === entry_containing_n_unanswered_questions
|
1694
|
+
|
1695
|
+
# ========================================================================= #
|
1696
|
+
# === button_solve_the_exam_question?
|
1697
|
+
# ========================================================================= #
|
1698
|
+
def button_solve_the_exam_question?
|
1699
|
+
@button_solve_the_exam_question
|
1700
|
+
end
|
1701
|
+
|
1702
|
+
# ========================================================================= #
|
1703
|
+
# === button_solve_the_exam_question_was_clicked (solved tag, solve tag)
|
1704
|
+
# ========================================================================= #
|
1705
|
+
def button_solve_the_exam_question_was_clicked
|
1706
|
+
# the_current_exam_question_is_now_solved
|
1707
|
+
# update_three_important_widgets
|
1708
|
+
_ = Studium::Exams::Solved.new(ARGV) { :do_not_run_yet }
|
1709
|
+
_.set_commandline
|
1710
|
+
_.run
|
1711
|
+
consider_running_rinstall2
|
1712
|
+
# ======================================================================= #
|
1713
|
+
# Also update the appropriate label next, whenever the solve-exam
|
1714
|
+
# question was clicked.
|
1715
|
+
# ======================================================================= #
|
1716
|
+
update_the_label_n_questions_were_answered
|
1717
|
+
end; alias mark_the_exam_question_as_solved button_solve_the_exam_question_was_clicked # === mark_the_exam_question_as_solved
|
1718
|
+
alias do_solve_the_exam_question button_solve_the_exam_question_was_clicked # === do_solve_the_exam_question
|
1719
|
+
alias the_current_exam_question_is_now_solved button_solve_the_exam_question_was_clicked # === the_current_exam_question_is_now_solved
|
1720
|
+
|
1721
|
+
# ========================================================================= #
|
1722
|
+
# === activate_the_third_textview
|
1723
|
+
# ========================================================================= #
|
1724
|
+
def activate_the_third_textview
|
1725
|
+
free_form_textarea?.do_focus_on_it
|
1726
|
+
end
|
1727
|
+
|
1728
|
+
# ========================================================================= #
|
1729
|
+
# === change_to_a_happy_smiley_before_reverting_to_the_prior_default_again
|
1730
|
+
#
|
1731
|
+
# This method is used to turn the thinking-smiley to a happy-smiley,
|
1732
|
+
# before reverting again to the prior default.
|
1733
|
+
# ========================================================================= #
|
1734
|
+
def change_to_a_happy_smiley_before_reverting_to_the_prior_default_again(
|
1735
|
+
delay_to_use = 5_000 # This refers to 5 seconds.
|
1736
|
+
)
|
1737
|
+
@a_thinking_smiley_emoji.toggle
|
1738
|
+
GLib::Timeout.add(delay_to_use) {
|
1739
|
+
@a_thinking_smiley_emoji.revert_to_the_initial_state # This reverts to the initial state again.
|
1740
|
+
false # Must end it.
|
1741
|
+
}
|
1742
|
+
end
|
1743
|
+
|
1744
|
+
# ======================================================================= #
|
1745
|
+
# === create_the_combobox
|
1746
|
+
#
|
1747
|
+
# This method will create the combo-box that contains all exam-topics.
|
1748
|
+
# It will be a bit truncated, largely for display-reasons rather
|
1749
|
+
# than any other reason.
|
1750
|
+
# ======================================================================= #
|
1751
|
+
def create_the_combobox(
|
1752
|
+
use_these_exam_topics = :default_exam_topics
|
1753
|
+
)
|
1754
|
+
case use_these_exam_topics
|
1755
|
+
# ===================================================================== #
|
1756
|
+
# === :default_exam_topics
|
1757
|
+
# ===================================================================== #
|
1758
|
+
when :default_exam_topics
|
1759
|
+
use_these_exam_topics = available_exam_topics_in_short_form?.
|
1760
|
+
map(&:downcase).sort
|
1761
|
+
end
|
1762
|
+
# ===================================================================== #
|
1763
|
+
# Next truncate these exam-topics a bit:
|
1764
|
+
# ===================================================================== #
|
1765
|
+
use_this_sorted_array = use_these_exam_topics.uniq.map {|entry|
|
1766
|
+
if entry.size > 25 # Truncate it a bit in this case here.
|
1767
|
+
entry = entry[0 .. 25]
|
1768
|
+
end
|
1769
|
+
entry
|
1770
|
+
}.sort
|
1771
|
+
_ = create_combobox_text # Create the combo-box here.
|
1772
|
+
# use_this_sorted_array.each {|entry|
|
1773
|
+
# entry = entry.to_s
|
1774
|
+
# _.append_text(entry) if entry and !entry.empty?
|
1775
|
+
# }
|
1776
|
+
_.fill_up(use_this_sorted_array)
|
1777
|
+
_.first_entry_is_active
|
1778
|
+
_.bblack1
|
1779
|
+
_.set_size_request(100, 28)
|
1780
|
+
# ======================================================================= #
|
1781
|
+
# Wrap-width determines how many entries per row are shown when the
|
1782
|
+
# combo-box is expanded. We stick to the default of 1 here.
|
1783
|
+
# ======================================================================= #
|
1784
|
+
_.set_wrap_width(1)
|
1785
|
+
# ======================================================================= #
|
1786
|
+
# The event where the combo-box is changed is handled next.
|
1787
|
+
# ======================================================================= #
|
1788
|
+
_.on_changed {
|
1789
|
+
handle_the_combo_box_available_exam_topics_on_changed_event
|
1790
|
+
}
|
1791
|
+
@internal_hash[:combobox_available_exam_topics] = _ # And assign it here.
|
1792
|
+
return _
|
1793
|
+
end
|
1794
|
+
|
1795
|
+
# ======================================================================= #
|
1796
|
+
# === set_exam_topic
|
1797
|
+
#
|
1798
|
+
# This will set towards the entry that holds the current exam topic.
|
1799
|
+
# ======================================================================= #
|
1800
|
+
def set_exam_topic(
|
1801
|
+
i = :default
|
1802
|
+
)
|
1803
|
+
case i
|
1804
|
+
# ===================================================================== #
|
1805
|
+
# === :default
|
1806
|
+
# ===================================================================== #
|
1807
|
+
when :default
|
1808
|
+
i = default_exam_topic?.to_s
|
1809
|
+
end
|
1810
|
+
i = i.to_s # .downcase # Studium.expand_exam_topic(use_this_topic.to_s)
|
1811
|
+
if i and !i.empty?
|
1812
|
+
entry_for_the_current_exam_topic?.set_text(i)
|
1813
|
+
end
|
1814
|
+
end; alias set_current_exam_topic set_exam_topic # === set_current_exam_topic
|
1815
|
+
|
1816
|
+
# ========================================================================= #
|
1817
|
+
# === create_the_entry_for_the_current_exam_topic
|
1818
|
+
# ========================================================================= #
|
1819
|
+
def create_the_entry_for_the_current_exam_topic
|
1820
|
+
# ======================================================================= #
|
1821
|
+
# === @internal_hash[:entry_exam_topic_in_use]
|
1822
|
+
#
|
1823
|
+
# This is the entry that contains the current exam topics. The user can
|
1824
|
+
# modify the content of this entry at his or her own discretion. It
|
1825
|
+
# is the most important entry for this widget, among all entries
|
1826
|
+
# used in this GUI application.
|
1827
|
+
#
|
1828
|
+
# This entry is positioned rather close to the top of the main widget,
|
1829
|
+
# on the left hand side. The user can thus simply manipulate it by
|
1830
|
+
# clicking on it; most users will look at the top left (or middle)
|
1831
|
+
# first.
|
1832
|
+
#
|
1833
|
+
# Another entry of this widget may depend on this entry here, so it
|
1834
|
+
# should come early in the create-entries method - aka on top of
|
1835
|
+
# this method.
|
1836
|
+
#
|
1837
|
+
# We use a completionable-entry here, but only for ruby-gtk3.
|
1838
|
+
# ======================================================================= #
|
1839
|
+
_ = entry_with_this_completion(
|
1840
|
+
available_exam_topics_in_short_form?
|
1841
|
+
)
|
1842
|
+
_.clear_background
|
1843
|
+
_.bblack1
|
1844
|
+
_.very_light_yellow_background
|
1845
|
+
_.width_height(400, 20)
|
1846
|
+
_.set_font(smaller_font?)
|
1847
|
+
_.hint = 'This is the entry that keeps '\
|
1848
|
+
'track of the current exam topic.'
|
1849
|
+
# ======================================================================= #
|
1850
|
+
# We need this entry to be fairly wide, hence the following method call.
|
1851
|
+
# ======================================================================= #
|
1852
|
+
_.set_size_request(500, 40)
|
1853
|
+
_.set_hexpand(false)
|
1854
|
+
_.set_vexpand(false)
|
1855
|
+
# ======================================================================= #
|
1856
|
+
# Allow for scroll-events.
|
1857
|
+
# ======================================================================= #
|
1858
|
+
_.enable_scroll_events
|
1859
|
+
_.on_enter {
|
1860
|
+
find_completion_for_the_entry_for_the_current_exam_topic
|
1861
|
+
the_button_ask_the_exam_question_was_clicked
|
1862
|
+
}
|
1863
|
+
_.on_scroll_event {|widget, event|
|
1864
|
+
# ===================================================================== #
|
1865
|
+
# For now this simply sets a new, random topic.
|
1866
|
+
# ===================================================================== #
|
1867
|
+
if scroll_up?(event)
|
1868
|
+
set_exam_topic(
|
1869
|
+
available_exam_topics?.sample.downcase
|
1870
|
+
)
|
1871
|
+
sync_entry_holding_all_exam_topics_onto_the_combo_box # Sync towards the combo-box.
|
1872
|
+
elsif scroll_down?(event)
|
1873
|
+
set_exam_topic(
|
1874
|
+
available_exam_topics?.sample.downcase
|
1875
|
+
)
|
1876
|
+
sync_entry_holding_all_exam_topics_onto_the_combo_box # Sync towards the combo-box.
|
1877
|
+
end
|
1878
|
+
}
|
1879
|
+
# ======================================================================= #
|
1880
|
+
# Respond to the enter-key pressed next.
|
1881
|
+
# ======================================================================= #
|
1882
|
+
# _.on_enter_key_pressed { |widget, event|
|
1883
|
+
# sync_entry_holding_all_exam_topics_onto_the_main_combo_box
|
1884
|
+
# }
|
1885
|
+
# ======================================================================= #
|
1886
|
+
# Assign the entry-widget finally:
|
1887
|
+
# ======================================================================= #
|
1888
|
+
@internal_hash[:entry_exam_topic_in_use] = _ # And assign it here as well.
|
1889
|
+
end
|
1890
|
+
|
1891
|
+
# ========================================================================= #
|
1892
|
+
# === do_update_the_entry_n_answered
|
1893
|
+
# ========================================================================= #
|
1894
|
+
def do_update_the_entry_n_answered(
|
1895
|
+
current_exam_topic = combo_box_available_exam_topics?.active_text.to_s.strip.dup,
|
1896
|
+
entry = entry_containing_n_answers? # The entry that is to be updated.
|
1897
|
+
)
|
1898
|
+
current_exam_topic.strip! if current_exam_topic.end_with? '_'
|
1899
|
+
entry.set_text(
|
1900
|
+
return_n_answers_from_the_currently_selected_topic(current_exam_topic).to_s
|
1901
|
+
)
|
1902
|
+
end
|
1903
|
+
|
1904
|
+
# ========================================================================= #
|
1905
|
+
# === set_n_exam_questions_are_unanswered
|
1906
|
+
# ========================================================================= #
|
1907
|
+
def set_n_exam_questions_are_unanswered(i)
|
1908
|
+
entry_containing_n_unanswered_questions?.set_text(i.to_s)
|
1909
|
+
end; alias set_n_unanswered_questions set_n_exam_questions_are_unanswered # === set_n_unanswered_questions
|
1910
|
+
|
1911
|
+
# ========================================================================= #
|
1912
|
+
# === select_not_yet_completed_exam_topics
|
1913
|
+
# ========================================================================= #
|
1914
|
+
def select_not_yet_completed_exam_topics(i)
|
1915
|
+
if i and i.is_a?(Array)
|
1916
|
+
return ::Studium.reject_already_completed_exam_topics(i, hash_dataset_of_all_lectures?)
|
1917
|
+
end
|
1918
|
+
return i # else return the original input unmodified.
|
1919
|
+
end
|
1920
|
+
|
1921
|
+
# ========================================================================= #
|
1922
|
+
# === return_string_how_many_exam_questions_are_already_answered
|
1923
|
+
# ========================================================================= #
|
1924
|
+
def return_string_how_many_exam_questions_are_already_answered
|
1925
|
+
::Studium.return_string_how_many_exam_questions_are_already_answered
|
1926
|
+
end
|
1927
|
+
|
1928
|
+
# ========================================================================= #
|
1929
|
+
# === question_is?
|
1930
|
+
# ========================================================================= #
|
1931
|
+
def question_is?
|
1932
|
+
@internal_hash[:exam_question_object].question?
|
1933
|
+
end
|
1934
|
+
|
1935
|
+
# ========================================================================= #
|
1936
|
+
# === answer_is?
|
1937
|
+
# ========================================================================= #
|
1938
|
+
def answer_is?
|
1939
|
+
@internal_hash[:exam_question_object].answer?
|
1940
|
+
end
|
1941
|
+
|
1942
|
+
# ========================================================================= #
|
1943
|
+
# === default_delay?
|
1944
|
+
# ========================================================================= #
|
1945
|
+
def delay_to_use?
|
1946
|
+
@internal_hash[:delay_to_use]
|
1947
|
+
end; alias default_delay? delay_to_use? # === default_delay?
|
1948
|
+
|
1949
|
+
# ========================================================================= #
|
1950
|
+
# === create_the_button_update_n_questions_were_answered (update tag)
|
1951
|
+
# ========================================================================= #
|
1952
|
+
def create_the_button_update_n_questions_were_answered
|
1953
|
+
# ======================================================================= #
|
1954
|
+
# === The update-button is created next. It had the cat emoji in the
|
1955
|
+
# past, aka 🐈️, but not every computer system has access to such
|
1956
|
+
# an emoji, so this was replaced via an image.
|
1957
|
+
#
|
1958
|
+
# The old text was: '🐈️ Update ➡️ '
|
1959
|
+
#
|
1960
|
+
# ======================================================================= #
|
1961
|
+
_ = bold_button('Update ➡️ ')
|
1962
|
+
_.on_hover(:lightblue)
|
1963
|
+
_.hint =
|
1964
|
+
'Click this button to update the entry to the right side.'
|
1965
|
+
_.on_clicked {
|
1966
|
+
update_the_label_n_questions_were_answered
|
1967
|
+
}
|
1968
|
+
# ======================================================================= #
|
1969
|
+
# Last but not least, assign it:
|
1970
|
+
# ======================================================================= #
|
1971
|
+
@internal_hash[:button_update_n_questions_were_answered] = _
|
1972
|
+
end
|
1973
|
+
|
1974
|
+
# ========================================================================= #
|
1975
|
+
# === return_eventbox_with_an_image_to_exit_the_application
|
1976
|
+
#
|
1977
|
+
# This method bundles together a quit-the-application functionality.
|
1978
|
+
# ========================================================================= #
|
1979
|
+
def return_eventbox_with_an_image_to_exit_the_application
|
1980
|
+
application_exit_image = return_this_image_based_on_the_default_icon_theme(
|
1981
|
+
'system-log-out-symbolic.symbolic'
|
1982
|
+
) # Or: :application_exit
|
1983
|
+
_ = create_eventbox(application_exit_image)
|
1984
|
+
_.hint = 'Click on this image to exit the program.'
|
1985
|
+
_.on_clicked {
|
1986
|
+
exit_application
|
1987
|
+
}
|
1988
|
+
return _
|
1989
|
+
end
|
1990
|
+
|
1991
|
+
# ========================================================================= #
|
1992
|
+
# === enable_the_main_key_combinations
|
1993
|
+
# ========================================================================= #
|
1994
|
+
def enable_the_main_key_combinations(
|
1995
|
+
use_this_hash = HASH_DESIGNATED_KEY_COMBINATIONS
|
1996
|
+
)
|
1997
|
+
enable_these_key_combinations(
|
1998
|
+
use_this_hash
|
1999
|
+
)
|
2000
|
+
end
|
2001
|
+
|
2002
|
+
# ========================================================================= #
|
2003
|
+
# === populate_the_main_grid (grid tag, populate tag)
|
2004
|
+
#
|
2005
|
+
# In order to populate the grid, all widgets have to be designated.
|
2006
|
+
# ========================================================================= #
|
2007
|
+
def populate_the_main_grid(
|
2008
|
+
grid = main_grid?
|
2009
|
+
)
|
2010
|
+
reset_the_grid_counter # Just to be safe.
|
2011
|
+
::Gtk::Grid.full_width = 3 # 3 entries per row.
|
2012
|
+
grid.left(
|
2013
|
+
return_frame_containing_the_label_exam_topic
|
2014
|
+
)
|
2015
|
+
grid.middle(
|
2016
|
+
entry_exam_topic_in_use?
|
2017
|
+
)
|
2018
|
+
mini_hbox = create_hbox
|
2019
|
+
mini_hbox.maximal(combobox_available_exam_topics?, 2)
|
2020
|
+
mini_hbox.minimal(return_event_box_with_face_glasses, 2)
|
2021
|
+
# ======================================================================= #
|
2022
|
+
# The event-box comes next to the box with face-glasses:
|
2023
|
+
# ======================================================================= #
|
2024
|
+
mini_hbox.minimal(return_eventbox_with_an_image_to_exit_the_application, 2)
|
2025
|
+
|
2026
|
+
grid.right(mini_hbox) # One row has been completed here.
|
2027
|
+
|
2028
|
+
grid.full_line(scrolled_window1?)
|
2029
|
+
grid.full_line(scrolled_window_containing_the_textarea2?)
|
2030
|
+
# ========================================================================= #
|
2031
|
+
# Show a little helpful text how to use the textview3:
|
2032
|
+
# ========================================================================= #
|
2033
|
+
grid.full_line(return_hbox_containing_two_icons_and_instructions_what_to_do_with_the_free_form_textarea)
|
2034
|
+
# ======================================================================= #
|
2035
|
+
# Next add the free-form widget:
|
2036
|
+
# ======================================================================= #
|
2037
|
+
grid.full_line(return_scrolled_window3)
|
2038
|
+
# ======================================================================= #
|
2039
|
+
# Next synchronize the design layout of the three scrolled windows:
|
2040
|
+
# ======================================================================= #
|
2041
|
+
[
|
2042
|
+
scrolled_window1?,
|
2043
|
+
scrolled_window2?,
|
2044
|
+
scrolled_window3?
|
2045
|
+
].each {|this_widget|
|
2046
|
+
this_widget.pad8px
|
2047
|
+
}
|
2048
|
+
|
2049
|
+
# ======================================================================= #
|
2050
|
+
# Next comes the middle-part of the GUI (middle tag)
|
2051
|
+
# ======================================================================= #
|
2052
|
+
|
2053
|
+
# ======================================================================= #
|
2054
|
+
# === n questions in total
|
2055
|
+
#
|
2056
|
+
# This will show the "n questions in total" text.
|
2057
|
+
# ======================================================================= #
|
2058
|
+
text = selectable_text(N_EXAM_QUESTIONS_IN_TOTAL)
|
2059
|
+
text.set_font(smaller_font?)
|
2060
|
+
text.pad6px
|
2061
|
+
mini_hbox = create_hbox(text, entry_n_total_exam_questions?)
|
2062
|
+
grid.left(mini_hbox)
|
2063
|
+
|
2064
|
+
# ======================================================================= #
|
2065
|
+
# === n unanswered questions
|
2066
|
+
# ======================================================================= #
|
2067
|
+
text = selectable_text(N_UNANSWERED_EXAM_QUESTIONS)
|
2068
|
+
text.set_font(smaller_font?)
|
2069
|
+
text.pad6px
|
2070
|
+
mini_hbox = create_hbox(text, entry_n_unanswered_questions?)
|
2071
|
+
grid.middle(mini_hbox)
|
2072
|
+
|
2073
|
+
# ======================================================================= #
|
2074
|
+
# === n answered exam questions
|
2075
|
+
#
|
2076
|
+
# This is the text that goes along the lines of
|
2077
|
+
# "n answered exam questions".
|
2078
|
+
# ======================================================================= #
|
2079
|
+
text = selectable_text(N_ANSWERED_EXAM_QUESTIONS)
|
2080
|
+
text.set_font(smaller_font?)
|
2081
|
+
text.pad6px
|
2082
|
+
text.royalblue
|
2083
|
+
text.make_bold
|
2084
|
+
mini_hbox = create_hbox(text, entry_n_answered_exam_questions?)
|
2085
|
+
grid.right(mini_hbox)
|
2086
|
+
|
2087
|
+
# ======================================================================= #
|
2088
|
+
# === The entry "percentage solved" comes next
|
2089
|
+
# ======================================================================= #
|
2090
|
+
text = selectable_text(N_PERCENT_SOLVED)
|
2091
|
+
text.set_font(smaller_font?)
|
2092
|
+
text.pad6px
|
2093
|
+
mini_hbox = create_hbox
|
2094
|
+
mini_hbox.minimal(text, 1)
|
2095
|
+
mini_hbox.maximal(entry_percentage?, 1)
|
2096
|
+
grid.left(mini_hbox)
|
2097
|
+
|
2098
|
+
# ======================================================================= #
|
2099
|
+
# === sleep n seconds solved
|
2100
|
+
#
|
2101
|
+
# Next we add the delay-n-seconds entry.
|
2102
|
+
# ======================================================================= #
|
2103
|
+
text = selectable_text(SLEEP_N_SECONDS)
|
2104
|
+
text.set_font(smaller_font?)
|
2105
|
+
text.pad6px
|
2106
|
+
mini_hbox = create_hbox
|
2107
|
+
mini_hbox.minimal(text, 1)
|
2108
|
+
mini_hbox.maximal(entry_for_sleeping_n_seconds?, 1)
|
2109
|
+
grid.middle(mini_hbox)
|
2110
|
+
grid.right(checkbox?)
|
2111
|
+
|
2112
|
+
# ======================================================================= #
|
2113
|
+
# Add three buttons next:
|
2114
|
+
# ======================================================================= #
|
2115
|
+
grid.left(button_ask_the_exam_question?)
|
2116
|
+
grid.middle(button_reveal_the_answer?)
|
2117
|
+
grid.right(button_solve_the_exam_question?)
|
2118
|
+
|
2119
|
+
# ======================================================================= #
|
2120
|
+
# And two more buttons:
|
2121
|
+
# ======================================================================= #
|
2122
|
+
grid.left(button_clear?)
|
2123
|
+
mini_hbox.set_hexpand(true)
|
2124
|
+
|
2125
|
+
mini_hbox = create_hbox
|
2126
|
+
mini_hbox.minimal(return_wikipedia_widget, 2)
|
2127
|
+
mini_hbox.minimal(return_event_box_for_asking_a_random_exam_topic, 2)
|
2128
|
+
mini_hbox.minimal(button_use_random_entry_from_the_ten_aliases?, 2)
|
2129
|
+
mini_hbox.minimal(return_button_open_exam_topic_file, 2)
|
2130
|
+
# ======================================================================= #
|
2131
|
+
# We could also add smiley-emojis next:
|
2132
|
+
#
|
2133
|
+
# mini_hbox.minimal(@a_thinking_smiley_emoji, 2)
|
2134
|
+
# mini_hbox.minimal(@thumbs_up_emoji, 2)
|
2135
|
+
#
|
2136
|
+
# ======================================================================= #
|
2137
|
+
grid.two_width(mini_hbox)
|
2138
|
+
grid.new_line
|
2139
|
+
# ======================================================================= #
|
2140
|
+
# Next add the label that the ^^^ button can update:
|
2141
|
+
# ======================================================================= #
|
2142
|
+
grid.left(button_update_n_questions_were_answered?)
|
2143
|
+
grid.two_width(label_n_questions_were_answered?)
|
2144
|
+
grid.new_line
|
2145
|
+
mini_hbox = create_hbox
|
2146
|
+
return grid
|
2147
|
+
end
|
2148
|
+
|
2149
|
+
# ========================================================================= #
|
2150
|
+
# === enhance_the_entry_for_sleeping_n_seconds
|
2151
|
+
# ========================================================================= #
|
2152
|
+
def enhance_the_entry_for_sleeping_n_seconds(
|
2153
|
+
i = entry_for_sleeping_n_seconds?
|
2154
|
+
)
|
2155
|
+
i.width_height(45, 20)
|
2156
|
+
i.center
|
2157
|
+
i.bblack1
|
2158
|
+
i.set_name('BG_bisque')
|
2159
|
+
i.hint =
|
2160
|
+
'Provide the delay here, as <b>n seconds</b>. This will only work '\
|
2161
|
+
'if the checkbox to the right side <b>active</b>.'
|
2162
|
+
end
|
2163
|
+
|
2164
|
+
# ========================================================================= #
|
2165
|
+
# === enhance_the_entry_percentage
|
2166
|
+
# ========================================================================= #
|
2167
|
+
def enhance_the_entry_percentage(
|
2168
|
+
use_this_font = nil
|
2169
|
+
)
|
2170
|
+
_ = entry_percentage?
|
2171
|
+
_.hint =
|
2172
|
+
"This field denotes how many questions have already\n"\
|
2173
|
+
"been answered successfully, <b>in percent</b>.\n\n"\
|
2174
|
+
"Note that this requires a specific exam topic to "\
|
2175
|
+
"have been set, so no percentage value may be "\
|
2176
|
+
"shown initially.\n\nSimply assign to an exam topic "\
|
2177
|
+
"and it should work fine."
|
2178
|
+
_.do_center
|
2179
|
+
_.disable_user_input # The user can not change this entry.
|
2180
|
+
_.set_font(use_this_font) if use_this_font
|
2181
|
+
_.set_name('BG_bisque')
|
2182
|
+
_.bblack1
|
2183
|
+
end
|
2184
|
+
|
2185
|
+
# ========================================================================= #
|
2186
|
+
# === enhance_the_entry_containing_n_questions
|
2187
|
+
# ========================================================================= #
|
2188
|
+
def enhance_the_entry_containing_n_questions(
|
2189
|
+
use_this_font = smaller_font?,
|
2190
|
+
entry = @internal_hash[:entry_n_total_exam_questions]
|
2191
|
+
)
|
2192
|
+
entry.set_font(use_this_font) if use_this_font
|
2193
|
+
entry.clear_background
|
2194
|
+
entry.width_height(350, 22)
|
2195
|
+
entry.bblack1
|
2196
|
+
entry.center
|
2197
|
+
entry.readonly
|
2198
|
+
entry.very_light_yellow_background
|
2199
|
+
end
|
2200
|
+
|
2201
|
+
# ========================================================================= #
|
2202
|
+
# === enhance_entry_n_answered_exam_questions
|
2203
|
+
#
|
2204
|
+
# This method can be used to enhance the entry "n answered exam questions".
|
2205
|
+
# ========================================================================= #
|
2206
|
+
def enhance_entry_n_answered_exam_questions(
|
2207
|
+
use_this_font = :default_font,
|
2208
|
+
entry = entry_n_answered_exam_questions?
|
2209
|
+
)
|
2210
|
+
case use_this_font
|
2211
|
+
# ======================================================================= #
|
2212
|
+
# === :default_font
|
2213
|
+
# ======================================================================= #
|
2214
|
+
when :default_font, nil
|
2215
|
+
use_this_font = smaller_font?
|
2216
|
+
end
|
2217
|
+
# ======================================================================= #
|
2218
|
+
# === @internal_hash[:entry_n_answered_exam_questions]
|
2219
|
+
# ======================================================================= #
|
2220
|
+
entry.set_font(use_this_font) if use_this_font
|
2221
|
+
entry.width_height(320, 22)
|
2222
|
+
entry.bblack1
|
2223
|
+
entry.very_light_yellow_background
|
2224
|
+
entry.center
|
2225
|
+
entry.readonly
|
2226
|
+
end
|
2227
|
+
|
2228
|
+
# ========================================================================= #
|
2229
|
+
# === create_the_entry_n_answered_exam_questions
|
2230
|
+
# ========================================================================= #
|
2231
|
+
def create_the_entry_n_answered_exam_questions(
|
2232
|
+
use_this_font = :default_font
|
2233
|
+
)
|
2234
|
+
# ======================================================================= #
|
2235
|
+
# === The entry keeping track as to how many answers have been
|
2236
|
+
# given for that particular exam-topic.
|
2237
|
+
# ======================================================================= #
|
2238
|
+
@internal_hash[:entry_n_answered_exam_questions] = entry('', 12)
|
2239
|
+
enhance_entry_n_answered_exam_questions(use_this_font)
|
2240
|
+
return entry_n_answered_exam_questions? # And return it here.
|
2241
|
+
end; alias create_the_entry_containing_n_answered_exam_questions create_the_entry_n_answered_exam_questions # === create_the_entry_containing_n_answered_exam_questions
|
2242
|
+
|
2243
|
+
# ========================================================================= #
|
2244
|
+
# === enhance_entry_containing_n_unanswered_questions
|
2245
|
+
# ========================================================================= #
|
2246
|
+
def enhance_entry_containing_n_unanswered_questions(
|
2247
|
+
use_this_font = smaller_font?,
|
2248
|
+
entry = entry_n_unanswered_questions?
|
2249
|
+
)
|
2250
|
+
case use_this_font
|
2251
|
+
# ======================================================================= #
|
2252
|
+
# === :default_font
|
2253
|
+
# ======================================================================= #
|
2254
|
+
when :default_font, nil
|
2255
|
+
use_this_font = smaller_font?
|
2256
|
+
end
|
2257
|
+
entry.clear_background
|
2258
|
+
entry.set_font(use_this_font) if use_this_font
|
2259
|
+
entry.width_height(50, 20)
|
2260
|
+
entry.bblack1
|
2261
|
+
entry.very_light_yellow_background
|
2262
|
+
entry.center
|
2263
|
+
entry.readonly
|
2264
|
+
end; alias enhance_entry_containing_n_unanswered_questions enhance_entry_containing_n_unanswered_questions # === enhance_entry_containing_n_unanswered_questions
|
2265
|
+
|
2266
|
+
# ========================================================================= #
|
2267
|
+
# === set_n_exam_questions_were_already_answered
|
2268
|
+
# ========================================================================= #
|
2269
|
+
def set_n_exam_questions_were_already_answered(i)
|
2270
|
+
entry_n_answered_exam_questions?.set_text(i.to_s)
|
2271
|
+
end
|
2272
|
+
|
2273
|
+
# ========================================================================= #
|
2274
|
+
# === enable_alt_w_key_combination
|
2275
|
+
#
|
2276
|
+
# This method will specifically enable the "alt+w" shortcut.
|
2277
|
+
# ========================================================================= #
|
2278
|
+
def enable_alt_w_key_combination(
|
2279
|
+
i = @accel_group
|
2280
|
+
)
|
2281
|
+
# ======================================================================= #
|
2282
|
+
# Add alt+w key combination, to open the current exam topic file:
|
2283
|
+
# ======================================================================= #
|
2284
|
+
use_this_key = ::Gdk::Keyval::KEY_W
|
2285
|
+
i.connect(use_this_key, :mod1_mask, :visible) { # alt+w
|
2286
|
+
do_open_the_current_exam_topic_file
|
2287
|
+
}
|
2288
|
+
end
|
2289
|
+
|
2290
|
+
# ========================================================================= #
|
2291
|
+
# === current_exam_topic_from_the_entry?
|
2292
|
+
# ========================================================================= #
|
2293
|
+
def current_exam_topic_from_the_entry?
|
2294
|
+
entry_for_the_current_exam_topic?.text?.to_s
|
2295
|
+
end; alias current_exam_topic_as_a_string? current_exam_topic_from_the_entry? # === current_exam_topic_as_a_string?
|
2296
|
+
|
2297
|
+
# ========================================================================= #
|
2298
|
+
# === do_open_the_current_exam_topic_file
|
2299
|
+
#
|
2300
|
+
# This method can either open the exam-file in the bluefish editor,
|
2301
|
+
# or in the integrated ruby-gtk editor. Since as of July 2021 we
|
2302
|
+
# will try the integrated variant. Unfortunately ruby-gtk is somehow
|
2303
|
+
# buggy - reading a large file leads to a BadAlloc error, so this
|
2304
|
+
# was changed to open an external editor instead.
|
2305
|
+
# ========================================================================= #
|
2306
|
+
def do_open_the_current_exam_topic_file(
|
2307
|
+
use_this_as_exam_topic = current_exam_topic_from_the_entry?
|
2308
|
+
)
|
2309
|
+
use_this_as_exam_topic = Studium.find_corresponding_exam_topic(use_this_as_exam_topic)
|
2310
|
+
if use_this_as_exam_topic.empty?
|
2311
|
+
do_popup_the_you_have_to_provide_an_exam_topic
|
2312
|
+
end
|
2313
|
+
# ======================================================================= #
|
2314
|
+
# We must obtain the correct path next, to then send into the editor:
|
2315
|
+
# ======================================================================= #
|
2316
|
+
use_this_as_exam_topic = Studium.path_to_exam_topic?+
|
2317
|
+
File.basename(use_this_as_exam_topic)
|
2318
|
+
if use_the_internal_editor? # This here is when we use the internal editor.
|
2319
|
+
set_save_into_this_local_file(use_this_as_exam_topic)
|
2320
|
+
set_editor_buffer(File.read(use_this_as_exam_topic))
|
2321
|
+
@notebook_tab.focus_on_this_tab(2)
|
2322
|
+
else
|
2323
|
+
# ======================================================================= #
|
2324
|
+
# Or simply use bluefish or whatever else the editor is.
|
2325
|
+
# ======================================================================= #
|
2326
|
+
_ = "#{use_this_editor?} #{use_this_as_exam_topic}"
|
2327
|
+
esystem(_)
|
2328
|
+
end
|
2329
|
+
end
|
2330
|
+
|
2331
|
+
# ========================================================================= #
|
2332
|
+
# === return_button_open_exam_topic_file
|
2333
|
+
#
|
2334
|
+
# This button should be next to the event box that will ask a random
|
2335
|
+
# exam topic.
|
2336
|
+
# ========================================================================= #
|
2337
|
+
def return_button_open_exam_topic_file
|
2338
|
+
# ======================================================================= #
|
2339
|
+
# This button will have the symbol for :open_file, an emoji - if
|
2340
|
+
# emojis are used. Otherwise an image will be used instead.
|
2341
|
+
# ======================================================================= #
|
2342
|
+
if use_emoji?
|
2343
|
+
_ = button(return_emoji(:open_box))
|
2344
|
+
else
|
2345
|
+
_ = button_with_this_image(image_open_file)
|
2346
|
+
end
|
2347
|
+
_.no_relief
|
2348
|
+
_.on_hover_lightblue
|
2349
|
+
_.hint = 'Click on this button to <b>open the current exam-topic file</b>.'
|
2350
|
+
_.on_clicked {
|
2351
|
+
do_open_the_current_exam_topic_file
|
2352
|
+
}
|
2353
|
+
return _
|
2354
|
+
end
|
2355
|
+
|
2356
|
+
# ========================================================================= #
|
2357
|
+
# === return_n_answers_from_the_currently_selected_topic
|
2358
|
+
# ========================================================================= #
|
2359
|
+
def return_n_answers_from_the_currently_selected_topic(
|
2360
|
+
i = current_exam_topic_as_a_string?
|
2361
|
+
)
|
2362
|
+
::Studium.n_answers_available_in_this_topic(i)
|
2363
|
+
end
|
2364
|
+
|
2365
|
+
# ========================================================================= #
|
2366
|
+
# === shall_we_create_the_gtk_editor?
|
2367
|
+
# ========================================================================= #
|
2368
|
+
def shall_we_create_the_gtk_editor?
|
2369
|
+
@internal_hash[:use_this_editor] == :internal
|
2370
|
+
end
|
2371
|
+
|
2372
|
+
# ========================================================================= #
|
2373
|
+
# === create_the_labels
|
2374
|
+
# ========================================================================= #
|
2375
|
+
def create_the_labels
|
2376
|
+
# ======================================================================= #
|
2377
|
+
# === @label_n_questions_were_answered
|
2378
|
+
# ======================================================================= #
|
2379
|
+
@label_n_questions_were_answered = selectable_label
|
2380
|
+
update_the_label_n_questions_were_answered(@label_n_questions_were_answered)
|
2381
|
+
end
|
2382
|
+
|
2383
|
+
# ========================================================================= #
|
2384
|
+
# === label_n_questions_were_answered?
|
2385
|
+
# ========================================================================= #
|
2386
|
+
def label_n_questions_were_answered?
|
2387
|
+
@label_n_questions_were_answered
|
2388
|
+
end
|
2389
|
+
|
2390
|
+
# ========================================================================= #
|
2391
|
+
# === set_n_exam_questions_exist_in_total
|
2392
|
+
#
|
2393
|
+
# This method exists to set the value of the proper entry, containing
|
2394
|
+
# how many exam-questions are still unanswered.
|
2395
|
+
# ========================================================================= #
|
2396
|
+
def set_n_exam_questions_exist_in_total(i)
|
2397
|
+
entry_n_total_exam_questions?.set_text(i.to_s)
|
2398
|
+
end
|
2399
|
+
|
2400
|
+
# ========================================================================= #
|
2401
|
+
# === combobox_available_exam_topics?
|
2402
|
+
#
|
2403
|
+
# This combo box will contain all available (registered) exam topics.
|
2404
|
+
# ========================================================================= #
|
2405
|
+
def combobox_available_exam_topics?
|
2406
|
+
@internal_hash[:combobox_available_exam_topics]
|
2407
|
+
end; alias return_the_combobox combobox_available_exam_topics? # === return_the_combobox
|
2408
|
+
alias combo_box_available_exam_topics? combobox_available_exam_topics? # === combo_box_available_exam_topics?
|
2409
|
+
alias main_combo_box? combobox_available_exam_topics? # === main_combo_box?
|
2410
|
+
alias combo_box? combobox_available_exam_topics? # === combo_box?
|
2411
|
+
alias return_combo_box_showing_all_exam_questions combobox_available_exam_topics? # === return_combo_box_showing_all_exam_questions
|
2412
|
+
alias return_combo_box_available_exam_topics combobox_available_exam_topics? # === return_combo_box_available_exam_topics
|
2413
|
+
|
2414
|
+
# ========================================================================= #
|
2415
|
+
# === button_update_n_questions_were_answered?
|
2416
|
+
# ========================================================================= #
|
2417
|
+
def button_update_n_questions_were_answered?
|
2418
|
+
@internal_hash[:button_update_n_questions_were_answered]
|
2419
|
+
end
|
2420
|
+
|
2421
|
+
# ========================================================================= #
|
2422
|
+
# === update_the_label_n_questions_were_answered
|
2423
|
+
# ========================================================================= #
|
2424
|
+
def update_the_label_n_questions_were_answered(
|
2425
|
+
i = @label_n_questions_were_answered
|
2426
|
+
)
|
2427
|
+
i.set_text(
|
2428
|
+
return_string_how_many_exam_questions_are_already_answered
|
2429
|
+
)
|
2430
|
+
end; alias update_the_label_containing_the_last_exam_question update_the_label_n_questions_were_answered # === update_the_label_containing_the_last_exam_question
|
2431
|
+
|
2432
|
+
# ========================================================================= #
|
2433
|
+
# === return_checkbox_shall_we_reveal_the_answer
|
2434
|
+
#
|
2435
|
+
# This will only return the checkbox; creation must happen before
|
2436
|
+
# this method is called.
|
2437
|
+
# ========================================================================= #
|
2438
|
+
def return_checkbox_shall_we_reveal_the_answer
|
2439
|
+
@internal_hash[:checkbox_shall_we_reveal_the_answer]
|
2440
|
+
end; alias checkbox? return_checkbox_shall_we_reveal_the_answer # === checkbox?
|
2441
|
+
alias checkbox_shall_we_reveal_the_answer? return_checkbox_shall_we_reveal_the_answer # === checkbox_shall_we_reveal_the_answer?
|
2442
|
+
|
2443
|
+
# ========================================================================= #
|
2444
|
+
# === simply_assign_this_as_the_new_exam_topic_onto_the_primary_combobox
|
2445
|
+
#
|
2446
|
+
# This method does not work currently.
|
2447
|
+
# ========================================================================= #
|
2448
|
+
def simply_assign_this_as_the_new_exam_topic_onto_the_primary_combobox(
|
2449
|
+
i
|
2450
|
+
)
|
2451
|
+
combobox_available_exam_topics?.append_text(i.to_s)
|
2452
|
+
end
|
2453
|
+
|
2454
|
+
# ========================================================================= #
|
2455
|
+
# === main_grid?
|
2456
|
+
# ========================================================================= #
|
2457
|
+
def main_grid?
|
2458
|
+
@internal_hash[:main_grid]
|
2459
|
+
end
|
2460
|
+
|
2461
|
+
# ======================================================================= #
|
2462
|
+
# === entry_exam_topic_in_use?
|
2463
|
+
# ======================================================================= #
|
2464
|
+
def entry_exam_topic_in_use?
|
2465
|
+
@internal_hash[:entry_exam_topic_in_use]
|
2466
|
+
end; alias entry_for_the_current_exam_topic? entry_exam_topic_in_use? # === entry_for_the_current_exam_topic?
|
2467
|
+
alias entry_ask_questions_from_this_topic? entry_exam_topic_in_use? # === entry_ask_questions_from_this_topic?
|
2468
|
+
alias entry_for_the_exam_topic? entry_exam_topic_in_use? # === entry_for_the_exam_topic?
|
2469
|
+
alias entry_holding_all_exam_topics? entry_exam_topic_in_use? # === entry_ask_questions_from_this_topic?
|
2470
|
+
alias entry_current_exam_topic? entry_exam_topic_in_use? # === entry_current_exam_topic?
|
2471
|
+
|
2472
|
+
# ========================================================================= #
|
2473
|
+
# === create_then_return_the_default_grid
|
2474
|
+
# ========================================================================= #
|
2475
|
+
def create_then_return_the_default_grid
|
2476
|
+
grid = default_grid # main_grid?
|
2477
|
+
grid.pad2px
|
2478
|
+
grid.default_spacing(8)
|
2479
|
+
grid.width_height(width?, height?)
|
2480
|
+
grid.set_size_request(width?, height?)
|
2481
|
+
@internal_hash[:main_grid] = grid
|
2482
|
+
return grid
|
2483
|
+
end; alias create_the_main_grid create_then_return_the_default_grid # === create_the_main_grid
|
2484
|
+
|
2485
|
+
# ========================================================================= #
|
2486
|
+
# === create_the_skeleton (create tag, skeleton tag)
|
2487
|
+
# ========================================================================= #
|
2488
|
+
def create_the_skeleton
|
2489
|
+
create_the_entries # Should come fairly early - definitely before the grid is created.
|
2490
|
+
create_the_checkbox_shall_we_reveal_the_answer # ← Must come after the entries were created.
|
2491
|
+
create_text_buffer_for_the_answer # Must come before create_the_textviews().
|
2492
|
+
create_the_textviews
|
2493
|
+
create_the_combobox
|
2494
|
+
create_the_buttons
|
2495
|
+
create_the_editor
|
2496
|
+
create_the_labels # Should come after the editor was created.
|
2497
|
+
# create_the_emoji_toggle_widget # This currently does not work.
|
2498
|
+
create_the_thumbs_up_emoji
|
2499
|
+
create_the_context_menu # The context-menu can come last.
|
2500
|
+
# instantiate_the_control_panel # This one must come before the notebook tab is populated.
|
2501
|
+
create_the_main_grid
|
2502
|
+
create_the_notebook_tab # This must come late.
|
2503
|
+
end; alias create_skeleton create_the_skeleton # === create_skeleton
|
2504
|
+
|
2505
|
+
# ========================================================================= #
|
2506
|
+
# === connect_the_notebook_tab
|
2507
|
+
#
|
2508
|
+
# This method will connect the notebook with the main Gtk::Window in use.
|
2509
|
+
# ========================================================================= #
|
2510
|
+
def connect_the_notebook_tab(
|
2511
|
+
window = main_window?,
|
2512
|
+
padding_to_use = 2
|
2513
|
+
)
|
2514
|
+
# @notebook_tab.halign = 0.5
|
2515
|
+
scrolled_window = create_scrolled_window(@notebook_tab)
|
2516
|
+
scrolled_window.show_all
|
2517
|
+
window.add(scrolled_window) # , padding_to_use)
|
2518
|
+
window.show_all
|
2519
|
+
end
|
2520
|
+
|
2521
|
+
# ========================================================================= #
|
2522
|
+
# === create_the_notebook_tab (notebook tag)
|
2523
|
+
# ========================================================================= #
|
2524
|
+
def create_the_notebook_tab
|
2525
|
+
# ======================================================================= #
|
2526
|
+
# === @notebook_tab
|
2527
|
+
# ======================================================================= #
|
2528
|
+
@notebook_tab = create_notebook { :make_it_scrollable }
|
2529
|
+
@notebook_tab.css_class('notebook_for_the_exam_trainer')
|
2530
|
+
@notebook_tab.the_tabs_appear_on_top
|
2531
|
+
@notebook_tab.can_be_rearranged
|
2532
|
+
@notebook_tab.do_show_the_tabs
|
2533
|
+
@notebook_tab.do_show_the_border
|
2534
|
+
end
|
2535
|
+
|
2536
|
+
# ========================================================================= #
|
2537
|
+
# === the_first_notebook_tab_is_active
|
2538
|
+
# ========================================================================= #
|
2539
|
+
def the_first_notebook_tab_is_active
|
2540
|
+
@notebook_tab.the_first_notebook_tab_is_active
|
2541
|
+
end
|
2542
|
+
|
2543
|
+
# ========================================================================= #
|
2544
|
+
# === populate_the_notebook_tab
|
2545
|
+
# ========================================================================= #
|
2546
|
+
def populate_the_notebook_tab
|
2547
|
+
# ======================================================================= #
|
2548
|
+
# We could display a Curriculum in a notebook-tab. Unfortunately, in
|
2549
|
+
# 2021, this is a bit wide, and makes the whole notebook appear too
|
2550
|
+
# large, so it was disabled again, until we improve on it. We probably
|
2551
|
+
# have to decrease its size from the get go, and manage it at all
|
2552
|
+
# times via scrolled-widgets.
|
2553
|
+
#
|
2554
|
+
# The old code is shown next:
|
2555
|
+
#
|
2556
|
+
# label4 = modify_bold_label('Curriculum Viewer', @internal_hash[:colour_to_use_for_the_notebook_labels])
|
2557
|
+
# @notebook_tab.add_tab(::Studium::GUI::Gtk::CurriculumViewer.new, label4)
|
2558
|
+
#
|
2559
|
+
# ======================================================================= #
|
2560
|
+
show_ten_aliases = show_ten_aliases?
|
2561
|
+
# ======================================================================= #
|
2562
|
+
# === Add the first tab, containing the "Exam Trainer" widget next
|
2563
|
+
#
|
2564
|
+
# This will be contained in @first_vbox, which in turn contains
|
2565
|
+
# the @horizontal_pane variable.
|
2566
|
+
# ======================================================================= #
|
2567
|
+
@notebook_tab.append_page(
|
2568
|
+
main_grid?,
|
2569
|
+
modify_bold_label('Exam trainer', @internal_hash[:colour_to_use_for_the_notebook_labels])
|
2570
|
+
)
|
2571
|
+
if use_the_internal_editor?
|
2572
|
+
# ===================================================================== #
|
2573
|
+
# Append the editor in this event:
|
2574
|
+
# ===================================================================== #
|
2575
|
+
@notebook_tab.append_page(@editor, bold_text('editor'))
|
2576
|
+
end
|
2577
|
+
if Object.const_defined?(:Roebe) and show_ten_aliases
|
2578
|
+
# ===================================================================== #
|
2579
|
+
# Designate the parent widget next:
|
2580
|
+
# ===================================================================== #
|
2581
|
+
show_ten_aliases.set_parent_widget(self)
|
2582
|
+
# ===================================================================== #
|
2583
|
+
# And append the show-ten-aliases widget next:
|
2584
|
+
# ===================================================================== #
|
2585
|
+
@notebook_tab.append_page(
|
2586
|
+
show_ten_aliases,
|
2587
|
+
modify_bold_label(
|
2588
|
+
'Current top-ten exams', @internal_hash[:colour_to_use_for_the_notebook_labels]
|
2589
|
+
)
|
2590
|
+
)
|
2591
|
+
end
|
2592
|
+
@notebook_tab.the_first_tab_is_active
|
2593
|
+
# ======================================================================= #
|
2594
|
+
# === Add the tab that includes the Control Panel
|
2595
|
+
# ======================================================================= #
|
2596
|
+
# label2 = modify_bold_label('Control Panel', @internal_hash[:colour_to_use_for_the_notebook_labels])
|
2597
|
+
# @notebook_tab.append_page(
|
2598
|
+
# @control_panel,
|
2599
|
+
# label2
|
2600
|
+
# )
|
2601
|
+
end
|
2602
|
+
|
2603
|
+
# ========================================================================= #
|
2604
|
+
# === Studium::GUI::UniversalWidgets::ExamTrainer.run
|
2605
|
+
# ========================================================================= #
|
2606
|
+
def self.run(
|
2607
|
+
i = ARGV
|
2608
|
+
)
|
2609
|
+
require 'gtk_paradise/run'
|
2610
|
+
_ = ::Studium::GUI::UniversalWidgets::ExamTrainer.new(i)
|
2611
|
+
r = ::Gtk.run
|
2612
|
+
r << _
|
2613
|
+
_.set_parent_widget(r) # Designate it as the parent widget.
|
2614
|
+
_.enable_the_main_key_combinations
|
2615
|
+
r.add_context_menu_with_the_default_accel_group
|
2616
|
+
r.on_button_press_event { |widget, event|
|
2617
|
+
if ::Gtk.right_mouse_click?(event) # right mouse click event.
|
2618
|
+
_.context_menu?.popup_based_on_this_event(event)
|
2619
|
+
end
|
2620
|
+
}
|
2621
|
+
r.automatic_size_then_automatic_title
|
2622
|
+
r.enable_quick_exit
|
2623
|
+
r.move_to(x: 15, y: 0)
|
2624
|
+
r.run
|
2625
|
+
end
|
2626
|
+
|
2627
|
+
# ========================================================================= #
|
2628
|
+
# === resize_the_notebook_tab_towards_the_primary_width_and_height
|
2629
|
+
# ========================================================================= #
|
2630
|
+
def resize_the_notebook_tab_towards_the_primary_width_and_height
|
2631
|
+
_ = @notebook_tab
|
2632
|
+
_.set_size_request(width?, height?)
|
2633
|
+
end
|
2634
|
+
|
2635
|
+
# ========================================================================= #
|
2636
|
+
# === return_button_solve_the_question
|
2637
|
+
#
|
2638
|
+
# The old String was:
|
2639
|
+
#
|
2640
|
+
# '_Solve the exam question'
|
2641
|
+
#
|
2642
|
+
# ========================================================================= #
|
2643
|
+
def return_button_solve_the_question
|
2644
|
+
_ = bold_button('😁️ Mark the question as _solved ✓', self, :use_a_mnemonic) {
|
2645
|
+
:button_solve_the_exam_question_was_clicked
|
2646
|
+
}
|
2647
|
+
# ======================================================================= #
|
2648
|
+
# .set_size_request() is not necessary as we use a separate method
|
2649
|
+
# that controls the size of the widget at hand.
|
2650
|
+
# ======================================================================= #
|
2651
|
+
_.hint =
|
2652
|
+
'Use this button to <span weight="bold" foreground="lightgreen">mark '\
|
2653
|
+
'the question as solved</span> - that is, it is now '\
|
2654
|
+
'<b>correctly answered</b>).'
|
2655
|
+
# button_solve_the_question.set_size_request(78, 30)
|
2656
|
+
return _
|
2657
|
+
end
|
2658
|
+
|
2659
|
+
# ========================================================================= #
|
2660
|
+
# === array_all_exam_questions?
|
2661
|
+
#
|
2662
|
+
# Query-method to keep track of all exam-questions that were asked in
|
2663
|
+
# the current run.
|
2664
|
+
# ========================================================================= #
|
2665
|
+
def array_all_exam_questions?
|
2666
|
+
@internal_hash[:array_all_exam_questions]
|
2667
|
+
end; alias all_exam_questions array_all_exam_questions? # === all_exam_questions
|
2668
|
+
|
2669
|
+
# ========================================================================= #
|
2670
|
+
# === update_array_all_exam_questions
|
2671
|
+
# ========================================================================= #
|
2672
|
+
def update_array_all_exam_questions
|
2673
|
+
@internal_hash[:array_all_exam_questions] = []
|
2674
|
+
end
|
2675
|
+
|
2676
|
+
# ========================================================================= #
|
2677
|
+
# === do_popup_the_array_of_all_exam_questions
|
2678
|
+
#
|
2679
|
+
# This method will be called then whe icon-with-glasses is clicked.
|
2680
|
+
# ========================================================================= #
|
2681
|
+
def do_popup_the_array_of_all_exam_questions(
|
2682
|
+
array = :infer
|
2683
|
+
)
|
2684
|
+
case array
|
2685
|
+
# ======================================================================= #
|
2686
|
+
# === :infer
|
2687
|
+
# ======================================================================= #
|
2688
|
+
when :infer
|
2689
|
+
array = Studium.return_all_exam_questions_from_this_topic(
|
2690
|
+
entry_exam_topic_as_string?
|
2691
|
+
)
|
2692
|
+
end
|
2693
|
+
content = array.map.with_index {|line, index| index += 1
|
2694
|
+
line = line.dup
|
2695
|
+
line.prepend(
|
2696
|
+
"(#{index}) "
|
2697
|
+
)
|
2698
|
+
line
|
2699
|
+
}.join("\n")
|
2700
|
+
text_buffer = create_text_buffer(content)
|
2701
|
+
text_view = create_text_view(text_buffer)
|
2702
|
+
scrolled_window = create_scrolled_window(text_view)
|
2703
|
+
scrolled_window.width_height(1200, 700)
|
2704
|
+
scrolled_window.pad8px
|
2705
|
+
# scrolled_window.add(text_view)
|
2706
|
+
scrolled_window.show_all
|
2707
|
+
popup_over_this_widget(
|
2708
|
+
scrolled_window,
|
2709
|
+
text_view,
|
2710
|
+
entry_for_the_exam_topic?
|
2711
|
+
).popup
|
2712
|
+
end
|
2713
|
+
|
2714
|
+
# ========================================================================= #
|
2715
|
+
# === do_popup_the_you_have_to_provide_an_exam_topic
|
2716
|
+
# ========================================================================= #
|
2717
|
+
def do_popup_the_you_have_to_provide_an_exam_topic
|
2718
|
+
bold_popover_message = bold_label(
|
2719
|
+
"You have to provide an exam-topic, in the exam-topic entry.\n\n"\
|
2720
|
+
"The arrow should indicate the proper entry."
|
2721
|
+
)
|
2722
|
+
popover_message( # Nudge the user here.
|
2723
|
+
bold_popover_message,
|
2724
|
+
entry_for_the_exam_topic?
|
2725
|
+
).popup
|
2726
|
+
end
|
2727
|
+
|
2728
|
+
# ========================================================================= #
|
2729
|
+
# === exam_topic_from_the_correct_entry?
|
2730
|
+
#
|
2731
|
+
# This method must always return a string, hence the .to_s call.
|
2732
|
+
# ========================================================================= #
|
2733
|
+
def exam_topic_from_the_correct_entry?
|
2734
|
+
entry_exam_topic_in_use?.text?.to_s.strip # This must always be a String.
|
2735
|
+
end; alias current_exam_topic? exam_topic_from_the_correct_entry? # === current_exam_topic?
|
2736
|
+
alias main_exam_topic? exam_topic_from_the_correct_entry? # === main_exam_topic?
|
2737
|
+
alias exam_topic? exam_topic_from_the_correct_entry? # === exam_topic?
|
2738
|
+
alias current_topic? exam_topic_from_the_correct_entry? # === current_topic?
|
2739
|
+
alias entry_exam_topic? exam_topic_from_the_correct_entry? # === exam_topic?
|
2740
|
+
alias entry_ask_questions? exam_topic_from_the_correct_entry? # === entry_ask_questions?
|
2741
|
+
alias entry_ask_questions_from_this_topic? exam_topic_from_the_correct_entry? # === entry_ask_questions_from_this_topic?
|
2742
|
+
alias entry_exam_topic_as_string? exam_topic_from_the_correct_entry? # === entry_exam_topic_as_string?
|
2743
|
+
|
2744
|
+
# ======================================================================= #
|
2745
|
+
# === sync_combo_box_entry_onto_the_current_exam_entry
|
2746
|
+
# ======================================================================= #
|
2747
|
+
def sync_combo_box_entry_onto_the_current_exam_entry(
|
2748
|
+
i = combo_box?.entry?
|
2749
|
+
)
|
2750
|
+
_ = ::Studium.find_corresponding_exam_title(i)
|
2751
|
+
set_current_exam_topic(_)
|
2752
|
+
end
|
2753
|
+
|
2754
|
+
# ========================================================================= #
|
2755
|
+
# === do_update_the_entry_n_unanswered_questions
|
2756
|
+
#
|
2757
|
+
# This method depends on two entries being set correctly.
|
2758
|
+
# ========================================================================= #
|
2759
|
+
def do_update_the_entry_n_unanswered_questions
|
2760
|
+
_ = entry_containing_n_questions?.text?.to_i -
|
2761
|
+
entry_containing_n_answers?.text?.to_i
|
2762
|
+
entry_containing_n_unanswered_questions?.set_text(_.to_s)
|
2763
|
+
end; alias update_the_entry_n_unanswered_questions do_update_the_entry_n_unanswered_questions # === update_the_entry_n_unanswered_questions
|
2764
|
+
alias update_n_unanswered do_update_the_entry_n_unanswered_questions # === update_n_unanswered
|
2765
|
+
|
2766
|
+
# ========================================================================= #
|
2767
|
+
# === set_n_percentage_of_questions_answered
|
2768
|
+
#
|
2769
|
+
# An alternative would be:
|
2770
|
+
#
|
2771
|
+
# percentage_value = Studium.n_percent_questions_answered_of_this_topic?(
|
2772
|
+
# use_this_exam_topic.downcase
|
2773
|
+
# )
|
2774
|
+
#
|
2775
|
+
# ========================================================================= #
|
2776
|
+
def set_n_percentage_of_questions_answered(i)
|
2777
|
+
percentage_value = -1 if percentage_value == false # Weak "safeguard".
|
2778
|
+
i = i.to_f.round(1)
|
2779
|
+
entry_percentage?.set_text("#{i}%") # Sync it onto the proper entry.
|
2780
|
+
end; alias set_n_percentage set_n_percentage_of_questions_answered # === set_n_percentage
|
2781
|
+
alias update_the_percentage_entry set_n_percentage_of_questions_answered # === update_the_percentage_entry
|
2782
|
+
alias do_update_this_entry_with_that_exam_topic_for_its_percentage_value set_n_percentage_of_questions_answered # === do_update_this_entry_with_that_exam_topic_for_its_percentage_value
|
2783
|
+
|
2784
|
+
# ======================================================================= #
|
2785
|
+
# === handle_the_combo_box_available_exam_topics_on_changed_event
|
2786
|
+
# ======================================================================= #
|
2787
|
+
def handle_the_combo_box_available_exam_topics_on_changed_event
|
2788
|
+
clear_question_buffer
|
2789
|
+
# ===================================================================== #
|
2790
|
+
# Now we need to sync from the combo-box towards the current
|
2791
|
+
# exam-entry.
|
2792
|
+
# ===================================================================== #
|
2793
|
+
sync_combo_box_entry_onto_the_current_exam_entry
|
2794
|
+
one_two_three
|
2795
|
+
end; alias do_handle_the_combobox_available_exam_topics_on_changed_event handle_the_combo_box_available_exam_topics_on_changed_event # === do_handle_the_combobox_available_exam_topics_on_changed_event
|
2796
|
+
alias sync_the_current_exam_topic_onto_the_exam_topic_entry handle_the_combo_box_available_exam_topics_on_changed_event # === sync_the_current_exam_topic_onto_the_exam_topic_entry
|
2797
|
+
|
2798
|
+
# ========================================================================= #
|
2799
|
+
# === create_the_checkbox_shall_we_reveal_the_answer
|
2800
|
+
# ========================================================================= #
|
2801
|
+
def create_the_checkbox_shall_we_reveal_the_answer(
|
2802
|
+
entry_delay_to_use = entry_delay_to_use?
|
2803
|
+
)
|
2804
|
+
_ = create_checkbox(
|
2805
|
+
" Automatically reveal the \n answer after a delay"
|
2806
|
+
)
|
2807
|
+
_.set_font(smallest_font?)
|
2808
|
+
# ======================================================================= #
|
2809
|
+
# Next determine whether the checkbox is active, on startup, or whether
|
2810
|
+
# it is not active when the GUI starts up.
|
2811
|
+
# ======================================================================= #
|
2812
|
+
_.mark_as_checked # Should be checked as-is.
|
2813
|
+
_.hint =
|
2814
|
+
'Deselect this if you do not want to automatically reveal the answer. '\
|
2815
|
+
'In that case you have to manually click on the Answer button.'
|
2816
|
+
_.on_toggled { |widget|
|
2817
|
+
if _.active?
|
2818
|
+
entry_delay_to_use.grey_in
|
2819
|
+
elsif not _.active?
|
2820
|
+
entry_delay_to_use.grey_out
|
2821
|
+
end
|
2822
|
+
}
|
2823
|
+
if _.is_it_active?
|
2824
|
+
entry_delay_to_use.grey_in
|
2825
|
+
else
|
2826
|
+
entry_delay_to_use.grey_out
|
2827
|
+
end
|
2828
|
+
# ======================================================================= #
|
2829
|
+
# === @internal_hash[:checkbox_shall_we_reveal_the_answer]
|
2830
|
+
# ======================================================================= #
|
2831
|
+
@internal_hash[:checkbox_shall_we_reveal_the_answer] = _
|
2832
|
+
end
|
2833
|
+
|
2834
|
+
# ========================================================================= #
|
2835
|
+
# === button_ask_the_exam_question_was_clicked (clicked tag)
|
2836
|
+
#
|
2837
|
+
# This is the most important button of this GUI.
|
2838
|
+
# ========================================================================= #
|
2839
|
+
def button_ask_the_exam_question_was_clicked(
|
2840
|
+
use_this_topic =
|
2841
|
+
:obtain_the_exam_topic_from_the_relevant_entry
|
2842
|
+
)
|
2843
|
+
case use_this_topic
|
2844
|
+
# ======================================================================= #
|
2845
|
+
# === :obtain_the_exam_topic_from_the_relevant_entry
|
2846
|
+
# ======================================================================= #
|
2847
|
+
when :obtain_the_exam_topic_from_the_relevant_entry
|
2848
|
+
use_this_topic = entry_exam_topic_in_use?.text?.to_s
|
2849
|
+
end
|
2850
|
+
we_may_reveal_the_exam_answer
|
2851
|
+
one_two_three(use_this_topic)
|
2852
|
+
end; alias do_handle_the_click_event_for_the_ask_question_button button_ask_the_exam_question_was_clicked # === do_handle_the_click_event_for_the_ask_question_button
|
2853
|
+
alias ask_an_exam_question button_ask_the_exam_question_was_clicked # === ask_an_exam_question
|
2854
|
+
alias do_ask_the_exam_question button_ask_the_exam_question_was_clicked # === do_ask_the_exam_question
|
2855
|
+
alias do_ask_a_new_question button_ask_the_exam_question_was_clicked # === do_ask_a_new_question
|
2856
|
+
alias trigger_the_event_when_the_ask_exam_question_button_was_clicked button_ask_the_exam_question_was_clicked # === trigger_the_event_when_the_ask_exam_question_button_was_clicked
|
2857
|
+
alias ask_an_exam_question button_ask_the_exam_question_was_clicked # === ask_an_exam_question
|
2858
|
+
alias do_ask_an_exam_question button_ask_the_exam_question_was_clicked # === do_ask_an_exam_question
|
2859
|
+
alias do_ask_a_new_exam_question button_ask_the_exam_question_was_clicked # === do_ask_a_new_exam_question
|
2860
|
+
alias the_button_ask_the_question_was_clicked button_ask_the_exam_question_was_clicked # === the_button_ask_the_question_was_clicked
|
2861
|
+
alias the_button_ask_the_exam_question_was_clicked button_ask_the_exam_question_was_clicked # === the_button_ask_the_exam_question_was_clicked
|
2862
|
+
|
2863
|
+
# ========================================================================= #
|
2864
|
+
# === entry_for_sleeping_n_seconds?
|
2865
|
+
# ========================================================================= #
|
2866
|
+
def entry_for_sleeping_n_seconds?
|
2867
|
+
@internal_hash[:entry_for_sleeping_n_seconds]
|
2868
|
+
end; alias entry_delay_to_use? entry_for_sleeping_n_seconds? # === entry_delay_to_use
|
2869
|
+
alias entry_sleep_n_seconds? entry_for_sleeping_n_seconds? # === entry_sleep_n_seconds?
|
2870
|
+
alias entry_delay? entry_for_sleeping_n_seconds? # === entry_delay?
|
2871
|
+
alias return_entry_for_sleeping_n_seconds entry_for_sleeping_n_seconds? # === return_entry_for_sleeping_n_seconds
|
2872
|
+
alias return_the_entry_sleep_n_seconds entry_for_sleeping_n_seconds? # === return_the_entry_sleep_n_seconds
|
2873
|
+
|
2874
|
+
# ========================================================================= #
|
2875
|
+
# === entry_delay_value?
|
2876
|
+
# ========================================================================= #
|
2877
|
+
def entry_delay_value?
|
2878
|
+
entry_for_sleeping_n_seconds?.text?.to_f
|
2879
|
+
end
|
2880
|
+
|
2881
|
+
# ========================================================================= #
|
2882
|
+
# === exam_question_object?
|
2883
|
+
# ========================================================================= #
|
2884
|
+
def exam_question_object?
|
2885
|
+
@internal_hash[:exam_question_object]
|
2886
|
+
end
|
2887
|
+
|
2888
|
+
# ========================================================================= #
|
2889
|
+
# === create_the_reveal_the_answer_button
|
2890
|
+
#
|
2891
|
+
# This is the so-called "reveal button".
|
2892
|
+
# ========================================================================= #
|
2893
|
+
def create_the_reveal_the_answer_button
|
2894
|
+
# ======================================================================= #
|
2895
|
+
# === @internal_hash[:button_reveal_the_answer] (answer tag)
|
2896
|
+
#
|
2897
|
+
# The reveal-button is created next, also known as the "answer button".
|
2898
|
+
# The mnemonic-key is set to "A", so that we can toggle between
|
2899
|
+
# "Q" and "A" for "Question" and "Answer" respectively.
|
2900
|
+
# ======================================================================= #
|
2901
|
+
_ = bold_button('Reveal the _Answer', self, true) { # This was the old emoji: ❗
|
2902
|
+
:the_button_reveal_the_answer_was_clicked
|
2903
|
+
}
|
2904
|
+
_.set_size_request(78, 30)
|
2905
|
+
#_.on_hover_lightblue
|
2906
|
+
_.hint = 'Click on this button in order to '\
|
2907
|
+
'reveal the answer to the current exam question at hand.'
|
2908
|
+
@internal_hash[:button_reveal_the_answer] = _
|
2909
|
+
end; alias create_the_reveal_button create_the_reveal_the_answer_button # === create_the_reveal_button
|
2910
|
+
|
2911
|
+
# ========================================================================= #
|
2912
|
+
# === set_exam_answer (answer tag)
|
2913
|
+
# ========================================================================= #
|
2914
|
+
def set_exam_answer(
|
2915
|
+
i = answer_is?,
|
2916
|
+
apply_these_filters = [:filter_away_tags]
|
2917
|
+
)
|
2918
|
+
i = sanitize_the_answer(i.to_s, apply_these_filters)
|
2919
|
+
i = ::Gtk.replace_all_URL_entries_in_this_string(i)
|
2920
|
+
i.lstrip!
|
2921
|
+
i.sub!(/A: /,'') if i.start_with? 'A: '
|
2922
|
+
# ================================================================= #
|
2923
|
+
# Replace all "(2) foo" entries with "(2) foo\n" entries.
|
2924
|
+
# ================================================================= #
|
2925
|
+
i = ::Studium.add_newlines_to_numbered_exam_question(i)
|
2926
|
+
@internal_hash[:exam_answer] = i
|
2927
|
+
textview2?.set_text(i)
|
2928
|
+
end; alias set_answer set_exam_answer # === set_answer
|
2929
|
+
|
2930
|
+
# ========================================================================= #
|
2931
|
+
# === exam_answer?
|
2932
|
+
# ========================================================================= #
|
2933
|
+
def exam_answer?
|
2934
|
+
@internal_hash[:exam_answer]
|
2935
|
+
end
|
2936
|
+
|
2937
|
+
# ========================================================================= #
|
2938
|
+
# === always_reveal_the_exam_answer_via_this_method
|
2939
|
+
#
|
2940
|
+
# This method will ALWAYS reveal the exam-answer.
|
2941
|
+
# ========================================================================= #
|
2942
|
+
def always_reveal_the_exam_answer_via_this_method
|
2943
|
+
set_exam_answer
|
2944
|
+
always_reset_the_delay_before_using_another_delay
|
2945
|
+
end
|
2946
|
+
|
2947
|
+
# ========================================================================= #
|
2948
|
+
# === may_we_reveal_the_answer_after_a_delay?
|
2949
|
+
# ========================================================================= #
|
2950
|
+
def may_we_reveal_the_answer_after_a_delay?
|
2951
|
+
@internal_hash[:may_we_reveal_the_answer_after_a_delay]
|
2952
|
+
end; alias may_we_reveal_the_answer? may_we_reveal_the_answer_after_a_delay? # === may_we_reveal_the_answer?
|
2953
|
+
|
2954
|
+
# ========================================================================= #
|
2955
|
+
# === do_sleep_now (sleep tag)
|
2956
|
+
# ========================================================================= #
|
2957
|
+
def do_sleep_now(
|
2958
|
+
i = :default,
|
2959
|
+
use_this_as_timeout = 0
|
2960
|
+
)
|
2961
|
+
case i
|
2962
|
+
# ======================================================================= #
|
2963
|
+
# === :default
|
2964
|
+
#
|
2965
|
+
# This will always obtain the value from the proper entry.
|
2966
|
+
# ======================================================================= #
|
2967
|
+
when :default,
|
2968
|
+
:use_the_correct_entry_for_the_delay
|
2969
|
+
i = entry_sleep_n_seconds?.text?
|
2970
|
+
end
|
2971
|
+
i = i.to_f # Always use a float here.
|
2972
|
+
# ======================================================================= #
|
2973
|
+
# An alternative to sleep() would be this:
|
2974
|
+
#
|
2975
|
+
# GLib::Timeout.add(use_this_as_timeout) {
|
2976
|
+
# @text_view_for_the_answer.set_text(answer)
|
2977
|
+
# false
|
2978
|
+
# }
|
2979
|
+
#
|
2980
|
+
# ======================================================================= #
|
2981
|
+
if use_this_as_timeout >= 0 and
|
2982
|
+
checkbox_shall_we_reveal_the_answer?.is_it_active?
|
2983
|
+
sleep(i)
|
2984
|
+
end
|
2985
|
+
end
|
2986
|
+
|
2987
|
+
# ========================================================================= #
|
2988
|
+
# === one_two_three (one_two_three tag)
|
2989
|
+
# ========================================================================= #
|
2990
|
+
def one_two_three(
|
2991
|
+
use_this_topic =
|
2992
|
+
exam_topic_from_the_correct_entry?
|
2993
|
+
)
|
2994
|
+
update_array_all_exam_questions
|
2995
|
+
if use_this_topic.empty?
|
2996
|
+
# ===================================================================== #
|
2997
|
+
# First protect against empty exam topics, with a helpful message to
|
2998
|
+
# the user.
|
2999
|
+
# ===================================================================== #
|
3000
|
+
do_popup_the_you_have_to_provide_an_exam_topic
|
3001
|
+
end
|
3002
|
+
unless ::Studium.is_this_exam_topic_available?(use_this_topic)
|
3003
|
+
# ===================================================================== #
|
3004
|
+
# Here we must notify the user that this exam-topic is not registered
|
3005
|
+
# aka not available.
|
3006
|
+
# ===================================================================== #
|
3007
|
+
popover_message( # Nudge the user here.
|
3008
|
+
text(
|
3009
|
+
' <b>⚠️</b> No exam-entry called <b>'+use_this_topic.to_s+
|
3010
|
+
'</b> is available. <b>⚠️</b>'
|
3011
|
+
),
|
3012
|
+
entry_for_the_exam_topic?
|
3013
|
+
).popup
|
3014
|
+
return
|
3015
|
+
end
|
3016
|
+
local_file = Studium.local_exam_file(use_this_topic)
|
3017
|
+
if File.exist?(local_file)
|
3018
|
+
update_hash_dataset_of_all_lectures
|
3019
|
+
# ===================================================================== #
|
3020
|
+
# (1) Pass the current exam topic into a method that will return
|
3021
|
+
# an Array.
|
3022
|
+
# ===================================================================== #
|
3023
|
+
# array = Studium.return_an_array_for_this_exam_topic(use_this_topic)
|
3024
|
+
dataset = Studium.read_in_unanswered_exam_questions_from_this_file(local_file)
|
3025
|
+
sample = dataset.sample
|
3026
|
+
n_exam_questions_in_total = Studium.n_exam_questions_in_this_topic?(File.basename(local_file))
|
3027
|
+
n_unanswered_exam_questions = dataset.size
|
3028
|
+
n_answered_exam_questions = n_exam_questions_in_total - n_unanswered_exam_questions
|
3029
|
+
# ===================================================================== #
|
3030
|
+
# (3) Next we must update various entries:
|
3031
|
+
# ===================================================================== #
|
3032
|
+
set_n_exam_questions_exist_in_total(n_exam_questions_in_total)
|
3033
|
+
set_n_unanswered_questions(n_unanswered_exam_questions)
|
3034
|
+
set_n_exam_questions_were_already_answered(n_answered_exam_questions)
|
3035
|
+
set_n_percentage(
|
3036
|
+
n_answered_exam_questions.to_f * 100.0 / n_exam_questions_in_total
|
3037
|
+
)
|
3038
|
+
if entry_percentage?.text?.to_f == 100.0
|
3039
|
+
# =================================================================== #
|
3040
|
+
# Handle the case where the exam-topic at hand has been answered
|
3041
|
+
# completely.
|
3042
|
+
# =================================================================== #
|
3043
|
+
bold_popover_message = label(
|
3044
|
+
"All questions have been answered for the topic <b>"\
|
3045
|
+
"#{current_exam_topic?}</b>.\n\n <b>Please choose another exam topic</b>.\n"
|
3046
|
+
)
|
3047
|
+
popover_message(
|
3048
|
+
bold_popover_message,
|
3049
|
+
button_ask_the_exam_question?
|
3050
|
+
).popup
|
3051
|
+
else
|
3052
|
+
# =================================================================== #
|
3053
|
+
# Next keep a backup-reference
|
3054
|
+
# =================================================================== #
|
3055
|
+
::Studium.set_last_exam_question_line(sample)
|
3056
|
+
# =================================================================== #
|
3057
|
+
# Keep a reference to the exam-question object:
|
3058
|
+
# =================================================================== #
|
3059
|
+
@internal_hash[:exam_question_object] = Studium::Exams::ExamQuestion.new(sample)
|
3060
|
+
@internal_hash[:may_we_reveal_the_answer_after_a_delay] = true
|
3061
|
+
clear_the_exam_answer
|
3062
|
+
last_exam_question_asked = current_exam_question?
|
3063
|
+
set_exam_question(
|
3064
|
+
@internal_hash[:exam_question_object].question?,
|
3065
|
+
:remove_tags
|
3066
|
+
)
|
3067
|
+
Thread.new {
|
3068
|
+
if may_we_reveal_the_answer_after_a_delay?
|
3069
|
+
do_sleep_now(:use_the_correct_entry_for_the_delay)
|
3070
|
+
unless last_exam_question_asked == current_exam_question?
|
3071
|
+
reveal_the_exam_answer(:but_only_if_we_may)
|
3072
|
+
end
|
3073
|
+
end
|
3074
|
+
}
|
3075
|
+
end
|
3076
|
+
else
|
3077
|
+
e "No file exists at `#{local_file}`."
|
3078
|
+
end
|
3079
|
+
end; alias update_n_questions one_two_three # === update_n_questions
|
3080
|
+
alias update_three_important_widgets one_two_three # === update_three_important_widgets
|
3081
|
+
|
3082
|
+
# ========================================================================= #
|
3083
|
+
# === reveal_the_exam_answer
|
3084
|
+
# ========================================================================= #
|
3085
|
+
def reveal_the_exam_answer(
|
3086
|
+
may_we_reveal_the_exam_answer = may_we_reveal_the_answer_after_a_delay?
|
3087
|
+
)
|
3088
|
+
case may_we_reveal_the_exam_answer
|
3089
|
+
# ========================================================================= #
|
3090
|
+
# === true
|
3091
|
+
# ========================================================================= #
|
3092
|
+
when true
|
3093
|
+
set_exam_answer
|
3094
|
+
# ========================================================================= #
|
3095
|
+
# === :but_only_if_we_may
|
3096
|
+
# ========================================================================= #
|
3097
|
+
when :but_only_if_we_may
|
3098
|
+
may_we_reveal_the_exam_answer = may_we_reveal_the_answer_after_a_delay?
|
3099
|
+
set_exam_answer if may_we_reveal_the_exam_answer
|
3100
|
+
end
|
3101
|
+
end; alias reveal_the_answer_to_the_exam_question set_exam_answer # === reveal_the_answer_to_the_exam_question
|
3102
|
+
|
3103
|
+
# ========================================================================= #
|
3104
|
+
# === exam_question?
|
3105
|
+
# ========================================================================= #
|
3106
|
+
def exam_question?
|
3107
|
+
@internal_hash[:exam_question]
|
3108
|
+
end; alias current_exam_question? exam_question? # === current_exam_question?
|
3109
|
+
|
3110
|
+
# ========================================================================= #
|
3111
|
+
# === button_reveal_the_answer_was_clicked
|
3112
|
+
# ========================================================================= #
|
3113
|
+
def button_reveal_the_answer_was_clicked
|
3114
|
+
if all_questions_have_been_answered_in_this_topic?
|
3115
|
+
notify_the_user_that_all_questions_have_been_answered_in_this_topic(
|
3116
|
+
current_topic?,
|
3117
|
+
_
|
3118
|
+
)
|
3119
|
+
else
|
3120
|
+
always_reveal_the_exam_answer_via_this_method
|
3121
|
+
we_may_not_reveal_the_exam_answer_anymore
|
3122
|
+
end
|
3123
|
+
end; alias the_button_reveal_the_answer_was_clicked button_reveal_the_answer_was_clicked # === the_button_reveal_the_answer_was_clicked
|
3124
|
+
|
3125
|
+
# ========================================================================= #
|
3126
|
+
# === return_button_ask_the_exam_question (ask tag)
|
3127
|
+
# ========================================================================= #
|
3128
|
+
def return_button_ask_the_exam_question(
|
3129
|
+
use_emoji = false
|
3130
|
+
)
|
3131
|
+
# ======================================================================= #
|
3132
|
+
# Add the ask-exam-question button next. Note that its click-event
|
3133
|
+
# is handled separately via a method call.
|
3134
|
+
#
|
3135
|
+
# The question mark emoji is Unicode Character "❓" (U+2753).
|
3136
|
+
# ======================================================================= #
|
3137
|
+
if use_emoji?
|
3138
|
+
_ = bold_button(mnemonic: 'Ask an exam _Question ❓')
|
3139
|
+
else
|
3140
|
+
_ = bold_button(mnemonic: 'Ask an exam _Question')
|
3141
|
+
end
|
3142
|
+
_.clear_background
|
3143
|
+
_.width_height(780, 38)
|
3144
|
+
_.pad2px
|
3145
|
+
_.hint =
|
3146
|
+
'Click on this button to ask an exam-question. '\
|
3147
|
+
'(Or, use alt+q as shortcut)'
|
3148
|
+
_.on_clicked {
|
3149
|
+
# ===================================================================== #
|
3150
|
+
# Determine what happens next when the ask-question button is clicked.
|
3151
|
+
# ===================================================================== #
|
3152
|
+
trigger_the_event_when_the_ask_exam_question_button_was_clicked
|
3153
|
+
}
|
3154
|
+
return _
|
3155
|
+
end; alias return_button_ask_an_exam_question return_button_ask_the_exam_question # === return_button_ask_an_exam_question
|
3156
|
+
|
3157
|
+
# ========================================================================= #
|
3158
|
+
# === we_may_reveal_the_exam_answer
|
3159
|
+
# ========================================================================= #
|
3160
|
+
def we_may_reveal_the_exam_answer
|
3161
|
+
@internal_hash[:may_we_reveal_the_answer_after_a_delay] = true
|
3162
|
+
end
|
3163
|
+
|
3164
|
+
# ========================================================================= #
|
3165
|
+
# === always_reset_the_delay_before_using_another_delay
|
3166
|
+
# ========================================================================= #
|
3167
|
+
def always_reset_the_delay_before_using_another_delay
|
3168
|
+
we_may_not_reveal_the_exam_answer_anymore
|
3169
|
+
end
|
3170
|
+
|
3171
|
+
# ========================================================================= #
|
3172
|
+
# === we_may_not_reveal_the_exam_answer_anymore
|
3173
|
+
# ========================================================================= #
|
3174
|
+
def we_may_not_reveal_the_exam_answer_anymore
|
3175
|
+
# ======================================================================= #
|
3176
|
+
# === @internal_hash[:may_we_reveal_the_answer_after_a_delay]
|
3177
|
+
# ======================================================================= #
|
3178
|
+
@internal_hash[:may_we_reveal_the_answer_after_a_delay] = false
|
3179
|
+
end
|
3180
|
+
|
3181
|
+
# ========================================================================= #
|
3182
|
+
# === consider_making_available_the_show_ten_aliases_widget
|
3183
|
+
# ========================================================================= #
|
3184
|
+
def consider_making_available_the_show_ten_aliases_widget
|
3185
|
+
# ======================================================================= #
|
3186
|
+
# The next if-clause must come after @internal_hash has been
|
3187
|
+
# defined.
|
3188
|
+
# ======================================================================= #
|
3189
|
+
if Object.const_defined?(:Roebe)
|
3190
|
+
begin
|
3191
|
+
require 'roebe/gui/gtk3/show_ten_aliases/show_ten_aliases.rb'
|
3192
|
+
@internal_hash[:show_ten_aliases] = ::Roebe::GUI::Gtk::ShowTenAliases.new
|
3193
|
+
rescue LoadError; end
|
3194
|
+
end
|
3195
|
+
end
|
3196
|
+
|
3197
|
+
# ========================================================================= #
|
3198
|
+
# === show_ten_aliases?
|
3199
|
+
# ========================================================================= #
|
3200
|
+
def show_ten_aliases?
|
3201
|
+
@internal_hash[:show_ten_aliases]
|
3202
|
+
end
|
3203
|
+
|
3204
|
+
# ========================================================================= #
|
3205
|
+
# === connect_the_skeleton (connect tag)
|
3206
|
+
# ========================================================================= #
|
3207
|
+
def connect_the_skeleton
|
3208
|
+
abort_on_exception
|
3209
|
+
add_the_status_icon
|
3210
|
+
r = create_window_or_runner(nil, width?, height?, title?)
|
3211
|
+
properly_prepare_this_window(
|
3212
|
+
r,
|
3213
|
+
return_the_default_hash_for_properly_preparing_this_window
|
3214
|
+
)
|
3215
|
+
do_style_all_buttons_uniformly
|
3216
|
+
do_assign_the_default_exam_topic_to_the_correct_entry
|
3217
|
+
let_the_scrolled_window_for_the_answer_parse_URLs
|
3218
|
+
deselect_the_entry_containing_the_exam_topic
|
3219
|
+
do_jump_into_the_entry_containing_the_current_exam_topic
|
3220
|
+
parse_the_commandline_arguments
|
3221
|
+
populate_the_main_grid(main_grid?) # Populate the main grid here next.
|
3222
|
+
populate_the_notebook_tab
|
3223
|
+
connect_the_notebook_tab(r)
|
3224
|
+
r.top_left
|
3225
|
+
set_parent_widget(r) # Designate it as the parent widget.
|
3226
|
+
enable_the_main_key_combinations
|
3227
|
+
r.add_context_menu_with_the_default_accel_group
|
3228
|
+
r.on_button_press_event { |widget, event|
|
3229
|
+
if ::Gtk.right_mouse_click?(event) # right mouse click event.
|
3230
|
+
_.context_menu?.popup_based_on_this_event(event)
|
3231
|
+
end
|
3232
|
+
}
|
3233
|
+
# r.automatic_size_then_automatic_title
|
3234
|
+
r.show_all
|
3235
|
+
the_first_notebook_tab_is_active
|
3236
|
+
r.enable_quick_exit
|
3237
|
+
r.set_default_size(width?, height?)
|
3238
|
+
# resize_the_notebook_tab_towards_the_primary_width_and_height
|
3239
|
+
run_main
|
3240
|
+
end
|
3241
|
+
|
3242
|
+
# ========================================================================= #
|
3243
|
+
# === run (run tag)
|
3244
|
+
# ========================================================================= #
|
3245
|
+
def run
|
3246
|
+
run_super
|
3247
|
+
end
|
3248
|
+
|
3249
|
+
# ========================================================================= #
|
3250
|
+
# === Studium::GUI::UniversalWidgets::ExamTrainer[]
|
3251
|
+
# ========================================================================= #
|
3252
|
+
def self.[](i = ARGV)
|
3253
|
+
new(i)
|
3254
|
+
end
|
3255
|
+
|
3256
|
+
# ========================================================================= #
|
3257
|
+
# Last but not least, add two "compatibility constants":
|
3258
|
+
# ========================================================================= #
|
3259
|
+
AskExamQuestion = ExamTrainer
|
3260
|
+
SimpleExamTrainer = ExamTrainer # And add a helper "alias" here.
|
3261
|
+
|
3262
|
+
end; end; end; end
|
3263
|
+
|
3264
|
+
if __FILE__ == $PROGRAM_NAME
|
3265
|
+
Studium::GUI::UniversalWidgets::ExamTrainer.new(ARGV)
|
3266
|
+
end # gtkexamtrainer 2
|