Skip to content
Snippets Groups Projects
Select Git revision
  • main default protected
1 result

alquiz-analysis-test.js

Blame
  • alquiz-analysis-test.js 65.46 KiB
    console.log("start alquiz analysis");
    //----------------QUIZ OBJECTS--------------------
    //WiMa SoSe 2023
    let quizObject = {
        groups: {
            start: "Start",
            s3: "3 Elementare Funktionen",
            s4: "4 Eigenschaften von Funktionen",
            s5: "5 Grenzwerte, Stetigkeit und Definitionslücken",
            s6: "6 Differentialrechnung I (Ableitungsregeln)",
            s7: "7 Differentialrechnung II (Anwendung)",
            s8: "8 Differentialrechnung in mehreren Variablen",
            s9: "9 Finanzmathematik I",
            s10: "10 Finanzmathematik II",
            s11: "11 Lineare Algebra Grundlagen",
            s12: "12 Weiterführende Matrixrechnung",
            s13: "13 Lineare Optimierung"
    
        },
        questions: {
            start: {
                name: "Home",
                group: "start",
                onsuccess: "s3_1",
                onfailure: "s3_1"
            },
            s3_1: {
                /*orange*/
                name: "Geradengleichung aufstellen 1",
                onsuccess: "s3_2",
                onfailure: "s3_2",
                variants: 4,
                color: "#fbc02d",
                filter: "invert(75%) sepia(32%) saturate(1024%) hue-rotate(352deg) brightness(102%) contrast(97%)"
            },
            s3_2: {
                /*red-orange*/
                name: "Geradengleichung aufstellen 2",
                onsuccess: "s3_3",
                onfailure: "s3_3",
                variants: 4,
                color: "#ff3d00",
                filter: "invert(31%) sepia(93%) saturate(4185%) hue-rotate(7deg) brightness(105%) contrast(110%)"
            },
            s3_3: {
                /*light orange*/
                name: "Scheitelpunkt aus Graphik ablesen",
                variants: 4,
                color: "#ffcc80",
                filter: "invert(94%) sepia(80%) saturate(1438%) hue-rotate(304deg) brightness(109%) contrast(101%)"
            },
            s3_4: {
                /*???*/
                name: "Erlösfunktion",
                variants: 4,
                color: "#CF7D35",
                filter: "invert(61%) sepia(55%) saturate(1048%) hue-rotate(339deg) brightness(88%) contrast(83%)"
            },
            s3_5: {
                /*???*/
                name: "Abschnittsweise def Funktion",
                variants: 4,
                color: "#34BC98",
                filter: "invert(64%) sepia(14%) saturate(1723%) hue-rotate(114deg) brightness(94%) contrast(93%)"
            },
            s3_6: {
                /*???*/
                name: "Gewinnfunktion aufstellen",
                variants: 4,
                color: "#E9FCEE",
                filter: "invert(100%) sepia(5%) saturate(4521%) hue-rotate(53deg) brightness(102%) contrast(96%)"
            },
            section_03_check_out_modified2_1: {
                name: "Angebot und Nachfrage",
                variants: 4,
                color: "#573036",
                filter: "invert(20%) sepia(11%) saturate(2292%) hue-rotate(301deg) brightness(88%) contrast(87%)",
                group: "s3"
            },
            section_03_check_out_modified2_2: {
                name: "Scheitelpunktform DOMAINUID 4 ACEA29",
                variants: 4,
                color: "#1BA1C7",
                filter: "invert(46%) sepia(89%) saturate(419%) hue-rotate(147deg) brightness(97%) contrast(96%)",
                group: "s3"
            },
            section_03_check_out_modified2_3: {
                name: "Erlösfunktion E(p) aufstellen",
                variants: 4,
                color: "#B38ABB",
                filter: "invert(67%) sepia(28%) saturate(423%) hue-rotate(244deg) brightness(85%) contrast(89%)",
                group: "s3"
            },
            section_03_check_out_modified2_4: {
                name: "Produktionsfunktion Def ök",
                variants: 4,
                color: "#D558A8",
                filter: "invert(50%) sepia(90%) saturate(907%) hue-rotate(290deg) brightness(87%) contrast(90%)",
                group: "s3"
            },
            section_03_check_out_modified2_5: {
                name: "Gewinnschwelle & Gewinngrenze Kap. 2.7 (TF) (Duplikat Malte)",
                variants: 4,
                color: "#1B5658",
                filter: "invert(26%) sepia(12%) saturate(2407%) hue-rotate(133deg) brightness(95%) contrast(86%)",
                group: "s3"
            },
            section_03_check_out_modified2_6: {
                name: "Definitionsbereich Ök. Kap. 2.7 (TF)",
                variants: 4,
                color: "#810311",
                filter: "invert(8%) sepia(64%) saturate(6140%) hue-rotate(346deg) brightness(93%) contrast(104%)",
                group: "s3"
            },
            section_04_check_in_modified_6: {
                name: "Nullstelle abspalten (Duplikat Malte)",
                variants: 4,
                color: "#74CD27",
                filter: "invert(68%) sepia(76%) saturate(507%) hue-rotate(42deg) brightness(95%) contrast(83%)",
                group: "s4"
            },
            s4_1: {
                /*very light green*/
                name: "NS reverse",
                onsuccess: "s4_2",
                onfailure: "s4_2",
                variants: 4,
                color: "#ccff90",
                filter: "invert(88%) sepia(22%) saturate(727%) hue-rotate(38deg) brightness(103%) contrast(107%)"
            },
            s4_2: {
                /*light green*/
                name: "NS bei Def",
                onsuccess: "s4_3",
                onfailure: "s4_3",
                variants: 4,
                color: "#b2ff59",
                filter: "invert(96%) sepia(97%) saturate(787%) hue-rotate(29deg) brightness(100%) contrast(108%)"
            },
            s4_3: {
                /*green*/
                name: "NS Wurzelfkt",
                onsuccess: "s4_4",
                onfailure: "s4_4",
                variants: 4,
                color: "#76ff03",
                filter: "invert(67%) sepia(72%) saturate(618%) hue-rotate(43deg) brightness(110%) contrast(103%)"
            },
            s4_4: {
                /*dimmed green*/
                name: "4.2 Polynom von Grad 4 her bestimmen",
                onsuccess: "s4_5",
                onfailure: "s4_5",
                variants: 4,
                color: "#64dd17",
                filter: "invert(79%) sepia(18%) saturate(3453%) hue-rotate(45deg) brightness(97%) contrast(91%)"
            },
            s4_5: {
                /*dark green*/
                name: "4.1 Funktion ablesen Grad 4",
                variants: 4,
                color: "#689f38",
                filter: "invert(54%) sepia(21%) saturate(1222%) hue-rotate(49deg) brightness(99%) contrast(83%)"
            },
            section_05_check_in_3: {
                name: "Grenzwert gegen inf ablesen",
                variants: 4,
                color: "#3CF48A",
                filter: "invert(72%) sepia(40%) saturate(699%) hue-rotate(89deg) brightness(101%) contrast(98%)",
                group: "s5"
            },
            section_05_check_in_modified2_7: {
                name: "Stetigkeit abschnittsw def Funktion (Duplikat Malte)",
                variants: 4,
                color: "#E249B2",
                filter: "invert(52%) sepia(64%) saturate(4425%) hue-rotate(292deg) brightness(93%) contrast(90%)",
                group: "s5"
            },
            section_05_check_in_6: {
                name: "Polstelle",
                variants: 4,
                color: "#77B211",
                filter: "invert(64%) sepia(52%) saturate(5261%) hue-rotate(48deg) brightness(107%) contrast(87%)",
                group: "s5"
            },
            section_05_check_in_modified2_8: {
                name: "Hebbare Lücke (Duplikat Malte)",
                variants: 4,
                color: "#D57774",
                filter: "invert(81%) sepia(50%) saturate(3032%) hue-rotate(305deg) brightness(86%) contrast(94%)",
                group: "s5"
            },
            section_05_check_in_8: {
                name: "Asymptote",
                variants: 4,
                color: "#FD9C80",
                filter: "invert(84%) sepia(53%) saturate(4565%) hue-rotate(313deg) brightness(115%) contrast(108%)",
                group: "s5"
            },
            section_05_check_out_1: {
                name: "Grenzwertaufgabe mögliche Polstellen (TU)",
                variants: 4,
                color: "#E249B2",
                filter: "invert(52%) sepia(64%) saturate(4425%) hue-rotate(292deg) brightness(93%) contrast(90%)",
                group: "s5"
            },
            section_05_check_out_2: {
                name: "Nullstellen und Polstellen von sqrt(P/Q-1) Kap. 2.4 & 2.6 (TF)",
                variants: 4,
                color: "#D57774",
                filter: "invert(81%) sepia(50%) saturate(3032%) hue-rotate(305deg) brightness(86%) contrast(94%)",
                group: "s5"
            },
            section_05_check_out_3: {
                name: "Nullstellen, Polstellen und Asymptoten einer gebrochenrationalen Funktion Kap. 2.4 & 2.6 (TF)",
                variants: 4,
                color: "#944A6C",
                filter: "invert(34%) sepia(25%) saturate(1028%) hue-rotate(280deg) brightness(96%) contrast(89%)",
                group: "s5"
            },
            section_05_check_out_5: {
                name: "Asymptote VWL",
                variants: 4,
                color: "#9B49A2",
                filter: "invert(35%) sepia(65%) saturate(573%) hue-rotate(248deg) brightness(92%) contrast(92%)",
                group: "s5"
            },
            section_05_check_out_6: {
                name: "Sprungstelle abschnittsw def Funktion",
                variants: 4,
                color: "#FA00D1",
                filter: "invert(54%) sepia(100%) saturate(7435%) hue-rotate(298deg) brightness(97%) contrast(127%)",
                group: "s5"
            },
            s6_1: {
                /*very light purple*/
                name: "Ableitungsfunktion Konstante",
                onsuccess: "s6_2",
                onfailure: "s6_2",
                variants: 4,
                color: "#ea80fc",
                filter: "invert(76%) sepia(34%) saturate(6604%) hue-rotate(231deg) brightness(102%) contrast(98%)"
            },
            s6_2: {
                /*light purple*/
                name: "Ableitungsfunktion Potenzfunktion",
                onsuccess: "s6_3",
                onfailure: "s6_3",
                variants: 4,
                color: "#e040fb",
                filter: "invert(37%) sepia(85%) saturate(3762%) hue-rotate(272deg) brightness(104%) contrast(97%)"
            },
            s6_3: {
                /*purple*/
                name: "Ableitungsfunktion Potenzfunktion gebrochener Exponent",
                variants: 4,
                color: "#d500f9",
                filter: "invert(26%) sepia(92%) saturate(2035%) hue-rotate(275deg) brightness(86%) contrast(153%)"
            },
            section_06_check_out_1: {
                name: "01 Summen- und konstanter Faktor",
                variants: 4,
                color: "#E2AFDA",
                filter: "invert(96%) sepia(86%) saturate(2059%) hue-rotate(203deg) brightness(96%) contrast(83%)",
                group: "s6"
            },
            section_06_check_out_2: {
                name: "02 Produktregel (TF)",
                variants: 4,
                color: "#EB3E57",
                filter: "invert(33%) sepia(19%) saturate(6570%) hue-rotate(328deg) brightness(97%) contrast(89%)",
                group: "s6"
            },
            section_06_check_out_3: {
                name: "03 Quotientenregel[neu](TF)",
                variants: 4,
                color: "#7E182C",
                filter: "invert(14%) sepia(27%) saturate(5843%) hue-rotate(328deg) brightness(98%) contrast(98%)",
                group: "s6"
            },
            section_06_check_out_4: {
                name: "05 Logarithmisches Ableiten",
                variants: 4,
                color: "#3960A7",
                filter: "invert(33%) sepia(56%) saturate(621%) hue-rotate(180deg) brightness(96%) contrast(95%)",
                group: "s6"
            },
            section_06_check_out_5: {
                name: "04 Kettenregel",
                variants: 4,
                color: "#E44FCD",
                filter: "invert(76%) sepia(58%) saturate(7362%) hue-rotate(280deg) brightness(93%) contrast(93%)",
                group: "s6"
            },
            section_07_check_in_1: {
                name: "Newtonverfahren",
                variants: 4,
                color: "#278495",
                filter: "invert(40%) sepia(10%) saturate(2946%) hue-rotate(142deg) brightness(107%) contrast(86%)",
                group: "s7"
            },
            section_07_check_in_2: {
                name: "Stationäre kritische Stelle",
                variants: 4,
                color: "#6D9D29",
                filter: "invert(53%) sepia(90%) saturate(357%) hue-rotate(43deg) brightness(87%) contrast(88%)",
                group: "s7"
            },
            section_07_check_in_modified2_4: {
                name: "Extrema und Wendestelle (Duplikat Malte)",
                variants: 4,
                color: "#A3717F",
                filter: "invert(51%) sepia(4%) saturate(3367%) hue-rotate(293deg) brightness(95%) contrast(75%)",
                group: "s7"
            },
            section_07_check_out_1: {
                name: "Grenzkostenfunktion",
                variants: 4,
                color: "#302FFF",
                filter: "invert(12%) sepia(96%) saturate(6720%) hue-rotate(247deg) brightness(102%) contrast(101%)",
                group: "s7"
            },
            section_07_check_out_2: {
                name: "Kurvendiskussion: gebrochenrationale Funktion",
                variants: 4,
                color: "#BBCBC4",
                filter: "invert(93%) sepia(3%) saturate(752%) hue-rotate(102deg) brightness(89%) contrast(85%)",
                group: "s7"
            },
            section_07_check_out_3: {
                name: "Maximalen Gewinn bestimmen",
                variants: 4,
                color: "#C5F99B",
                filter: "invert(100%) sepia(16%) saturate(5613%) hue-rotate(328deg) brightness(109%) contrast(92%)",
                group: "s7"
            },
            section_07_check_out_4: {
                name: "Optimierung Gewinn",
                variants: 4,
                color: "#A3717F",
                filter: "invert(51%) sepia(4%) saturate(3367%) hue-rotate(293deg) brightness(95%) contrast(75%)",
                group: "s7"
            },
            section_07_check_out_5: {
                name: "Optimierung Umsatz",
                variants: 4,
                color: "#395C44",
                filter: "invert(28%) sepia(21%) saturate(737%) hue-rotate(86deg) brightness(102%) contrast(87%)",
                group: "s7"
            },
            section_08_check_in_2: {
                name: "01 partiell Diff",
                variants: 4,
                color: "#10F046",
                filter: "invert(52%) sepia(95%) saturate(903%) hue-rotate(88deg) brightness(115%) contrast(90%)",
                group: "s8"
            },
            section_08_check_in_3: {
                name: "02 partiell Diff",
                variants: 4,
                color: "#E39FB2",
                filter: "invert(78%) sepia(4%) saturate(2863%) hue-rotate(296deg) brightness(88%) contrast(102%)",
                group: "s8"
            },
            section_08_check_out_2: {
                name: "06 partiell Diff",
                variants: 4,
                color: "#01D504",
                filter: "invert(43%) sepia(74%) saturate(1175%) hue-rotate(89deg) brightness(106%) contrast(114%)",
                group: "s8"
            },
            section_08_check_out_3: {
                name: "7.03 Det 3x3 Folie 16",
                variants: 4,
                color: "#C6F237",
                filter: "invert(96%) sepia(38%) saturate(4597%) hue-rotate(13deg) brightness(104%) contrast(89%)",
                group: "s8"
            },
            section_09_check_in_1: {
                name: "wann ver-x-facht sich K",
                variants: 4,
                color: "#B64537",
                filter: "invert(36%) sepia(12%) saturate(4301%) hue-rotate(324deg) brightness(93%) contrast(92%)",
                group: "s9"
            },
            section_09_check_in_2: {
                name: "Zinssatz i berechnen",
                variants: 4,
                color: "#8C9BF5",
                filter: "invert(64%) sepia(5%) saturate(3975%) hue-rotate(195deg) brightness(98%) contrast(96%)",
                group: "s9"
            },
            section_09_check_in_modified2_6: {
                name: "Barwert Zahlungsstrom (Duplikat Malte)(Kopiert aus Barwert Endwert Zahlungsstrom)",
                variants: 4,
                color: "#910602",
                filter: "invert(11%) sepia(63%) saturate(4965%) hue-rotate(14deg) brightness(103%) contrast(124%)",
                group: "s9"
            },
            section_09_check_in_modified2_7: {
                name: "Endwert Zahlungsstrom (Duplikat Malte)(Kopiert aus Barwert Endwert Zahlungsstrom)",
                variants: 4,
                color: "#C8B210",
                filter: "invert(72%) sepia(81%) saturate(1388%) hue-rotate(8deg) brightness(93%) contrast(87%)",
                group: "s9"
            },
            section_09_check_in_4: {
                name: "BW",
                variants: 4,
                color: "#9F6D55",
                filter: "invert(49%) sepia(5%) saturate(4049%) hue-rotate(334deg) brightness(89%) contrast(72%)",
                group: "s9"
            },
            section_09_check_in_5: {
                name: "EW",
                variants: 4,
                color: "#65D794",
                filter: "invert(80%) sepia(24%) saturate(818%) hue-rotate(88deg) brightness(91%) contrast(88%)",
                group: "s9"
            },
            section_09_check_in_6: {
                name: "Grundbegriffe",
                variants: 4,
                color: "#162095",
                filter: "invert(18%) sepia(23%) saturate(6913%) hue-rotate(217deg) brightness(94%) contrast(98%)",
                group: "s9"
            },
            section_09_check_out_1: {
                name: "Äquivalenzprinzip",
                variants: 4,
                color: "#DD5BE4",
                filter: "invert(46%) sepia(92%) saturate(1381%) hue-rotate(268deg) brightness(96%) contrast(85%)",
                group: "s9"
            },
            section_09_check_out_2: {
                name: "Effektivzins 1",
                variants: 4,
                color: "#A4FFDC",
                filter: "invert(91%) sepia(24%) saturate(563%) hue-rotate(85deg) brightness(103%) contrast(103%)",
                group: "s9"
            },
            section_09_check_out_3: {
                name: "Impl. Terminzinss.",
                variants: 4,
                color: "#BA9DCC",
                filter: "invert(70%) sepia(13%) saturate(705%) hue-rotate(233deg) brightness(94%) contrast(91%)",
                group: "s9"
            },
            section_09_check_out_4: {
                name: "Barwert und Endwert eines Zahlungsstroms",
                variants: 4,
                color: "#D34FDB",
                filter: "invert(45%) sepia(84%) saturate(1892%) hue-rotate(259deg) brightness(88%) contrast(94%)",
                group: "s9"
            },
            section_09_check_out_5: {
                name: "Endwert berechnen",
                variants: 4,
                color: "#910602",
                filter: "invert(11%) sepia(63%) saturate(4965%) hue-rotate(14deg) brightness(103%) contrast(124%)",
                group: "s9"
            },
            section_09_check_out_6: {
                name: "Kapitalwert bestimmen",
                variants: 4,
                color: "#C8B210",
                filter: "invert(72%) sepia(81%) saturate(1388%) hue-rotate(8deg) brightness(93%) contrast(87%)",
                group: "s9"
            },
            section_10_check_in_3: {
                name: "Rentenbarwertfaktor",
                variants: 4,
                color: "#3BDBAA",
                filter: "invert(92%) sepia(80%) saturate(1117%) hue-rotate(82deg) brightness(101%) contrast(69%)",
                group: "s10"
            },
            section_10_check_in_4: {
                name: "Rentenendwertfaktor",
                variants: 4,
                color: "#916F06",
                filter: "invert(43%) sepia(44%) saturate(6440%) hue-rotate(38deg) brightness(93%) contrast(95%)",
                group: "s10"
            },
            section_10_check_out_1: {
                name: "Rente n berechnen",
                variants: 4,
                color: "#C5B6C7",
                filter: "invert(80%) sepia(6%) saturate(490%) hue-rotate(246deg) brightness(91%) contrast(96%)",
                group: "s10"
            },
            section_10_check_out_modified2_6: {
                name: "Rentenbarwert, Rentenendwert (Duplikat Malte)",
                variants: 4,
                color: "#DA8376",
                filter: "invert(76%) sepia(76%) saturate(1360%) hue-rotate(305deg) brightness(86%) contrast(86%)",
                group: "s10"
            },
            section_10_check_out_3: {
                name: "Annuität berechnen",
                variants: 4,
                color: "#88383B",
                filter: "invert(27%) sepia(85%) saturate(439%) hue-rotate(308deg) brightness(84%) contrast(94%)",
                group: "s10"
            },
            section_10_check_out_4: {
                name: "Annutätentilgung, Tilgungsplan",
                variants: 4,
                color: "#71BC2E",
                filter: "invert(61%) sepia(95%) saturate(366%) hue-rotate(48deg) brightness(91%) contrast(84%)",
                group: "s10"
            },
            section_10_check_out_5: {
                name: "Laufzeit eines Darlehens",
                variants: 4,
                color: "#B20EE3",
                filter: "invert(22%) sepia(84%) saturate(4934%) hue-rotate(280deg) brightness(90%) contrast(116%)",
                group: "s10"
            },
            section_10_check_out_6: {
                name: "Restschuld eines Darlehens",
                variants: 4,
                color: "#C751FB",
                filter: "invert(41%) sepia(23%) saturate(6695%) hue-rotate(255deg) brightness(101%) contrast(97%)",
                group: "s10"
            },
            section_11_check_in_modified_7: {
                name: "MatrixMultiplikation",
                variants: 4,
                color: "#496108",
                filter: "invert(32%) sepia(17%) saturate(2438%) hue-rotate(36deg) brightness(96%) contrast(94%)",
                group: "s11"
            },
            section_11_check_in_modified_8: {
                name: "Transponieren",
                variants: 4,
                color: "#4DA97E",
                filter: "invert(54%) sepia(42%) saturate(476%) hue-rotate(100deg) brightness(100%) contrast(84%)",
                group: "s11"
            },
            section_11_check_in_modified_9: {
                name: "8.12 LGS Matrix-Form Folie 11 (5.1 LGS) (Duplikat Malte)",
                variants: 4,
                color: "#F8C255",
                filter: "invert(76%) sepia(85%) saturate(388%) hue-rotate(335deg) brightness(100%) contrast(95%)",
                group: "s11"
            },
            section_11_check_out_1: {
                name: "6.02 extern Matrizenrechnung",
                variants: 4,
                color: "#642E0E",
                filter: "invert(18%) sepia(12%) saturate(6525%) hue-rotate(354deg) brightness(97%) contrast(92%)",
                group: "s11"
            },
            section_11_check_out_2: {
                name: "6.03 Matrix-Vektor-Produkt",
                variants: 4,
                color: "#16C9D7",
                filter: "invert(67%) sepia(27%) saturate(3791%) hue-rotate(137deg) brightness(101%) contrast(83%)",
                group: "s11"
            },
            section_11_check_out_3: {
                name: "6.06 Addition von 2 Linearkombi",
                variants: 4,
                color: "#C768E5",
                filter: "invert(51%) sepia(33%) saturate(1489%) hue-rotate(239deg) brightness(96%) contrast(86%)",
                group: "s11"
            },
            section_11_check_out_4: {
                name: "6.08 Folie S.18 Matrixprodukt",
                variants: 4,
                color: "#DA8376",
                filter: "invert(76%) sepia(76%) saturate(1360%) hue-rotate(305deg) brightness(86%) contrast(86%)",
                group: "s11"
            },
            section_11_check_out_5: {
                name: "6.11 Operationen von 3 Matrizen",
                variants: 4,
                color: "#93916B",
                filter: "invert(62%) sepia(7%) saturate(1282%) hue-rotate(19deg) brightness(91%) contrast(88%)",
                group: "s11"
            },
            section_11_check_out_6: {
                name: "8.05 LGS 2x2",
                variants: 4,
                color: "#A4AA17",
                filter: "invert(57%) sepia(80%) saturate(463%) hue-rotate(23deg) brightness(95%) contrast(84%)",
                group: "s11"
            },
            section_11_check_out_7: {
                name: "8.06 LGS 3x3",
                variants: 4,
                color: "#62CB69",
                filter: "invert(99%) sepia(33%) saturate(3140%) hue-rotate(51deg) brightness(87%) contrast(79%)",
                group: "s11"
            },
            section_12_check_in_4: {
                name: "Inverse 2x2",
                variants: 4,
                color: "#CD51BA",
                filter: "invert(52%) sepia(46%) saturate(3109%) hue-rotate(280deg) brightness(85%) contrast(86%)",
                group: "s12"
            },
            section_12_check_in_5: {
                name: "Streichungsmatrix",
                variants: 4,
                color: "#877931",
                filter: "invert(51%) sepia(15%) saturate(1482%) hue-rotate(13deg) brightness(88%) contrast(89%)",
                group: "s12"
            },
            section_12_check_in_6: {
                name: "7.01 Det 2x2",
                variants: 4,
                color: "#DDB76F",
                filter: "invert(77%) sepia(47%) saturate(395%) hue-rotate(353deg) brightness(90%) contrast(91%)",
                group: "s12"
            },
            section_12_check_out_modified_1: {
                name: "7.03 Det 3x3 Folie 16",
                variants: 4,
                color: "#C14532",
                filter: "invert(29%) sepia(72%) saturate(1119%) hue-rotate(334deg) brightness(100%) contrast(91%)",
                group: "s12"
            },
            section_12_check_out_modified_2: {
                name: "Inverse 3x3",
                variants: 4,
                color: "#70C3CA",
                filter: "invert(72%) sepia(7%) saturate(2161%) hue-rotate(136deg) brightness(100%) contrast(88%)",
                group: "s12"
            },
            section_12_check_out_modified_3: {
                name: "Inverse singulär 3x3",
                variants: 4,
                color: "#6AC2E3",
                filter: "invert(67%) sepia(76%) saturate(312%) hue-rotate(161deg) brightness(93%) contrast(90%)",
                group: "s12"
            },
            section_12_check_out_modified_4: {
                name: "Laplace 4x4 (TF) (Duplikat Malte)",
                variants: 4,
                color: "#8F822E",
                filter: "invert(44%) sepia(53%) saturate(494%) hue-rotate(15deg) brightness(101%) contrast(89%)",
                group: "s12"
            },
            section_13_check_out_modified_1: {
                name: "Simplex Pivotelement Dualer Simplex",
                variants: 4,
                color: "#040237",
                filter: "invert(5%) sepia(65%) saturate(6178%) hue-rotate(225deg) brightness(82%) contrast(117%)",
                group: "s13"
            },
            section_13_check_out_modified_2: {
                name: "Simplex Pivotelement+Neue Basis angeben",
                variants: 4,
                color: "#AEC069",
                filter: "invert(74%) sepia(10%) saturate(1407%) hue-rotate(32deg) brightness(95%) contrast(97%)",
                group: "s13"
            },
            section_13_check_out_modified_3: {
                name: "Simplex dual",
                variants: 4,
                color: "#C6E2B2",
                filter: "invert(99%) sepia(25%) saturate(1040%) hue-rotate(32deg) brightness(96%) contrast(83%)",
                group: "s13"
            },
            section_13_check_out_modified_4: {
                name: "Simplex Tableau aufstellen (Duplikat Malte)",
                variants: 4,
                color: "#0EE073",
                filter: "invert(74%) sepia(55%) saturate(3187%) hue-rotate(95deg) brightness(100%) contrast(89%)",
                group: "s13",
                onsuccess: "_finish",
                onfailure: "_finish"
            }
        }
    };
    
    /*Preparatory courses WiSe 2023-24*/
    let quizObjectAsString = '{"groups": {"start": "Start", "t0_syn_1": "Syntax", "t1_fra_1": "Bruchrechnung", "t3_frabin_1": "Binom. Formeln", "t4_pq_1": "pq-Formel", "t5_rul_1": "Potenzrechenregeln", "t7_der_1": "Ableitungen"}, "questions": {"start": {"name": "Start", "group": "start"}, "t0_syn_1_a": {"name": "Gleichung eingeben (Multiplikation)", "variants": 4, "color": "#573036", "filter": "invert(20%) sepia(11%) saturate(2292%) hue-rotate(301deg) brightness(88%) contrast(87%)"}, "t0_syn_1_b": {"name": "Gleichung eingeben (Division)", "variants": 4, "color": "#1BA1C7", "filter": "invert(46%) sepia(89%) saturate(419%) hue-rotate(147deg) brightness(97%) contrast(96%)"}, "t0_syn_1_c": {"name": "Potenzen", "variants": 4, "color": "#B38ABB", "filter": "invert(67%) sepia(28%) saturate(423%) hue-rotate(244deg) brightness(85%) contrast(89%)"}, "t0_syn_1_d": {"name": "Rationale Ausdr\u00fccke", "variants": 3, "color": "#D558A8", "filter": "invert(50%) sepia(90%) saturate(907%) hue-rotate(290deg) brightness(87%) contrast(90%)"}, "t0_syn_1_e": {"name": "Wurzelzeichen", "variants": 4, "color": "#1B5658", "filter": "invert(26%) sepia(12%) saturate(2407%) hue-rotate(133deg) brightness(95%) contrast(86%)"}, "t0_syn_1_f": {"name": "Mehrere L\u00f6sungen", "variants": 4, "color": "#810311", "filter": "invert(8%) sepia(64%) saturate(6140%) hue-rotate(346deg) brightness(93%) contrast(104%)"}, "t0_syn_1_g": {"name": "Gleichung mehrschrittig l\u00f6sen", "variants": 4, "color": "#74CD27", "filter": "invert(68%) sepia(76%) saturate(507%) hue-rotate(42deg) brightness(95%) contrast(83%)"}, "t0_syn_1_h": {"name": "Griechische Buchstaben", "variants": 4, "color": "#3CF48A", "filter": "invert(72%) sepia(40%) saturate(699%) hue-rotate(89deg) brightness(101%) contrast(98%)"}, "t0_syn_1_i": {"name": "Syntax-Endboss", "variants": 4, "color": "#77B211", "filter": "invert(64%) sepia(52%) saturate(5261%) hue-rotate(48deg) brightness(107%) contrast(87%)"}, "t1_fra_1_bi-a": {"name": "K\u00fcrzen zweier einfacher Br\u00fcche", "variants": 4, "color": "#FD9C80", "filter": "invert(84%) sepia(53%) saturate(4565%) hue-rotate(313deg) brightness(115%) contrast(108%)"}, "t1_fra_1_bi-b": {"name": "K\u00fcrzen zweier Br\u00fcche mit Variablen", "variants": 4, "color": "#E249B2", "filter": "invert(52%) sepia(64%) saturate(4425%) hue-rotate(292deg) brightness(93%) contrast(90%)"}, "t1_fra_1_bi-c": {"name": "K\u00fcrzen zweier Br\u00fcche mit Variablen und Zahlen", "variants": 4, "color": "#D57774", "filter": "invert(81%) sepia(50%) saturate(3032%) hue-rotate(305deg) brightness(86%) contrast(94%)"}, "t1_fra_1_bi-d": {"name": "K\u00fcrzen zweier Br\u00fcche mit Termen", "variants": 4, "color": "#944A6C", "filter": "invert(34%) sepia(25%) saturate(1028%) hue-rotate(280deg) brightness(96%) contrast(89%)"}, "t1_fra_1_bii-a": {"name": "Einfachen Bruch erweitern", "variants": 4, "color": "#9B49A2", "filter": "invert(35%) sepia(65%) saturate(573%) hue-rotate(248deg) brightness(92%) contrast(92%)"}, "t1_fra_1_bii-b": {"name": "Bruch mit Variablen erweitern", "variants": 4, "color": "#FA00D1", "filter": "invert(54%) sepia(100%) saturate(7435%) hue-rotate(298deg) brightness(97%) contrast(127%)"}, "t1_fra_1_bii-c": {"name": "Bruch mit Variablen und Zahlen erweitern", "variants": 4, "color": "#E2AFDA", "filter": "invert(96%) sepia(86%) saturate(2059%) hue-rotate(203deg) brightness(96%) contrast(83%)"}, "t1_fra_1_ca": {"name": "Einfache Addition von Br\u00fcchen", "variants": 4, "color": "#EB3E57", "filter": "invert(33%) sepia(19%) saturate(6570%) hue-rotate(328deg) brightness(97%) contrast(89%)"}, "t1_fra_1_cb": {"name": "Addition von Br\u00fcchen mit Variablen und gleichem Nenner", "variants": 4, "color": "#7E182C", "filter": "invert(14%) sepia(27%) saturate(5843%) hue-rotate(328deg) brightness(98%) contrast(98%)"}, "t1_fra_1_cc": {"name": "Addition von Br\u00fcchen mit Variablen und unterschiedlichen Nennern", "variants": 4, "color": "#3960A7", "filter": "invert(33%) sepia(56%) saturate(621%) hue-rotate(180deg) brightness(96%) contrast(95%)"}, "t1_fra_1_cd": {"name": "Addition von Br\u00fcchen mit einer Variablen und unterschiedlichen Nennern", "variants": 4, "color": "#E44FCD", "filter": "invert(76%) sepia(58%) saturate(7362%) hue-rotate(280deg) brightness(93%) contrast(93%)"}, "t1_fra_1_ce": {"name": "Addition von Br\u00fcchen mit Variablen und unterschiedlichen Nennern I", "variants": 4, "color": "#278495", "filter": "invert(40%) sepia(10%) saturate(2946%) hue-rotate(142deg) brightness(107%) contrast(86%)"}, "t1_fra_1_cf": {"name": "Addition von Br\u00fcchen mit Variablen und unterschiedlichen Nennern II", "variants": 4, "color": "#6D9D29", "filter": "invert(53%) sepia(90%) saturate(357%) hue-rotate(43deg) brightness(87%) contrast(88%)"}, "t1_fra_1_da": {"name": "Multiplikation zweier einfacher Br\u00fcche", "variants": 4, "color": "#302FFF", "filter": "invert(12%) sepia(96%) saturate(6720%) hue-rotate(247deg) brightness(102%) contrast(101%)"}, "t1_fra_1_db": {"name": "Multiplikation zweier Br\u00fcche mit Variablen", "variants": 4, "color": "#BBCBC4", "filter": "invert(93%) sepia(3%) saturate(752%) hue-rotate(102deg) brightness(89%) contrast(85%)"}, "t1_fra_1_dc": {"name": "Multiplikation Bruch mit Zahlen, Bruch mit Variablen, Ganzzahl", "variants": 4, "color": "#C5F99B", "filter": "invert(100%) sepia(16%) saturate(5613%) hue-rotate(328deg) brightness(109%) contrast(92%)"}, "t1_fra_1_dd": {"name": "Multiplikation zweier Br\u00fcche mit Termen", "variants": 4, "color": "#A3717F", "filter": "invert(51%) sepia(4%) saturate(3367%) hue-rotate(293deg) brightness(95%) contrast(75%)"}, "t1_fra_1_de": {"name": "Einfacher Doppelbruch", "variants": 4, "color": "#395C44", "filter": "invert(28%) sepia(21%) saturate(737%) hue-rotate(86deg) brightness(102%) contrast(87%)"}, "t1_fra_1_df": {"name": "Bruch und Geteilt-Rechnung", "variants": 4, "color": "#10F046", "filter": "invert(52%) sepia(95%) saturate(903%) hue-rotate(88deg) brightness(115%) contrast(90%)"}, "t1_fra_1_dg": {"name": "Doppelbruch mit Zahlen und Variablen", "variants": 4, "color": "#E39FB2", "filter": "invert(78%) sepia(4%) saturate(2863%) hue-rotate(296deg) brightness(88%) contrast(102%)"}, "t1_fra_1_dh": {"name": "Doppelbruch mit Termen", "variants": 4, "color": "#23F5CC", "filter": "invert(100%) sepia(72%) saturate(2181%) hue-rotate(84deg) brightness(106%) contrast(91%)"}, "t1_fra_1_ea": {"name": "Bruchrechnung Kombination I", "variants": 4, "color": "#01D504", "filter": "invert(43%) sepia(74%) saturate(1175%) hue-rotate(89deg) brightness(106%) contrast(114%)"}, "t1_fra_1_eb": {"name": "Bruchrechnung Kombination II", "variants": 4, "color": "#C6F237", "filter": "invert(96%) sepia(38%) saturate(4597%) hue-rotate(13deg) brightness(104%) contrast(89%)"}, "t1_fra_1_ec": {"name": "Bruchrechnung Kombination III", "variants": 4, "color": "#B64537", "filter": "invert(36%) sepia(12%) saturate(4301%) hue-rotate(324deg) brightness(93%) contrast(92%)"}, "t3_frabin_1_g": {"name": "Binomische Formeln Ia - Erste binomische Formel", "variants": 4, "color": "#8C9BF5", "filter": "invert(64%) sepia(5%) saturate(3975%) hue-rotate(195deg) brightness(98%) contrast(96%)"}, "t3_frabin_1_h": {"name": "Binomische Formeln Ib - Zweite binomische Formel", "variants": 4, "color": "#9F6D55", "filter": "invert(49%) sepia(5%) saturate(4049%) hue-rotate(334deg) brightness(89%) contrast(72%)"}, "t3_frabin_1_i": {"name": "Binomische Formeln Ic - Dritte binomische Formel", "variants": 4, "color": "#65D794", "filter": "invert(80%) sepia(24%) saturate(818%) hue-rotate(88deg) brightness(91%) contrast(88%)"}, "t3_frabin_1_j": {"name": "Binomische Formeln I - Anwendungsaufgabe", "variants": 4, "color": "#162095", "filter": "invert(18%) sepia(23%) saturate(6913%) hue-rotate(217deg) brightness(94%) contrast(98%)"}, "t3_frabin_1_k": {"name": "Bruchrechenregeln Ig2 - Bruch mit binomischem Term erweitern 2 (copy)", "variants": 3, "color": "#DD5BE4", "filter": "invert(46%) sepia(92%) saturate(1381%) hue-rotate(268deg) brightness(96%) contrast(85%)"}, "t4_pq_1_a": {"name": "p-q-Formal Ia - Termumformung", "variants": 4, "color": "#A4FFDC", "filter": "invert(91%) sepia(24%) saturate(563%) hue-rotate(85deg) brightness(103%) contrast(103%)"}, "t4_pq_1_b": {"name": "p-q-Formel Ib - pq-Formel", "variants": 4, "color": "#BA9DCC", "filter": "invert(70%) sepia(13%) saturate(705%) hue-rotate(233deg) brightness(94%) contrast(91%)"}, "t4_pq_1_c": {"name": "p-q-Formel I - Endboss", "variants": 4, "color": "#D34FDB", "filter": "invert(45%) sepia(84%) saturate(1892%) hue-rotate(259deg) brightness(88%) contrast(94%)"}, "t5_rul_1_a": {"name": "Potenzrechenregeln Ia \u2013 Exponenten addieren", "variants": 2, "color": "#910602", "filter": "invert(11%) sepia(63%) saturate(4965%) hue-rotate(14deg) brightness(103%) contrast(124%)"}, "t5_rul_1_b": {"name": "Potenzrechenregeln Ib \u2013 Exponenten subtrahieren", "variants": 2, "color": "#C8B210", "filter": "invert(72%) sepia(81%) saturate(1388%) hue-rotate(8deg) brightness(93%) contrast(87%)"}, "t5_rul_1_c": {"name": "Potenzrechenregeln Ic - Wurzel als Potenz darstellen", "variants": 4, "color": "#3BDBAA", "filter": "invert(92%) sepia(80%) saturate(1117%) hue-rotate(82deg) brightness(101%) contrast(69%)"}, "t5_rul_1_d": {"name": "Potenzrechenregeln Id \u2013 Exponenten multiplizieren", "variants": 2, "color": "#916F06", "filter": "invert(43%) sepia(44%) saturate(6440%) hue-rotate(38deg) brightness(93%) contrast(95%)"}, "t5_rul_1_e": {"name": "Potenzrechenregeln Ie - Potenzrechenregeln anwenden", "variants": 2, "color": "#C5B6C7", "filter": "invert(80%) sepia(6%) saturate(490%) hue-rotate(246deg) brightness(91%) contrast(96%)"}, "t5_rul_1_f": {"name": "Potenzrechenregeln I - Endboss", "variants": 2, "color": "#88383B", "filter": "invert(27%) sepia(85%) saturate(439%) hue-rotate(308deg) brightness(84%) contrast(94%)"}, "t7_der_1_a": {"name": "Ganzzahlige Summanden ableiten", "variants": 4, "color": "#71BC2E", "filter": "invert(61%) sepia(95%) saturate(366%) hue-rotate(48deg) brightness(91%) contrast(84%)"}, "t7_der_1_b": {"name": "Gebrochenrationale Summanden ableiten", "variants": 4, "color": "#B20EE3", "filter": "invert(22%) sepia(84%) saturate(4934%) hue-rotate(280deg) brightness(90%) contrast(116%)"}, "t7_der_1_c": {"name": "Produkte ableiten I", "variants": 4, "color": "#C751FB", "filter": "invert(41%) sepia(23%) saturate(6695%) hue-rotate(255deg) brightness(101%) contrast(97%)"}, "t7_der_1_d": {"name": "Produkte ableiten II", "variants": 4, "color": "#496108", "filter": "invert(32%) sepia(17%) saturate(2438%) hue-rotate(36deg) brightness(96%) contrast(94%)"}, "t7_der_1_e": {"name": "Division ableiten I", "variants": 4, "color": "#4DA97E", "filter": "invert(54%) sepia(42%) saturate(476%) hue-rotate(100deg) brightness(100%) contrast(84%)"}, "t7_der_1_f": {"name": "Division ableiten II", "variants": 4, "color": "#F8C255", "filter": "invert(76%) sepia(85%) saturate(388%) hue-rotate(335deg) brightness(100%) contrast(95%)"}, "t7_der_1_g": {"name": "Kettenregel I", "variants": 4, "color": "#642E0E", "filter": "invert(18%) sepia(12%) saturate(6525%) hue-rotate(354deg) brightness(97%) contrast(92%)"}, "t7_der_1_h": {"name": "Kettenregel II", "variants": 4, "color": "#16C9D7", "filter": "invert(67%) sepia(27%) saturate(3791%) hue-rotate(137deg) brightness(101%) contrast(83%)"}, "t7_der_1_i": {"name": "Gemischtes I", "variants": 4, "color": "#C768E5", "filter": "invert(51%) sepia(33%) saturate(1489%) hue-rotate(239deg) brightness(96%) contrast(86%)"}, "t7_der_1_j": {"name": "Gemischtes II", "variants": 4, "color": "#DA8376", "filter": "invert(76%) sepia(76%) saturate(1360%) hue-rotate(305deg) brightness(86%) contrast(86%)"}, "t7_der_1_k": {"name": "Gemischtes III", "variants": 4, "color": "#93916B", "filter": "invert(62%) sepia(7%) saturate(1282%) hue-rotate(19deg) brightness(91%) contrast(88%)"}, "t7_der_1_l": {"name": "Gemischtes IV", "variants": 4, "color": "#A4AA17", "filter": "invert(57%) sepia(80%) saturate(463%) hue-rotate(23deg) brightness(95%) contrast(84%)"}, "t7_der_1_m": {"name": "Gemischtes V", "variants": 4, "color": "#62CB69", "filter": "invert(99%) sepia(33%) saturate(3140%) hue-rotate(51deg) brightness(87%) contrast(79%)"}, "t7_der_1_n": {"name": "Gemischtes VI", "variants": 4, "color": "#CD51BA", "filter": "invert(52%) sepia(46%) saturate(3109%) hue-rotate(280deg) brightness(85%) contrast(86%)"}}}';
    quizObject = JSON.parse(quizObjectAsString);
    
    var processedAttempts = 0;
    var allAttempts = 0;
    //var CryptoObj = 
    var fetches = {};
    var urls = {};
    
    //Paginate quiz objects
    let page = 0;
    for(let i in quizObject.questions) {
        quizObject.questions[i].page = page;
        let toAdd = quizObject.questions[i].variants == undefined ? 1 : quizObject.questions[i].variants;
        page += toAdd;
    }
    
    let Encoder = new TextEncoder();
    //Hash functions to encrypt user id
    async function sha256(message) {
        // encode as UTF-8
        const msgBuffer = Encoder.encode(message);
    
        // hash the message
        const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);
        
        // convert ArrayBuffer to Array
        const hashArray = Array.from(new Uint8Array(hashBuffer));
    
        // convert bytes to hex string
        const hashHex = hashArray.map(b => ('00' + b.toString(16)).slice(-2)).join('');
        return hashHex;
    }
    
    let monthTranslator = {
        "Januar":0,
        "Februar":1,
        "März":2,
        "März":2,
        "April":3,
        "Mai":4,
        "Juni":5,
        "Juli":6,
        "August":7,
        "September":8,
        "Oktober":9,
        "November":10,
        "Dezember":11
    };
    //----------------CLASSES-------------------------
    class CQuestionAttempt {
        constructor(timestampOrString, questionId, action, outcome, variant) {
            this.variant = variant;
            if(this.variant == undefined) {
                this.variant = 1;
            }
            //Check timestampOrString
            this.timestamp;
            if(Number.isInteger(timestampOrString)) {
                this.timestamp = timestampOrString;
            }
            else if(timestampOrString instanceof String || typeof timestampOrString === 'string') {
                //German with full months written?
                this.timestamp = this.getTimestampFromGermanTime(timestampOrString);
            }
            this.questionId = questionId;
            this.action = action;
            this.outcome = outcome;
            if(!this.timestamp) {
                console.log("timestring could not be converted");
                this.timestamp = timestampOrString;
            }
        }
    
        /*getTimestampFromGermanTime(timestring) {
            let matchAllResult = timestring.matchAll(/(\d+)\. (.{4,}?) (\d{2,4}), (\d+):(\d+):(\d+)/g);
            if(!matchAllResult) {
                //probably not german
                return false;
            }
    
            let matches = Array.from(matchAllResult)[0];
            //1: day of month, 2: month in words, 3: year, 4: hours, 5: minutes, 6:seconds
            if(monthTranslator[matches[2]] == undefined) {
                //probably not german
                return false;
            }
    
            let time = new Date(matches[3], monthTranslator[matches[2]], matches[1], matches[4], matches[5], matches[6]);
            if(!time) {
                return false;
            }
            return time.getTime();
        }*/
        getTimestampFromGermanTime(timestring) {
            let hasAmPm = ((timestring.search(/ am/i) + timestring.search(/ pm/i)) > -2);
            let time;
            if(hasAmPm == true) {
                console.log("special handling for AM / PM time string is neccessary");
                return false;
            }
            //let matchAllResult = timestring.matchAll(/(\d+)\. (.{4,}?) (\d{2,4}), (\d+):(\d+):(\d+)/g);
            let matchAllResult = timestring.matchAll(/(\d+)\.* (.{4,}?) (\d{2,4}),* (\d+):(\d+):*(\d*)/g);
            let matches = Array.from(matchAllResult)[0];
            if(!matches) {
                //Give it another try, matching e. g. 18/09/23, 11:55:42
                matchAllResult = timestring.matchAll(/(\d+)[\.\/-](\d+)[\.\/-](\d+),* (\d+):(\d+):*(\d*)/g);
                matches = Array.from(matchAllResult)[0];
    
                if(!matches) {
                    //probably not german, try Date
                    //console.log(timestring)
                    time = new Date(timestring);
                }
                else {
                    let year = matches[3]
                    if(matches[3].length == 2) {
                        year = "20"+year;
                    }
                    let month = parseInt(matches[2])-1;
                    time = new Date(year, month, matches[1], matches[4], matches[5], matches[6]);
                }
            }
            else {
                //1: day of month, 2: month in words, 3: year, 4: hours, 5: minutes, 6:seconds
                if(monthTranslator[matches[2]] == undefined) {
                    //probably not german
                    return false;
                }
    
                time = new Date(matches[3], monthTranslator[matches[2]], matches[1], matches[4], matches[5], matches[6]);
            }
            if(isNaN(time)) {
                return false;
            }
            return time.getTime();
        }
    }
    
    class CUser {
        constructor(idOrNode) {
            let object = this;
            this.Parser = new DOMParser();
            this.QuestionAttempts = [];
    
            if(idOrNode instanceof String || typeof idOrNode === 'string') {
                this.id = idOrNode;
            }
            else if(idOrNode instanceof Element) {
                if(idOrNode.tagName == "TR") {
                    let idNode = idOrNode.querySelector(".c3");
                    if(idNode == undefined) {
                        console.log("no id found for this row");
                        return;
                    }
                    this.id = idNode.innerHTML;
    
                    let reviewLink = idOrNode.querySelector(".reviewlink");
                    if(reviewLink == undefined) {
                        console.log("no review link found for this row");
                        return;
                    }
                    this.addAttempt(reviewLink.href);
                }
            }
            else {
                console.log("unknown type");
            }
        }
        
        addAttempt(reviewUrl) {
            let object = this;
            if(reviewUrl == undefined) {
                return;
            }
            fetch(reviewUrl)
            .then(function(response) {
                return response.text();
            })
            .then(function(htmlText) {
                let fetchedPage = object.Parser.parseFromString(htmlText, "text/html");
                
                let allQuestions = fetchedPage.querySelectorAll(".que");
                if(allQuestions.length <= 1) {
                    //Sometimes, default is to show questions by pages. In this case, reload the page with all questions shown.
                    //Get url from .othernav or simply add "&showall=1" to the url.
                    return fetch(reviewUrl+"&showall=1").then(function(responseShowAll) {
                        return responseShowAll.text();
                    })
                    .then(function(htmlTextShowAll) {
                        let fetchedPageShowAll = object.Parser.parseFromString(htmlTextShowAll, "text/html");
                        //console.log(fetchedPageShowAll.querySelectorAll(".que"));
                        return fetchedPageShowAll;
                    });
                }
                else {
                    return fetchedPage;
                }
            })
            .then(function(fetchedPageOrShowAll) {
                //test = fetchedPageOrShowAll;
                let allQuestions = fetchedPageOrShowAll.querySelectorAll(".que");
                //console.log(allQuestions);
                if(allQuestions.length < 1) {
                    throw new Error("bad amount of questions");
                }
    
                //Assume each question is shown, even the unattended. Then, allQuestions can be paginated as in quizObject.
                //Loop through questions and variants in quiz object and append question information one by one.
                let page = 0;
                let questionIds = Object.keys(quizObject.questions);
                let lastQuestionId = questionIds[questionIds.length-1];
                let lastPage = quizObject.questions[lastQuestionId].page+quizObject.questions[lastQuestionId].variants-1;
                for(let questionName in quizObject.questions) {
                    var variants = quizObject.questions[questionName].variants == undefined ? 1 : quizObject.questions[questionName].variants;
    
                    for(let i = 0;i<variants;i++) {
                        //console.log(page);
                        let relevantQuestionNode = allQuestions[page];
                        //fetch all question attempts from history
                        var previousQuestionAttemptUrls = relevantQuestionNode.querySelectorAll(".history a[id*='action_link']:not(.history tr a)");
                        if(previousQuestionAttemptUrls.length > 0) {
                            //console.log("but in "+questionName+" it's "+previousQuestionAttemptUrls.length);
                            for(var j=0;j<previousQuestionAttemptUrls.length;j++) {
                                let fetchId = Date.now().toString(36) + Math.random().toString(36).slice(2);
                                fetches[fetchId] = 0;
                                urls[fetchId] = previousQuestionAttemptUrls[j].href;
                                fetch(previousQuestionAttemptUrls[j].href)
                                .then(function(response) {
                                    return response.text();
                                })
                                .then(function(htmlText) {
                                    //console.log("and after fetch it's "+previousQuestionAttemptUrls.length);
                                    let fetchedQuestionAttemptHistoryPage = object.Parser.parseFromString(htmlText, "text/html");
                                    let infoTable = fetchedQuestionAttemptHistoryPage.querySelector(".que .history .generaltable");
                                    if(infoTable == undefined) {
                                        console.log(fetchedQuestionAttemptHistoryPage);
                                        throw new Error("no table found error 2 for history number "+j);
                                    }
                                    let questionAttemptInfo = object.getQuestionAttemptInfoFromTable(infoTable);
                                    object.QuestionAttempts.push(new CQuestionAttempt(questionAttemptInfo.timestring, questionName, questionAttemptInfo.action, questionAttemptInfo.status, i+1));
    
                                    fetches[fetchId] = 1;
                                })
                                .catch(function(error) {
                                    console.log("Error fetching question attempt from history.");
                                    console.log(error);
                                });
                            }
                        }
    
                        //Fetch most recent question attempt. This one is found on the overview page without clicking.
                        let shownTable = allQuestions[page].querySelector(".generaltable");
                        if(shownTable == undefined) {
                            throw new Error("no table found error 1 for for question "+questionName);
                        }
                        let questionAttemptInfo = object.getQuestionAttemptInfoFromTable(shownTable);
                        object.QuestionAttempts.push(new CQuestionAttempt(questionAttemptInfo.timestring, questionName, questionAttemptInfo.action, questionAttemptInfo.status, i+1));
    
                        if(page == lastPage) {
                            processedAttempts++;
                            console.log("(Nearly) processed "+processedAttempts+" of "+allAttempts+ " attempts. (Fetch amount now at "+Object.keys(fetches).length+")");
                        }
    
                        page++;
                    }
                }
            })
            .catch(function(error) {
                console.log("error in promise chain");
                console.log(error);
            });
        }
    
        getQuestionAttemptInfoFromTable(tableNode) {
            if(tableNode == undefined) {
                return false;
            }
            let lastRow = tableNode.querySelector(".current.lastrow");
            if(lastRow == undefined) {
                return false;
            }
            //Assume c1 be the time, c2 be the action text and c3 be the status
            let timestringNode = lastRow.querySelector(".c1");
            let actionNode = lastRow.querySelector(".c2");
            let statusNode = lastRow.querySelector(".c3");
    
            if(timestringNode == undefined || statusNode == undefined) {
                return false;
            }
    
            return {timestring:timestringNode.innerHTML, action:(actionNode.innerHTML == undefined ? "" : actionNode.innerHTML), status:statusNode.innerHTML};
        }
    
        simpleGetAttemptsAsCSV(addUserCol, addHeadingRow, encryptId, getRidOfInitializationAttempts) {
            let csvString = "";
            if(addUserCol == undefined) {
                addUserCol = true;
            }
            if(addHeadingRow == undefined) {
                addHeadingRow = false;
            }
            /*if(encryptId == undefined) {
                encryptId = true;
            }*/
            encryptId = false;
            let id = this.id;
            i/*f(encryptId == true) {
                //Because by default, Moodle's export results function returns Matrikelnummern as int, we encrypt the int too to ensure consistent results.
                let toEncrypt = parseInt(id);
                id = await sha256(""+toEncrypt);
            }*/
            if(getRidOfInitializationAttempts == undefined) {
                getRidOfInitializationAttempts = true;
            }
    
    
            if(addHeadingRow == true) {
                if(addUserCol == true) {
                    csvString += "user_id;";
                }
                csvString += "timestamp;question_id;variant;action;outcome;next_timestamp;next_question_id;next_variant\n";
            }
    
            //Sort attempts by time. To add next question attribute.
            let SortedAttempts = this.getSanitizedAttempts(getRidOfInitializationAttempts);
    
            for(let i=0;i<SortedAttempts.length;i++) {
                let relevantVars = []
                if(addUserCol == true) {
                    relevantVars.push(id);
                }
                relevantVars.push(SortedAttempts[i].timestamp, SortedAttempts[i].questionId, SortedAttempts[i].variant,  SortedAttempts[i].action, SortedAttempts[i].outcome);
                if(SortedAttempts[i+1] != undefined) {
                    relevantVars.push(SortedAttempts[i+1].timestamp, SortedAttempts[i+1].questionId, SortedAttempts[i+1].variant);
                    //relevantVars.push(SortedAttempts[i+1].questionId)
                }
                else {
                    relevantVars.push("", "_finish", "");
                }
                //csvString += "\""+relevantVars.join("\";\"")+"\"\n";
                csvString += "'"+relevantVars.join("';'")+"'\n";
            }
    
            //csvString += "\n";
            return csvString;
        }
    
        async getAttemptsAsCSV(addUserCol, addHeadingRow, encryptId, getRidOfInitializationAttempts) {
            let csvString = "";
            if(addUserCol == undefined) {
                addUserCol = true;
            }
            if(addHeadingRow == undefined) {
                addHeadingRow = false;
            }
            if(encryptId == undefined) {
                encryptId = true;
            }
            let id = this.id;
            if(encryptId == true) {
                //Because by default, Moodle's export results function returns Matrikelnummern as int, we encrypt the int too to ensure consistent results.
                let toEncrypt = parseInt(id);
                if(!isNaN(toEncrypt)) {
                    id = await sha256(""+toEncrypt);
                }
                else {
                    //In case not the Matricel Id is listed, the e-mail-address will be hashed here to identify unique users.
                    id = await sha256(""+id);
                }
            }
            if(getRidOfInitializationAttempts == undefined) {
                getRidOfInitializationAttempts = true;
            }
    
    
            if(addHeadingRow == true) {
                if(addUserCol == true) {
                    csvString += "user_id;";
                }
                csvString += "timestamp;question_id;variant;action;outcome;next_timestamp;next_question_id;next_variant\n";
            }
    
            //Sort attempts by time. To add next question attribute.
            let SortedAttempts = this.getSanitizedAttempts(getRidOfInitializationAttempts);
    
            for(let i=0;i<SortedAttempts.length;i++) {
                let relevantVars = []
                if(addUserCol == true) {
                    relevantVars.push(id);
                }
                relevantVars.push(SortedAttempts[i].timestamp, SortedAttempts[i].questionId, SortedAttempts[i].variant,  SortedAttempts[i].action, SortedAttempts[i].outcome);
                if(SortedAttempts[i+1] != undefined) {
                    relevantVars.push(SortedAttempts[i+1].timestamp, SortedAttempts[i+1].questionId, SortedAttempts[i+1].variant);
                    //relevantVars.push(SortedAttempts[i+1].questionId)
                }
                else {
                    relevantVars.push("", "_finish", "");
                }
                csvString += "'"+relevantVars.join("';'")+"'\n";
            }
    
            //csvString += "\n";
            return csvString;
        }
    
        /*Leave the calculations up to python.
        async getOverallInfoAsCSVRow(addHeadingRow, encryptId, getRidOfInitializationAttempts) {
            let csvString = "";
            if(addHeadingRow == undefined) {
                addHeadingRow = false;
            }
            if(encryptId == undefined) {
                encryptId = true;
            }
            let id = this.id;
            if(encryptId == true) {
                id = await sha256(this.id);
                
            }
            if(getRidOfInitializationAttempts == undefined) {
                getRidOfInitializationAttempts = true;
            }
    
            if(addHeadingRow == true) {
                if(addUserCol == true) {
                    csvString += "id,";
                }
                csvString += "started_working_amount,solved_amount,calls,first_action,last_action";
            }
    
            //Sort attempts by time. To add next question attribute.
            let SortedAttempts = this.getSanitizedAttempts(getRidOfInitializationAttempts);
    
            if(getRidOfInitializationAttempts == true) {
                let initialTimestamp = SortedAttempts[0].timestamp;
                let SortedAttemptsCopy = JSON.parse(JSON.stringify(SortedAttempts));
                SortedAttempts = [];
                for(let j=0;j<SortedAttemptsCopy.length;j++) {
                    if(SortedAttemptsCopy[j].timestamp != initialTimestamp) {
                        SortedAttempts.push(SortedAttemptsCopy[j]);
                    }
                }
            }
    
            for(let i=0;i<SortedAttempts.length;i++) {
                let relevantVars = []
                if(addUserCol == true) {
                    relevantVars.push(id);
                }
                relevantVars.push(SortedAttempts[i].timestamp, SortedAttempts[i].questionId, SortedAttempts[i].variant,  SortedAttempts[i].action, SortedAttempts[i].outcome);
                if(SortedAttempts[i+1] != undefined) {
                    relevantVars.push(SortedAttempts[i+1].timestamp, SortedAttempts[i+1].questionId, SortedAttempts[i+1].variant);
                    //relevantVars.push(SortedAttempts[i+1].questionId)
                }
                else {
                    relevantVars.push("", "_finish", "");
                }
                csvString += "\""+relevantVars.join("\";\"")+"\"\n";
            }
    
            //csvString += "\n";
            return csvString;
        }*/
    
        getSanitizedAttempts(getRidOfInitializationAttempts, getRidOfFinishedAttemptAttempts) {
            //Will sort the question attempts and get rid of initialization attempts.
            if(getRidOfInitializationAttempts == undefined) {
                getRidOfInitializationAttempts = true;
            }
            if(getRidOfFinishedAttemptAttempts == undefined) {
                getRidOfFinishedAttemptAttempts = true;
            }
            
            if(this.QuestionAttempts.length == 0) {
                console.log("error: no attempts to sanitize");
                return [];
            }
    
            let SanitizedAttempts = JSON.parse(JSON.stringify(this.QuestionAttempts));
            SanitizedAttempts.sort(function(a, b) { return parseInt(a.timestamp) - parseInt(b.timestamp); });
    
            if(getRidOfFinishedAttemptAttempts == true) {
                let SanitizedAttemptsCopy = JSON.parse(JSON.stringify(SanitizedAttempts));
                SanitizedAttempts = [];
                for(let i=0;i<SanitizedAttemptsCopy.length;i++) {
                    if(SanitizedAttemptsCopy[i].action != "Versuch beendet" && SanitizedAttemptsCopy[i].action != "Attempt finished") {
                        SanitizedAttempts.push(SanitizedAttemptsCopy[i]);
                    }
                }
            }
    
            if(!getRidOfInitializationAttempts) {
                return SanitizedAttempts;
            }
    
            let initialTimestamp = SanitizedAttempts[0].timestamp;
            let SanitizedAttemptsCopy = JSON.parse(JSON.stringify(SanitizedAttempts));
            SanitizedAttempts = [];
            for(let j=0;j<SanitizedAttemptsCopy.length;j++) {
                if(SanitizedAttemptsCopy[j].timestamp != initialTimestamp) {
                    SanitizedAttempts.push(SanitizedAttemptsCopy[j]);
                }
            }
            return SanitizedAttempts;
        }
    }
    
    
    //----------------MAIN-------------------------
    //Classic theme?
    //let tableIdentifier = "#responses";
    //Alternative for HS BO Moodle Theme?
    
    let manualStart = false;
    
    let tableIdentifier = "#attempts";
    let allRows = document.querySelectorAll(tableIdentifier+" tbody tr:not(.emptyrow)");
    //Test group specific: Exclude those, who clicked through the questions as in control group design due to technically disappearing game design after re-initialization of the learning activity. This may not be neccessary any more as of 2023-09-19 due to fallback solutions.
    let i=0;
    allRows.forEach(function(row) {
        let icons = row.querySelectorAll(".icon.fa");
        if(icons.length > 1 /* Don't exclude those, who submitted their exercise and hence have one icon for each exercise. */ && row.classList.contains("gradedattempt") == false) {
            console.log("Bad icon amount in row "+i+" ("+icons.length+"). Is excluded.");
            row.classList.add("exclude");
        }
        i++;
    }); 
    //console.log(allRows);
    
    var rows = document.querySelectorAll(tableIdentifier+" tbody tr:not(.emptyrow):not(.exclude)");
    //console.log(rows);
    
    allAttempts = rows.length;
    var Users = {};
    
    console.log("There are "+allAttempts+" rows. Run 'loadUsers();' or 'loadUsers(from, to);' or 'loadUsersStepwise();' to start processing.");
    
    //for(let i=29;i<30;i++) {
    /*for(let i=0;i<rows.length;i++) {
        let id;
        let idNode = rows[i].querySelector(".c3");
        if(idNode == undefined) {
            console.log("no id found for row "+i);
            continue;
        }
        id = idNode.innerHTML;
        if(id == "") {
            console.log("empty id in row "+i);
            continue;
        }
        
        if(Users[id] == undefined) {
            Users[id] = new CUser(rows[i]);
        }
        else {
            //Get review link and add attempt to already existing user.
            let reviewLink = rows[i].querySelector(".reviewlink");
            if(reviewLink != undefined) {
                Users[id].addAttempt(reviewLink.href);
            }
            else {
                console.log("Found user row of already existing user, but didn't find review link ("+id+").");
            }
        }
    }*/
    
    function loadUsers(from, to) {
        if(from == undefined) {
            from = 0;
        }
        if(to == undefined) {
            to = rows.length;
        }
    
        for(let i=from;i<to;i++) {
            let id;
            let idNode = rows[i].querySelector(".c3");
            if(idNode == undefined) {
                console.log("no id found for row "+i);
                continue;
            }
            id = idNode.innerHTML;
            if(id == "") {
                console.log("empty id in row "+i);
                continue;
            }
            
            if(Users[id] == undefined) {
                Users[id] = new CUser(rows[i]);
            }
            else {
                //Get review link and add attempt to already existing user.
                let reviewLink = rows[i].querySelector(".reviewlink");
                if(reviewLink != undefined) {
                    Users[id].addAttempt(reviewLink.href);
                }
                else {
                    console.log("Found user row of already existing user, but didn't find review link ("+id+").");
                }
            }
        }
    }
    
    var csvText = "";
    
    function simpleLoadCSV(UsersObject) {
        if(UsersObject == undefined) {
            if(Users == undefined) {
                return false;
            }
            UsersObject = Users;
        }
        csvText = "";
        let first = true;
        for(let i in UsersObject) {
            csvText += UsersObject[i].getAttemptsAsCSV(true, first, false);
            if(first == true) { first = false; }
        }
    }
    
    async function loadCSV(UsersObject) {
        if(UsersObject == undefined) {
            if(Users == undefined) {
                return false;
            }
            UsersObject = Users;
        }
        //let csvText = "";
        csvText = "";
        let first = true;
        for(let i in UsersObject) {
            csvText += await UsersObject[i].getAttemptsAsCSV(true, first);
            if(first == true) { first = false; }
        }
        return csvText;
        /*let c = document.createElement("a");
        c.download = "alquiz-analysis-control.csv";
        var t = new Blob([csvText], {
            type: "text/plain"
        });
        c.href = window.URL.createObjectURL(t);
        c.click();*/
    }
    
    function downloadCSV() {
        let c = document.createElement("a");
        c.download = "alquiz-analysis-test.csv";
        var t = new Blob([csvText], {
            type: "text/plain"
        });
        c.href = window.URL.createObjectURL(t);
        c.click();
    }
    
    async function loadAndDownloadCSV() {
        return await loadCSV().then(function(response) {
            downloadCSV();
            return response;
        });
    }
    
    async function simpleDownloadCSV() {
        if(UsersObject == undefined) {
            if(Users == undefined) {
                return false;
            }
            UsersObject = Users;
        }
        //let csvText = "";
        csvText = "";
        let first = true;
        for(let i in UsersObject) {
            csvText += await UsersObject[i].getAttemptsAsCSV(true, first, false);
            if(first == true) { first = false; }
        }
        let c = document.createElement("a");
        c.download = "alquiz-analysis-test-quick.csv";
        var t = new Blob([csvText], {
            type: "text/plain"
        });
        c.href = window.URL.createObjectURL(t);
        c.click();
    }
    
    function getFetchState() {
        /*let overallFetches = Object.keys(fetches).length;
        let solvedFetches = 0;
        for(let fetchId in fetches) {
            if(fetches[fetchId] == 1) {
                solvedFetches++;
            }
        }*/
        infoObject = getFetchStateMachineReadable();
        console.log("Fetched "+infoObject.solved+" of "+infoObject.overall+".");
    }
    
    function getFetchStateMachineReadable() {
        let overallFetches = Object.keys(fetches).length;
        let solvedFetches = 0;
        for(let fetchId in fetches) {
            if(fetches[fetchId] == 1) {
                solvedFetches++;
            }
        }
        return {"solved":solvedFetches, "overall":overallFetches};
    }
    
    //----------------TEST--------------------------
    function showAllAttemptsOf018345157(questionId) {
        if(questionId == undefined) {
            questionId = "start";
        }
        let OnlyStartAttempts = [];
        if(Users["018345157"] != undefined) {
            Users["018345157"].QuestionAttempts.forEach(function(QuestionAttempt) {
                if(QuestionAttempt.questionId == questionId) {
                    OnlyStartAttempts.push(QuestionAttempt);
                }
            });
        }
        console.log(OnlyStartAttempts);
    }
    
    var processCount = 0;
    function processStepByStep() {
        fetchInfoObject = getFetchStateMachineReadable();
        if(fetchInfoObject.solved == fetchInfoObject.overall) {
            if(processCount == allAttempts) {
                console.log("Successfully processed all attempts.")
                if(interval != undefined) {
                    clearInterval(interval);
                }
                return;
            }
            else {
                loadUsers(processCount, processCount+1);
                processCount++;
            }
        }
    }
    
    var interval;
    function loadUsersStepwise() {
        interval = setInterval(processStepByStep, 5000);
    }