Save current state before exploring first DRS commit

Preserving current work:
- Modified DRS modules and factories
- Updated content and progress tracking
- Deprecated PhraseModule moved to archive

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
StillHammer 2025-10-12 08:47:23 +08:00
parent 44f43324cf
commit 3da40c0d73
12 changed files with 3203 additions and 351 deletions

View File

@ -205,8 +205,9 @@
"elaborate": { "user_language": "élaboré", "type": "adjective", "pronunciation": "/ɪˈlæbərət/" }, "elaborate": { "user_language": "élaboré", "type": "adjective", "pronunciation": "/ɪˈlæbərət/" },
"sophisticated": { "user_language": "sophistiqué", "type": "adjective", "pronunciation": "/səˈfɪstɪkeɪtɪd/" } "sophisticated": { "user_language": "sophistiqué", "type": "adjective", "pronunciation": "/səˈfɪstɪkeɪtɪd/" }
}, },
"lessons": { "texts": [
"lesson1": { {
"id": "text1",
"title": "Foundations of Research Methodology", "title": "Foundations of Research Methodology",
"content": "Research methodology constitutes the systematic theoretical analysis of the methods applied to a field of study. It encompasses the comprehensive framework of epistemological, ontological, and phenomenological considerations that guide rigorous academic inquiry. Contemporary researchers must navigate complex paradigmatic tensions between positivist empirical approaches and constructivist interpretive methodologies. The theoretical foundations of quantitative research emphasize statistical significance, experimental control, and generalizability of findings across diverse populations. Conversely, qualitative investigation prioritizes comprehensive understanding, contextual interpretation, and the nuanced exploration of subjective phenomena. Modern academic discourse increasingly advocates for sophisticated mixed-methods approaches that synthesize both quantitative measurement and qualitative analysis. Triangulation strategies enhance validity through multiple data sources, theoretical perspectives, and methodological approaches. Researchers must demonstrate meticulous attention to bias reduction, sample representativeness, and ethical considerations throughout the investigation process. The operationalization of abstract concepts requires precise definitional frameworks and robust measurement instruments. Contemporary methodology emphasizes reproducibility, transparency, and rigorous peer review processes. Advanced statistical techniques including regression modeling, multivariate analysis, and machine learning algorithms enable sophisticated pattern recognition and predictive modeling. Researchers increasingly utilize computational processing power for extensive dataset analysis and complex simulation procedures.", "content": "Research methodology constitutes the systematic theoretical analysis of the methods applied to a field of study. It encompasses the comprehensive framework of epistemological, ontological, and phenomenological considerations that guide rigorous academic inquiry. Contemporary researchers must navigate complex paradigmatic tensions between positivist empirical approaches and constructivist interpretive methodologies. The theoretical foundations of quantitative research emphasize statistical significance, experimental control, and generalizability of findings across diverse populations. Conversely, qualitative investigation prioritizes comprehensive understanding, contextual interpretation, and the nuanced exploration of subjective phenomena. Modern academic discourse increasingly advocates for sophisticated mixed-methods approaches that synthesize both quantitative measurement and qualitative analysis. Triangulation strategies enhance validity through multiple data sources, theoretical perspectives, and methodological approaches. Researchers must demonstrate meticulous attention to bias reduction, sample representativeness, and ethical considerations throughout the investigation process. The operationalization of abstract concepts requires precise definitional frameworks and robust measurement instruments. Contemporary methodology emphasizes reproducibility, transparency, and rigorous peer review processes. Advanced statistical techniques including regression modeling, multivariate analysis, and machine learning algorithms enable sophisticated pattern recognition and predictive modeling. Researchers increasingly utilize computational processing power for extensive dataset analysis and complex simulation procedures.",
"questions": [ "questions": [
@ -242,7 +243,8 @@
} }
] ]
}, },
"lesson2": { {
"id": "text2",
"title": "Advanced Statistical Analysis and Data Interpretation", "title": "Advanced Statistical Analysis and Data Interpretation",
"content": "Statistical analysis represents the cornerstone of empirical research methodology, encompassing sophisticated techniques for data exploration, hypothesis testing, and inferential reasoning. Contemporary researchers utilize advanced algorithms for pattern recognition, anomaly detection, and predictive modeling across extensive datasets. The distribution characteristics of variables determine appropriate statistical procedures, including parametric and non-parametric approaches for hypothesis evaluation. Correlation analysis reveals relationships between variables, while causation requires controlled experimental manipulation and rigorous confounding variable elimination. Regression modeling enables prediction and explanation of dependent variable variance through multiple independent predictors. Cluster analysis identifies natural groupings within populations, facilitating targeted intervention strategies and segmentation approaches. Longitudinal studies track cohorts across time, revealing developmental patterns and causal sequences. Cross-sectional comparative designs enable efficient population sampling at specific temporal points. Measurement validity encompasses content, construct, and criterion-related approaches for instrument development. Reliability coefficients assess consistency across time, interrater agreement, and internal consistency measures. Confidence intervals provide probability-based ranges for population parameter estimation. Effect sizes quantify practical significance beyond statistical significance testing. Meta-analysis synthesizes findings across multiple independent studies, enhancing generalizability and statistical power. Advanced modeling techniques including structural equation modeling, hierarchical linear modeling, and machine learning algorithms enable sophisticated hypothesis testing with complex nested data structures.", "content": "Statistical analysis represents the cornerstone of empirical research methodology, encompassing sophisticated techniques for data exploration, hypothesis testing, and inferential reasoning. Contemporary researchers utilize advanced algorithms for pattern recognition, anomaly detection, and predictive modeling across extensive datasets. The distribution characteristics of variables determine appropriate statistical procedures, including parametric and non-parametric approaches for hypothesis evaluation. Correlation analysis reveals relationships between variables, while causation requires controlled experimental manipulation and rigorous confounding variable elimination. Regression modeling enables prediction and explanation of dependent variable variance through multiple independent predictors. Cluster analysis identifies natural groupings within populations, facilitating targeted intervention strategies and segmentation approaches. Longitudinal studies track cohorts across time, revealing developmental patterns and causal sequences. Cross-sectional comparative designs enable efficient population sampling at specific temporal points. Measurement validity encompasses content, construct, and criterion-related approaches for instrument development. Reliability coefficients assess consistency across time, interrater agreement, and internal consistency measures. Confidence intervals provide probability-based ranges for population parameter estimation. Effect sizes quantify practical significance beyond statistical significance testing. Meta-analysis synthesizes findings across multiple independent studies, enhancing generalizability and statistical power. Advanced modeling techniques including structural equation modeling, hierarchical linear modeling, and machine learning algorithms enable sophisticated hypothesis testing with complex nested data structures.",
"questions": [ "questions": [
@ -278,7 +280,8 @@
} }
] ]
}, },
"lesson3": { {
"id": "text3",
"title": "Qualitative Research and Interpretive Methodologies", "title": "Qualitative Research and Interpretive Methodologies",
"content": "Qualitative research methodology embraces interpretive paradigms that prioritize comprehensive understanding of complex social phenomena through detailed narrative analysis and contextual interpretation. Ethnographic approaches involve extensive participant observation, immersive fieldwork, and cultural interpretation through prolonged engagement with research participants. Phenomenological investigations explore lived experiences, consciousness structures, and subjective meaning-making processes through in-depth interview techniques. Grounded theory methodology emphasizes systematic data collection, theoretical sampling, and iterative analysis for theory development from empirical observations. Hermeneutical approaches focus on textual interpretation, discourse analysis, and the historical contextualization of cultural artifacts. Narrative research examines personal stories, biographical accounts, and identity construction through temporal sequence analysis. Case study methodology provides comprehensive investigation of specific instances, organizations, or phenomena within natural settings. Action research integrates investigation with practical intervention, emphasizing collaborative participation and social change objectives. Data collection techniques include semi-structured interviews, focus group discussions, participant observation, and document analysis procedures. Coding procedures involve open, axial, and selective approaches for pattern identification and categorical development. Triangulation strategies enhance credibility through multiple data sources, investigator perspectives, and theoretical frameworks. Member checking validates interpretations through participant feedback and collaborative meaning verification. Transferability replaces generalizability through detailed contextual description and theoretical conceptualization. Confirmability ensures objectivity through reflexive journaling, audit trails, and peer debriefing processes. Advanced qualitative analysis software facilitates systematic coding, pattern recognition, and theoretical model development.", "content": "Qualitative research methodology embraces interpretive paradigms that prioritize comprehensive understanding of complex social phenomena through detailed narrative analysis and contextual interpretation. Ethnographic approaches involve extensive participant observation, immersive fieldwork, and cultural interpretation through prolonged engagement with research participants. Phenomenological investigations explore lived experiences, consciousness structures, and subjective meaning-making processes through in-depth interview techniques. Grounded theory methodology emphasizes systematic data collection, theoretical sampling, and iterative analysis for theory development from empirical observations. Hermeneutical approaches focus on textual interpretation, discourse analysis, and the historical contextualization of cultural artifacts. Narrative research examines personal stories, biographical accounts, and identity construction through temporal sequence analysis. Case study methodology provides comprehensive investigation of specific instances, organizations, or phenomena within natural settings. Action research integrates investigation with practical intervention, emphasizing collaborative participation and social change objectives. Data collection techniques include semi-structured interviews, focus group discussions, participant observation, and document analysis procedures. Coding procedures involve open, axial, and selective approaches for pattern identification and categorical development. Triangulation strategies enhance credibility through multiple data sources, investigator perspectives, and theoretical frameworks. Member checking validates interpretations through participant feedback and collaborative meaning verification. Transferability replaces generalizability through detailed contextual description and theoretical conceptualization. Confirmability ensures objectivity through reflexive journaling, audit trails, and peer debriefing processes. Advanced qualitative analysis software facilitates systematic coding, pattern recognition, and theoretical model development.",
"questions": [ "questions": [
@ -314,7 +317,7 @@
} }
] ]
} }
}, ],
"dialogs": [ "dialogs": [
{ {
"id": "conference_presentation", "id": "conference_presentation",
@ -477,113 +480,272 @@
] ]
} }
], ],
"sentences": { "phrases": {
"practice": [ "The methodology demonstrates rigorous scientific standards": {
"The methodology demonstrates rigorous scientific standards.", "user_language": "La méthodologie démontre des normes scientifiques rigoureuses",
"Researchers utilize sophisticated statistical techniques for comprehensive analysis.", "context": "methodology",
"Quantitative data provides empirical evidence for theoretical hypotheses.", "pronunciation": "/ðə ˌmeθəˈdɒlədʒi ˈdemənstreɪts ˈrɪɡərəs ˌsaɪənˈtɪfɪk ˈstændərdz/"
"Qualitative interpretation reveals nuanced patterns in participant narratives.", },
"The experimental design controls confounding variables effectively.", "Researchers utilize sophisticated statistical techniques": {
"Statistical significance indicates meaningful relationships between measured variables.", "user_language": "Les chercheurs utilisent des techniques statistiques sophistiquées",
"Longitudinal studies track developmental changes across extended timeframes.", "context": "research-methods",
"Cross-sectional comparisons examine differences between demographic populations.", "pronunciation": "/rɪˈːtʃərz ˈjuːtəlaɪz səˈfɪstɪkeɪtɪd stəˈtɪstɪkəl tekˈniːks/"
"Triangulation strategies enhance validity through multiple data sources.", },
"Systematic literature review synthesizes existing theoretical knowledge comprehensively.", "Quantitative data provides empirical evidence": {
"Operational definitions specify measurement procedures for abstract concepts.", "user_language": "Les données quantitatives fournissent des preuves empiriques",
"Random sampling ensures population representativeness and generalizability.", "context": "data-analysis",
"Ethical considerations protect participant welfare throughout investigations.", "pronunciation": "/ˈkwɒntɪtətɪv ˈdeɪtə prəˈvaɪdz ɪmˈpɪrɪkəl ˈevɪdəns/"
"Correlation analysis reveals associations without establishing causation.", },
"Regression modeling predicts outcomes through multiple predictor variables.", "Qualitative interpretation reveals nuanced patterns": {
"The paradigm influences methodological choices and theoretical interpretations.", "user_language": "L'interprétation qualitative révèle des modèles nuancés",
"Empirical observations support or refute proposed theoretical frameworks.", "context": "qualitative-research",
"Phenomenological analysis explores subjective experiences and meaning-making.", "pronunciation": "/ˈkwɒlɪtətɪv ɪnˌtɜːprɪˈteɪʃən rɪˈviːlz ˈnjuːɑːnst ˈpætənz/"
"Grounded theory develops from systematic data collection and analysis.", },
"Hermeneutical interpretation examines cultural texts and historical contexts.", "The experimental design controls confounding variables": {
"The algorithm processes large datasets for pattern recognition.", "user_language": "Le design expérimental contrôle les variables confondantes",
"Simulation modeling tests theoretical assumptions before empirical implementation.", "context": "experimental-design",
"Validation procedures confirm measurement accuracy and theoretical relevance.", "pronunciation": "/ði ɪkˌsperɪˈmentəl dɪˈzaɪn kənˈtrəʊlz kənˈfaʊndɪŋ ˈvɛəriəbəlz/"
"Replication studies verify original findings across different contexts.", },
"Meta-analysis combines results from multiple independent investigations.", "Statistical significance indicates meaningful relationships": {
"Effect sizes quantify practical significance beyond statistical testing.", "user_language": "La signification statistique indique des relations significatives",
"Confidence intervals estimate population parameters with probability ranges.", "context": "statistics",
"Bias reduction requires careful attention to methodological procedures.", "pronunciation": "/stəˈtɪstɪkəl sɪɡˈnɪfɪkəns ˈɪndɪkeɪts ˈmiːnɪŋfəl rɪˈleɪʃənʃɪps/"
"The framework integrates multiple theoretical perspectives comprehensively.", },
"Operationalization transforms abstract concepts into measurable variables.", "Longitudinal studies track developmental changes": {
"Distribution characteristics determine appropriate statistical procedures.", "user_language": "Les études longitudinales suivent les changements développementaux",
"Anomaly detection identifies unusual patterns in complex datasets.", "context": "research-design",
"The criterion establishes standards for measurement and evaluation.", "pronunciation": "/ˌlɒŋɡɪˈtjuːdɪnəl ˈstʌdiz træk dɪˌveləpˈmentəl ˈtʃeɪndʒɪz/"
"Multiple criteria guide comprehensive assessment and decision-making.", },
"The phenomenon requires sophisticated analytical approaches.", "Cross-sectional comparisons examine demographic differences": {
"Various phenomena demonstrate consistent patterns across contexts.", "user_language": "Les comparaisons transversales examinent les différences démographiques",
"Assessment procedures evaluate participant performance objectively.", "context": "comparative-research",
"Comprehensive evaluation examines multiple dimensions simultaneously.", "pronunciation": "/krɒs ˈsekʃənəl kəmˈpærɪsənz ɪɡˈzæmɪn ˌdeməˈɡræfɪk ˈdɪfərənsɪz/"
"Interpretation depends on theoretical frameworks and contextual factors.", },
"Conceptualization provides foundation for empirical investigation.", "Triangulation strategies enhance validity": {
"Epistemological assumptions influence research design and methodology.", "user_language": "Les stratégies de triangulation améliorent la validité",
"Ontological considerations determine reality conceptualization and measurement.", "context": "validation",
"Phenomenology examines consciousness structures and lived experiences.", "pronunciation": "/traɪˌæŋɡjuˈleɪʃən ˈstrætɪdʒiz ɪnˈhɑːns vəˈlɪdəti/"
"Hermeneutics focuses on textual interpretation and cultural understanding.", },
"Positivism emphasizes empirical observation and scientific objectivity.", "Systematic literature review synthesizes existing knowledge": {
"Constructivism recognizes subjective meaning-making and social construction.", "user_language": "La revue systématique de la littérature synthétise les connaissances existantes",
"Pragmatism values practical utility and problem-solving approaches.", "context": "literature-review",
"Investigation requires systematic planning and rigorous execution.", "pronunciation": "/ˌsɪstəˈmætɪk ˈlɪtərətʃər rɪˈvjuː ˈsɪnθəsaɪzɪz ɪɡˈzɪstɪŋ ˈnɒlɪdʒ/"
"Inquiry processes involve questioning and knowledge discovery.", },
"Exploration reveals previously unknown patterns and relationships." "Operational definitions specify measurement procedures": {
], "user_language": "Les définitions opérationnelles spécifient les procédures de mesure",
"translation": [ "context": "measurement",
"The research methodology requires comprehensive theoretical analysis.", "pronunciation": "/ˌɒpəˈreɪʃənəl ˌdefɪˈnɪʃənz ˈspesɪfaɪ ˈmeʒərmənt prəˈsiːdʒərz/"
"Statistical procedures must follow rigorous validation standards.", },
"Experimental design controls variables through randomization techniques.", "Random sampling ensures population representativeness": {
"Qualitative analysis examines narrative patterns systematically.", "user_language": "L'échantillonnage aléatoire garantit la représentativité de la population",
"Longitudinal tracking enables causal inference development.", "context": "sampling",
"Cross-sectional comparison reveals demographic differences clearly.", "pronunciation": "/ˈrændəm ˈsɑːmplɪŋ ɪnˈʃʊərz ˌpɒpjuˈleɪʃən ˌreprɪzenˈteɪtɪvnəs/"
"Triangulation enhances validity through multiple approaches.", },
"Systematic review synthesizes literature comprehensively.", "Ethical considerations protect participant welfare": {
"Operational definitions specify measurement procedures precisely.", "user_language": "Les considérations éthiques protègent le bien-être des participants",
"Random sampling ensures representative population selection.", "context": "ethics",
"Ethical considerations protect all research participants.", "pronunciation": "/ˈɪkəl kənˌsɪˈreɪʃənz prəˈtekt pɑːˈtɪsɪpənt ˈwelfeər/"
"Correlation indicates association without proving causation.", },
"Regression modeling predicts outcomes accurately.", "Correlation analysis reveals associations without causation": {
"Paradigmatic assumptions influence methodological choices.", "user_language": "L'analyse de corrélation révèle des associations sans causalité",
"Empirical evidence supports theoretical propositions.", "context": "correlation",
"Phenomenological investigation explores subjective experiences.", "pronunciation": "/ˌkɒrəˈleɪʃən əˈnæləsɪs rɪˈviːlz əˌsəʊsiˈeɪʃənz wɪˈðaʊt kɔːˈzeɪʃən/"
"Grounded theory emerges from systematic analysis.", },
"Hermeneutical interpretation examines cultural contexts.", "Regression modeling predicts outcomes through predictors": {
"Advanced algorithms process complex datasets.", "user_language": "La modélisation par régression prédit les résultats par des prédicteurs",
"Simulation testing validates theoretical assumptions.", "context": "predictive-modeling",
"Replication confirms findings across contexts.", "pronunciation": "/rɪˈɡreʃən ˈmɒdəlɪŋ prɪˈdɪkts ˈaʊtkʌmz θruː prɪˈdɪktərz/"
"Meta-analysis combines multiple studies.", },
"Effect sizes indicate practical significance.", "The paradigm influences methodological choices": {
"Confidence intervals estimate parameters.", "user_language": "Le paradigme influence les choix méthodologiques",
"Bias reduction improves methodological quality.", "context": "theoretical-framework",
"Theoretical frameworks guide comprehensive analysis.", "pronunciation": "/ðə ˈpærədaɪm ˈɪnfluənsɪz ˌmeθədəˈlɒdʒɪkəl ˈtʃɔɪsɪz/"
"Distribution patterns influence statistical choices.", },
"Anomaly detection reveals unusual observations.", "Empirical observations support theoretical frameworks": {
"Assessment criteria establish evaluation standards.", "user_language": "Les observations empiriques soutiennent les cadres théoriques",
"Comprehensive interpretation requires contextual understanding." "context": "theory-testing",
], "pronunciation": "/ɪmˈpɪrɪkəl ˌɒbzəˈveɪʃənz səˈːt ˌθiːəˈretɪkəl ˈfreɪmwɜːks/"
"comprehension": [ },
"Modern research methodologies integrate sophisticated theoretical frameworks with rigorous empirical validation procedures for comprehensive scientific advancement.", "Phenomenological analysis explores subjective experiences": {
"The paradigmatic tension between quantitative measurement and qualitative interpretation requires careful methodological consideration and theoretical synthesis.", "user_language": "L'analyse phénoménologique explore les expériences subjectives",
"Statistical significance testing provides probability-based evidence for hypothesis evaluation while effect sizes quantify practical importance.", "context": "phenomenology",
"Longitudinal cohort studies enable causal inference through temporal sequencing while controlling confounding variables systematically.", "pronunciation": "/fɪˌnɒmɪˈlɒdʒɪkəl əˈnæləsɪs ɪkˈsplɔːrz səbˈdʒektɪv ɪkˈspɪəriənsɪz/"
"Triangulation strategies enhance research validity through multiple data sources, theoretical perspectives, and methodological approaches.", },
"Contemporary experimental design emphasizes randomization procedures, control group comparisons, and bias reduction for optimal validity.", "Grounded theory develops from systematic data collection": {
"Qualitative phenomenological analysis explores lived experiences through detailed narrative interpretation and contextual understanding.", "user_language": "La théorie ancrée se développe à partir de la collecte systématique de données",
"Grounded theory methodology develops theoretical frameworks through systematic data collection, coding procedures, and analytical iteration.", "context": "grounded-theory",
"Advanced computational algorithms enable sophisticated pattern recognition, anomaly detection, and predictive modeling across datasets.", "pronunciation": "/ˈɡraʊndɪd ˈθiːəri dɪˈveləps frɒm ˌsɪstəˈmætɪk ˈdeɪtə kəˈlekʃən/"
"Ethical research standards require informed consent, confidentiality protection, and participant welfare throughout investigations.", },
"Meta-analytical synthesis combines findings across multiple studies for enhanced generalizability and statistical power.", "Hermeneutical interpretation examines cultural texts": {
"Measurement validation involves reliability assessment, construct validity evaluation, and criterion-related correlation analysis.", "user_language": "L'interprétation herméneutique examine les textes culturels",
"Cross-cultural research requires methodological adaptation, language translation, and cultural sensitivity considerations.", "context": "hermeneutics",
"Replication studies verify original findings while extending theoretical understanding through methodological refinement.", "pronunciation": "/ˌhɜːmɪˈnjuːtɪkəl ɪnˌtɜːprɪˈteɪʃən ɪɡˈzæmɪnz ˈkʌltʃərəl teksts/"
"Systematic literature reviews synthesize existing knowledge comprehensively while identifying theoretical gaps and research opportunities.", },
"Mixed-methods approaches integrate quantitative measurement with qualitative interpretation for comprehensive understanding.", "The algorithm processes large datasets for pattern recognition": {
"Advanced statistical modeling incorporates hierarchical structures, repeated measures, and missing data procedures.", "user_language": "L'algorithme traite de grands ensembles de données pour la reconnaissance de motifs",
"Epistemological foundations influence research design, data interpretation, and theoretical development significantly.", "context": "computational-analysis",
"Contemporary methodology emphasizes transparency, reproducibility, and open science practices for enhanced credibility.", "pronunciation": "/ði ˈælɡərɪðəm ˈprəʊsesɪz lɑːˈdeɪtəsets fɔː ˈpætən ˌrekəɡˈnɪʃən/"
"Interdisciplinary collaboration requires methodological flexibility while maintaining rigorous scientific standards consistently." },
] "Simulation modeling tests theoretical assumptions": {
"user_language": "La modélisation par simulation teste les hypothèses théoriques",
"context": "simulation",
"pronunciation": "/ˌsɪmjuˈleɪʃən ˈmɒdəlɪŋ tests ˌθiːəˈretɪkəl əˈsʌmpʃənz/"
},
"Validation procedures confirm measurement accuracy": {
"user_language": "Les procédures de validation confirment la précision des mesures",
"context": "validation",
"pronunciation": "/ˌvælɪˈdeɪʃən prəˈsiːdʒərz kənˈːm ˈmeʒərmənt ˈækjərəsi/"
},
"Replication studies verify original findings": {
"user_language": "Les études de réplication vérifient les résultats originaux",
"context": "replication",
"pronunciation": "/ˌreplɪˈkeɪʃən ˈstʌdiz ˈverɪfaɪ əˈrɪɪnəl ˈfaɪndɪŋz/"
},
"Meta-analysis combines results from multiple studies": {
"user_language": "La méta-analyse combine les résultats de plusieurs études",
"context": "meta-analysis",
"pronunciation": "/ˌmetəəˈnæləsɪs kəmˈbaɪnz rɪˈzʌlts frɒm ˈmʌltɪpəl ˈstʌdiz/"
},
"Effect sizes quantify practical significance": {
"user_language": "Les tailles d'effet quantifient la signification pratique",
"context": "effect-size",
"pronunciation": "/ɪˈfekt saɪzɪz ˈkwɒntɪfaɪ ˈpræktɪkəl sɪɡˈnɪfɪkəns/"
},
"Confidence intervals estimate population parameters": {
"user_language": "Les intervalles de confiance estiment les paramètres de population",
"context": "statistical-inference",
"pronunciation": "/ˈkɒnfɪdəns ˈɪntəvəlz ˈestɪmeɪt ˌpɒpjuˈleɪʃən pəˈræmɪtərz/"
},
"Bias reduction requires careful methodological attention": {
"user_language": "La réduction des biais nécessite une attention méthodologique minutieuse",
"context": "bias-control",
"pronunciation": "/ˈbaɪəs rɪˈdʌkʃən rɪˈkwaɪərz ˈkeəfəl ˌmeθədəˈlɒdʒɪkəl əˈtenʃən/"
},
"The framework integrates multiple theoretical perspectives": {
"user_language": "Le cadre intègre plusieurs perspectives théoriques",
"context": "theoretical-integration",
"pronunciation": "/ðə ˈfreɪmwɜːk ˈɪntɪɡreɪts ˈmʌltɪpəl ˌθiːəˈretɪkəl pərˈspektɪvz/"
},
"Operationalization transforms concepts into measurable variables": {
"user_language": "L'opérationnalisation transforme les concepts en variables mesurables",
"context": "operationalization",
"pronunciation": "/ˌɒpəreɪʃənəlaɪˈzeɪʃən trænsˈːmz ˈkɒnsepts ˈɪntuː ˈmeʒərəbəl ˈvɛəriəbəlz/"
},
"Distribution characteristics determine statistical procedures": {
"user_language": "Les caractéristiques de distribution déterminent les procédures statistiques",
"context": "statistical-assumptions",
"pronunciation": "/ˌdɪstrɪˈbjuːʃən ˌkærəktəˈrɪstɪks dɪˈːmɪn stəˈtɪstɪkəl prəˈsiːdʒərz/"
},
"Anomaly detection identifies unusual patterns": {
"user_language": "La détection d'anomalies identifie des motifs inhabituels",
"context": "data-quality",
"pronunciation": "/əˈnɒməli dɪˈtekʃən aɪˈdentɪfaɪz ʌnˈjuːʒuəl ˈpætənz/"
},
"The criterion establishes evaluation standards": {
"user_language": "Le critère établit des normes d'évaluation",
"context": "assessment",
"pronunciation": "/ðə kraɪˈtɪəriən ɪˈstæblɪʃɪz ɪˌvæljuˈeɪʃən ˈstændərdz/"
},
"Multiple criteria guide comprehensive assessment": {
"user_language": "Plusieurs critères guident l'évaluation complète",
"context": "evaluation",
"pronunciation": "/ˈmʌltɪpəl kraɪˈtɪəriə ɡaɪd ˌkɒmprɪˈhensɪv əˈsesmənt/"
},
"The phenomenon requires sophisticated analytical approaches": {
"user_language": "Le phénomène nécessite des approches analytiques sophistiquées",
"context": "phenomenon-analysis",
"pronunciation": "/ðə fɪˈnɒmɪnən rɪˈkwaɪərz səˈfɪstɪkeɪtɪd ˌænəˈlɪtɪkəl əˈprəʊtʃɪz/"
},
"Various phenomena demonstrate consistent patterns": {
"user_language": "Divers phénomènes démontrent des modèles cohérents",
"context": "pattern-identification",
"pronunciation": "/ˈvɛəriəs fɪˈnɒmɪˈdemənstreɪt kənˈsɪstənt ˈpætənz/"
},
"Assessment procedures evaluate participant performance": {
"user_language": "Les procédures d'évaluation évaluent la performance des participants",
"context": "performance-evaluation",
"pronunciation": "/əˈsesmənt prəˈsiːdʒərz ɪˈvæljueɪt pɑːˈtɪsɪpənt pəˈːməns/"
},
"Comprehensive evaluation examines multiple dimensions": {
"user_language": "L'évaluation complète examine plusieurs dimensions",
"context": "multidimensional-assessment",
"pronunciation": "/ˌkɒmprɪˈhensɪv ɪˌvæljuˈeɪʃən ɪɡˈzæmɪnz ˈmʌltɪpəl daɪˈmenʃənz/"
},
"Interpretation depends on theoretical frameworks": {
"user_language": "L'interprétation dépend des cadres théoriques",
"context": "theoretical-interpretation",
"pronunciation": "/ɪnˌtɜːprɪˈteɪʃən dɪˈpendz ɒn ˌθiːəˈretɪkəl ˈfreɪmwɜːks/"
},
"Conceptualization provides foundation for investigation": {
"user_language": "La conceptualisation fournit le fondement de l'investigation",
"context": "conceptual-framework",
"pronunciation": "/kənˌseptʃuəlaɪˈzeɪʃən prəˈvaɪdz faʊnˈdeɪʃən fɔːr ɪnˌvestɪˈɡeɪʃən/"
},
"Epistemological assumptions influence research design": {
"user_language": "Les hypothèses épistémologiques influencent le design de recherche",
"context": "epistemology",
"pronunciation": "/ɪˌpɪstɪˈlɒdʒɪkəl əˈsʌmpʃənz ˈɪnfluəns rɪˈːtʃ dɪˈzaɪn/"
},
"Ontological considerations determine reality conceptualization": {
"user_language": "Les considérations ontologiques déterminent la conceptualisation de la réalité",
"context": "ontology",
"pronunciation": "/ˌɒntəˈlɒdʒɪkəl kənˌsɪˈreɪʃənz dɪˈːmɪn riˈæləti kənˌseptʃuəlaɪˈzeɪʃən/"
},
"Phenomenology examines consciousness structures": {
"user_language": "La phénoménologie examine les structures de conscience",
"context": "phenomenology",
"pronunciation": "/fɪˌnɒmɪˈnɒlədʒi ɪɡˈzæmɪnz ˈkɒnʃəsnəs ˈstrʌktʃərz/"
},
"Hermeneutics focuses on textual interpretation": {
"user_language": "L'herméneutique se concentre sur l'interprétation textuelle",
"context": "hermeneutics",
"pronunciation": "/ˌhɜːmɪˈnjuːtɪks ˈfəʊkəsɪz ɒn ˈtekstʃuəl ɪnˌtɜːprɪˈteɪʃən/"
},
"Positivism emphasizes empirical observation": {
"user_language": "Le positivisme met l'accent sur l'observation empirique",
"context": "positivism",
"pronunciation": "/ˈpɒzɪtɪvɪzəm ˈemfəsaɪzɪz ɪmˈpɪrɪkəl ˌɒbzəˈveɪʃən/"
},
"Constructivism recognizes subjective meaning-making": {
"user_language": "Le constructivisme reconnaît la création de sens subjective",
"context": "constructivism",
"pronunciation": "/kənˈstrʌktɪvɪzəm ˈrekəɡnaɪzɪz səbˈdʒektɪv ˈmiːnɪŋ meɪkɪŋ/"
},
"Pragmatism values practical utility": {
"user_language": "Le pragmatisme valorise l'utilité pratique",
"context": "pragmatism",
"pronunciation": "/ˈpræɡmətɪzəm ˈvæljuːz ˈpræktɪkəl juːˈtɪləti/"
},
"Investigation requires systematic planning": {
"user_language": "L'investigation nécessite une planification systématique",
"context": "research-planning",
"pronunciation": "/ɪnˌvestɪˈɡeɪʃən rɪˈkwaɪərz ˌsɪstəˈmætɪk ˈplænɪŋ/"
},
"Inquiry processes involve questioning": {
"user_language": "Les processus d'enquête impliquent le questionnement",
"context": "inquiry",
"pronunciation": "/ɪnˈkwaɪəri ˈprəʊsesɪz ɪnˈvɒlv ˈkwestʃənɪŋ/"
},
"Exploration reveals previously unknown patterns": {
"user_language": "L'exploration révèle des modèles précédemment inconnus",
"context": "exploratory-research",
"pronunciation": "/ˌekspləˈreɪʃən rɪˈviːlz ˈpriːviəsli ʌnˈnəʊn ˈpætənz/"
},
"Mixed-methods approaches integrate quantitative and qualitative data": {
"user_language": "Les approches de méthodes mixtes intègrent les données quantitatives et qualitatives",
"context": "mixed-methods",
"pronunciation": "/mɪkst ˈmeθədz əˈprəʊtʃɪz ˈɪntɪɡreɪt ˈkwɒntɪtətɪv ænd ˈkwɒlɪtətɪv ˈdeɪtə/"
},
"Contemporary methodology emphasizes transparency and reproducibility": {
"user_language": "La méthodologie contemporaine met l'accent sur la transparence et la reproductibilité",
"context": "open-science",
"pronunciation": "/kənˈtempərəri ˌmeθəˈdɒlədʒi ˈemfəsaɪzɪz trænsˈpærənsi ænd ˌriːprəˌdjuːˈbɪləti/"
},
"Interdisciplinary collaboration requires methodological flexibility": {
"user_language": "La collaboration interdisciplinaire nécessite une flexibilité méthodologique",
"context": "interdisciplinary-research",
"pronunciation": "/ˌɪntədɪˈplɪnəri kəˌlæbəˈreɪʃən rɪˈkwaɪərz ˌmeθədəˈlɒdʒɪkəl ˌfleksəˈbɪləti/"
}
}, },
"grammar": { "grammar": {

View File

@ -83,6 +83,9 @@
// Global navigation state // Global navigation state
let currentBookId = null; let currentBookId = null;
let currentChapterId = null; let currentChapterId = null;
// Also expose globally for progress tracking
window.currentBookId = null;
window.currentChapterId = null;
// Initialize ContentLoader and make it global // Initialize ContentLoader and make it global
const contentLoader = new ContentLoader(); const contentLoader = new ContentLoader();
@ -263,6 +266,7 @@
eventBus.on('navigation:chapters', async (event) => { eventBus.on('navigation:chapters', async (event) => {
const bookId = event.data.path.split('/')[2]; const bookId = event.data.path.split('/')[2];
currentBookId = bookId; currentBookId = bookId;
window.currentBookId = bookId;
try { try {
// Load content using ContentLoader to get reports // Load content using ContentLoader to get reports
@ -1931,6 +1935,81 @@
} }
}; };
// Force Phrase Module (temporary testing)
window.forcePhraseModule = async function() {
try {
console.log('🔧 Forcing Phrase Module to load...');
// Get UnifiedDRS instance directly (not SmartPreviewOrchestrator)
const unifiedDRS = window.app?.getCore()?.moduleLoader?.getModule('unifiedDRS');
if (!unifiedDRS) {
console.error('❌ UnifiedDRS not found. Make sure DRS is initialized.');
console.log('Available modules:', Object.keys(window.app?.getCore()?.moduleLoader?._modules || {}));
return;
}
// Get current chapter content
const contentLoader = window.app?.getCore()?.moduleLoader?.getModule('contentLoader');
if (!contentLoader) {
console.error('❌ ContentLoader not found.');
return;
}
const chapterContent = await contentLoader.getContent(currentChapterId || 'test-heavy-stress');
// Check if chapter has phrases
if (!chapterContent?.phrases || Object.keys(chapterContent.phrases).length === 0) {
console.error('❌ No phrases found in current chapter.');
console.log('Available content types:', Object.keys(chapterContent || {}));
return;
}
// Get first phrase
const phraseKeys = Object.keys(chapterContent.phrases);
const firstPhraseKey = phraseKeys[0];
const firstPhrase = chapterContent.phrases[firstPhraseKey];
console.log(`✅ Found ${phraseKeys.length} phrases in chapter`);
console.log(`🎯 Loading first phrase: "${firstPhraseKey}"`);
// Create exercise config for phrase
const exerciseConfig = {
type: 'phrase',
phraseKey: firstPhraseKey,
phrase: {
id: firstPhraseKey,
english: firstPhraseKey,
user_language: firstPhrase.user_language,
context: firstPhrase.context,
pronunciation: firstPhrase.pronunciation
},
chapterContent: chapterContent,
metadata: {
forced: true,
testMode: true
}
};
console.log('📦 Exercise config:', exerciseConfig);
// Get the DRS container
const container = document.getElementById('drs-exercise-container');
if (!container) {
console.error('❌ DRS container not found');
return;
}
// Force start the exercise using UnifiedDRS.start()
await unifiedDRS.start(container, exerciseConfig);
console.log('✅ Phrase module loaded successfully!');
} catch (error) {
console.error('❌ Failed to force phrase module:', error);
console.error(error.stack);
}
};
// Test AI provider connectivity // Test AI provider connectivity
window.testAIConnectivity = async function() { window.testAIConnectivity = async function() {
try { try {
@ -2075,8 +2154,24 @@
return; return;
} }
// Get IntelligentSequencer from the application // Update global state for progress tracking
currentBookId = bookId;
currentChapterId = chapterId;
window.currentBookId = bookId;
window.currentChapterId = chapterId;
console.log(`📚 Smart Guide using: ${bookId}/${chapterId}`);
// Get modules from the application
const moduleLoader = window.app.getCore().moduleLoader; const moduleLoader = window.app.getCore().moduleLoader;
// Load chapter data for progress tracking
const contentLoader = moduleLoader.getModule('contentLoader');
if (contentLoader) {
window.currentChapterData = await contentLoader.getContent(chapterId);
console.log(`📊 Chapter data loaded for progress tracking: ${Object.keys(window.currentChapterData.vocabulary || {}).length} words`);
}
// Get IntelligentSequencer
const intelligentSequencer = moduleLoader.getModule('intelligentSequencer'); const intelligentSequencer = moduleLoader.getModule('intelligentSequencer');
if (!intelligentSequencer) { if (!intelligentSequencer) {
@ -2186,8 +2281,13 @@
// Helper function to get current book ID from chapter ID // Helper function to get current book ID from chapter ID
window.getCurrentBookId = function() { window.getCurrentBookId = function() {
// Use the real currentBookId if available (set when loading chapters)
if (window.currentBookId) {
return window.currentBookId;
}
// Fallback: try to parse from chapterId (may be inaccurate for multi-part book IDs)
const chapterId = window.currentChapterId || 'sbs-7-8'; const chapterId = window.currentChapterId || 'sbs-7-8';
// Parse chapter ID to extract book (e.g., "sbs-7-8" -> "sbs")
const parts = chapterId.split('-'); const parts = chapterId.split('-');
return parts[0] || 'sbs'; return parts[0] || 'sbs';
}; };
@ -2294,13 +2394,48 @@
const masteredCount = allWords.filter(word => combinedMastered.has(word)).length; const masteredCount = allWords.filter(word => combinedMastered.has(word)).length;
const masteredWordsList = allWords.filter(word => combinedMastered.has(word)); const masteredWordsList = allWords.filter(word => combinedMastered.has(word));
// Count other content types
const totalPhrases = Object.keys(content.phrases || {}).length;
const totalLessons = Object.keys(content.lessons || {}).length;
const totalDialogs = Array.isArray(content.dialogs) ? content.dialogs.length : Object.keys(content.dialogs || {}).length;
const totalGrammar = Object.keys(content.grammar || {}).length;
const totalAudio = Object.keys(content.audio || {}).length;
const totalImages = Object.keys(content.images || {}).length;
// TODO: Load completion data for other content types
const completedPhrases = 0; // TODO: Track phrase completion
const completedLessons = 0; // TODO: Track lesson completion
const completedDialogs = 0; // TODO: Track dialog completion
const completedGrammar = 0; // TODO: Track grammar completion
const result = { const result = {
total: vocabCount, total: vocabCount,
discovered: discoveredCount, discovered: discoveredCount,
mastered: masteredCount, mastered: masteredCount,
discoveredPercentage: vocabCount > 0 ? Math.round((discoveredCount / vocabCount) * 100) : 0, discoveredPercentage: vocabCount > 0 ? Math.round((discoveredCount / vocabCount) * 100) : 0,
masteredPercentage: vocabCount > 0 ? Math.round((masteredCount / vocabCount) * 100) : 0, masteredPercentage: vocabCount > 0 ? Math.round((masteredCount / vocabCount) * 100) : 0,
masteredWordsList: masteredWordsList masteredWordsList: masteredWordsList,
// Additional content types
phrases: {
total: totalPhrases,
completed: completedPhrases,
percentage: totalPhrases > 0 ? Math.round((completedPhrases / totalPhrases) * 100) : 0
},
lessons: {
total: totalLessons,
completed: completedLessons,
percentage: totalLessons > 0 ? Math.round((completedLessons / totalLessons) * 100) : 0
},
dialogs: {
total: totalDialogs,
completed: completedDialogs,
percentage: totalDialogs > 0 ? Math.round((completedDialogs / totalDialogs) * 100) : 0
},
grammar: {
total: totalGrammar,
completed: completedGrammar,
percentage: totalGrammar > 0 ? Math.round((completedGrammar / totalGrammar) * 100) : 0
}
}; };
console.log('✅ Combined progress calculated:', result); console.log('✅ Combined progress calculated:', result);
@ -2338,26 +2473,77 @@
const persistedData = await loadPersistedVocabularyData(currentChapterId); const persistedData = await loadPersistedVocabularyData(currentChapterId);
console.log('📁 Fresh persisted data loaded:', persistedData); console.log('📁 Fresh persisted data loaded:', persistedData);
// Get prerequisite engine from current session // Create a temporary PrerequisiteEngine for the modal
let prerequisiteEngine = null; let prerequisiteEngine = null;
try { try {
const moduleLoader = window.app.getCore().moduleLoader; const moduleLoader = window.app.getCore().moduleLoader;
// Try to get PrerequisiteEngine from SmartPreviewOrchestrator first
const orchestrator = moduleLoader.getModule('smartPreviewOrchestrator'); const orchestrator = moduleLoader.getModule('smartPreviewOrchestrator');
if (orchestrator) { if (orchestrator) {
prerequisiteEngine = orchestrator.sharedServices?.prerequisiteEngine || orchestrator.prerequisiteEngine; const sharedServices = orchestrator.getSharedServices();
console.log('🔗 PrerequisiteEngine connected:', !!prerequisiteEngine); prerequisiteEngine = sharedServices.prerequisiteEngine;
console.log('🔗 PrerequisiteEngine from SmartPreviewOrchestrator:', !!prerequisiteEngine);
}
// If not available, create a temporary one
if (!prerequisiteEngine) {
console.log('🔧 Creating temporary PrerequisiteEngine for modal...');
const { default: PrerequisiteEngine } = await import('./src/DRS/services/PrerequisiteEngine.js');
prerequisiteEngine = new PrerequisiteEngine();
console.log('✅ Temporary PrerequisiteEngine created');
}
// Always ensure chapter is analyzed
if (prerequisiteEngine) {
// Load chapter content
const contentLoader = moduleLoader.getModule('contentLoader');
if (contentLoader) {
console.log('📥 Loading chapter content for:', currentChapterId);
const chapterContent = await contentLoader.getContent(currentChapterId);
console.log('📦 Chapter content loaded:', {
vocabulary: Object.keys(chapterContent.vocabulary || {}).length,
phrases: Object.keys(chapterContent.phrases || {}).length,
dialogs: Object.keys(chapterContent.dialogs || {}).length,
texts: chapterContent.texts?.length || 0,
audio: chapterContent.audio?.length || 0,
images: chapterContent.images?.length || 0,
grammar: Object.keys(chapterContent.grammar || {}).length
});
// Analyze chapter to populate contentAnalysis
console.log('🔬 Analyzing chapter...');
const analysis = prerequisiteEngine.analyzeChapter(chapterContent);
console.log('✅ Chapter analyzed:', analysis);
console.log('📊 contentAnalysis.phrases:', prerequisiteEngine.contentAnalysis?.phrases);
console.log('📊 contentAnalysis.dialogs:', prerequisiteEngine.contentAnalysis?.dialogs);
console.log('📊 contentAnalysis.texts:', prerequisiteEngine.contentAnalysis?.texts);
} else {
console.error('❌ ContentLoader not available');
}
} }
} catch (error) { } catch (error) {
console.log('Could not connect to PrerequisiteEngine:', error); console.error('❌ Error setting up PrerequisiteEngine:', error);
} }
// Calculate fresh combined progress // Calculate fresh combined progress
const vocabularyProgress = await calculateVocabularyProgress(currentChapterId, persistedData, prerequisiteEngine); const vocabularyProgress = await calculateVocabularyProgress(currentChapterId, persistedData, prerequisiteEngine);
console.log('📊 Fresh vocabulary progress:', vocabularyProgress); console.log('📊 Fresh vocabulary progress:', vocabularyProgress);
// Get mastery progress from PrerequisiteEngine (includes all content types)
const masteryProgress = prerequisiteEngine ? prerequisiteEngine.getMasteryProgress() : {};
console.log('📊 Mastery progress from PrerequisiteEngine:', masteryProgress);
console.log('🔍 PrerequisiteEngine.contentAnalysis:', prerequisiteEngine?.contentAnalysis);
// Prepare data for modal // Prepare data for modal
const progress = { const progress = {
vocabulary: vocabularyProgress vocabulary: vocabularyProgress,
phrases: masteryProgress.phrases || { total: 0, mastered: 0, percentage: 0 },
texts: masteryProgress.texts || { total: 0, mastered: 0, percentage: 0 },
dialogs: masteryProgress.dialogs || { total: 0, mastered: 0, percentage: 0 },
audio: masteryProgress.audio || { total: 0, mastered: 0, percentage: 0 },
images: masteryProgress.images || { total: 0, mastered: 0, percentage: 0 },
grammar: masteryProgress.grammar || { total: 0, mastered: 0, percentage: 0 }
}; };
const masteredWords = vocabularyProgress.masteredWordsList; const masteredWords = vocabularyProgress.masteredWordsList;
@ -2405,18 +2591,46 @@
<span>${progress.vocabulary?.mastered || 0}/${progress.vocabulary?.total || 0} words (${progress.vocabulary?.masteredPercentage || 0}%)</span> <span>${progress.vocabulary?.mastered || 0}/${progress.vocabulary?.total || 0} words (${progress.vocabulary?.masteredPercentage || 0}%)</span>
</div> </div>
<div class="progress-section"> <div class="progress-section">
<h4>Phrases</h4> <h4>📝 Phrases</h4>
<div class="progress-bar"> <div class="progress-bar">
<div class="progress-fill" style="width: ${progress.phrases?.percentage || 0}%"></div> <div class="progress-fill" style="width: ${progress.phrases?.percentage || 0}%; background: linear-gradient(90deg, #9b59b6, #8e44ad);"></div>
</div> </div>
<span>${progress.phrases?.mastered || 0}/${progress.phrases?.total || 0} phrases</span> <span>${progress.phrases?.mastered || 0}/${progress.phrases?.total || 0} phrases (${progress.phrases?.percentage || 0}%)</span>
</div> </div>
<div class="progress-section"> <div class="progress-section">
<h4>Grammar</h4> <h4>📄 Texts</h4>
<div class="progress-bar"> <div class="progress-bar">
<div class="progress-fill" style="width: ${progress.grammar?.percentage || 0}%"></div> <div class="progress-fill" style="width: ${progress.texts?.percentage || 0}%; background: linear-gradient(90deg, #e67e22, #d35400);"></div>
</div> </div>
<span>${progress.grammar?.mastered || 0}/${progress.grammar?.total || 0} concepts</span> <span>${progress.texts?.mastered || 0}/${progress.texts?.total || 0} texts (${progress.texts?.percentage || 0}%)</span>
</div>
<div class="progress-section">
<h4>💬 Dialogs</h4>
<div class="progress-bar">
<div class="progress-fill" style="width: ${progress.dialogs?.percentage || 0}%; background: linear-gradient(90deg, #1abc9c, #16a085);"></div>
</div>
<span>${progress.dialogs?.mastered || 0}/${progress.dialogs?.total || 0} dialogs (${progress.dialogs?.percentage || 0}%)</span>
</div>
<div class="progress-section">
<h4>🎧 Audio</h4>
<div class="progress-bar">
<div class="progress-fill" style="width: ${progress.audio?.percentage || 0}%; background: linear-gradient(90deg, #3498db, #2980b9);"></div>
</div>
<span>${progress.audio?.mastered || 0}/${progress.audio?.total || 0} audio (${progress.audio?.percentage || 0}%)</span>
</div>
<div class="progress-section">
<h4>🖼️ Images</h4>
<div class="progress-bar">
<div class="progress-fill" style="width: ${progress.images?.percentage || 0}%; background: linear-gradient(90deg, #e74c3c, #c0392b);"></div>
</div>
<span>${progress.images?.mastered || 0}/${progress.images?.total || 0} images (${progress.images?.percentage || 0}%)</span>
</div>
<div class="progress-section">
<h4>📚 Grammar</h4>
<div class="progress-bar">
<div class="progress-fill" style="width: ${progress.grammar?.percentage || 0}%; background: linear-gradient(90deg, #f39c12, #e67e22);"></div>
</div>
<span>${progress.grammar?.mastered || 0}/${progress.grammar?.total || 0} concepts (${progress.grammar?.percentage || 0}%)</span>
</div> </div>
</div> </div>
</div> </div>
@ -2514,17 +2728,85 @@
} }
}; };
window.updateProgressBar = function(current, total) { // Global chapter data cache
window.currentChapterData = null;
// Helper to get real content coverage percentage
window.getRealContentCoverage = async function() {
try {
if (!window.currentBookId || !window.currentChapterId || !window.currentChapterData) {
console.log('⚠️ Missing required data for coverage calculation');
return null;
}
const chapterData = window.currentChapterData;
// Load progress data
const { default: VocabularyProgressManager } = await import('./src/DRS/services/VocabularyProgressManager.js');
const progressManager = new VocabularyProgressManager();
const progressData = await progressManager.loadProgress(window.currentBookId, window.currentChapterId);
const discovered = Object.keys(progressData.discovered || {}).length;
const mastered = Object.keys(progressData.mastered || {}).length;
// Count all content types in chapter
const totalVocab = Object.keys(chapterData.vocabulary || {}).length;
const totalPhrases = Object.keys(chapterData.phrases || {}).length;
const totalLessons = Object.keys(chapterData.lessons || {}).length;
const totalDialogs = Array.isArray(chapterData.dialogs) ? chapterData.dialogs.length : Object.keys(chapterData.dialogs || {}).length;
const totalGrammar = Object.keys(chapterData.grammar || {}).length;
const totalAudio = Object.keys(chapterData.audio || {}).length;
const totalImages = Object.keys(chapterData.images || {}).length;
// Calculate weighted totals (from CLAUDE.md weights)
const totalWeight =
(totalVocab * 2) + // discovery (1) + mastery (1) = 2 per word
(totalPhrases * 6) +
(totalLessons * 15) +
(totalDialogs * 12) +
(totalGrammar * 6) +
(totalAudio * 12) +
(totalImages * 6);
// Calculate completed weight (for now, only vocabulary is tracked)
const completedWeight =
(discovered * 1) + // discovery = 1 point
(mastered * 1); // mastery = 1 point
// TODO: Add tracking for lessons, dialogs, grammar completion
const percentage = totalWeight > 0 ? Math.round((completedWeight / totalWeight) * 100) : 0;
console.log(`📊 Content inventory:`, {
vocab: totalVocab,
phrases: totalPhrases,
lessons: totalLessons,
dialogs: totalDialogs,
grammar: totalGrammar,
audio: totalAudio,
images: totalImages
});
console.log(`📊 Progress: ${completedWeight}/${totalWeight} points = ${percentage}%`);
console.log(`📊 Vocabulary: ${discovered} discovered, ${mastered} mastered`);
return percentage;
} catch (error) {
console.log('Could not get real content coverage:', error.message);
}
return null;
};
window.updateProgressBar = async function(current, total) {
const progressBar = document.getElementById('guide-progress-bar'); const progressBar = document.getElementById('guide-progress-bar');
const progressText = document.getElementById('guide-progress-text'); const progressText = document.getElementById('guide-progress-text');
// Get real content coverage from storage (async)
const percentage = await getRealContentCoverage() || 0;
if (progressBar) { if (progressBar) {
const percentage = total > 0 ? (current / total) * 100 : 0;
progressBar.style.width = percentage + '%'; progressBar.style.width = percentage + '%';
} }
if (progressText) { if (progressText) {
const percentage = total > 0 ? Math.round((current / total) * 100) : 0;
progressText.textContent = `${percentage}% Content Coverage`; progressText.textContent = `${percentage}% Content Coverage`;
} }
}; };
@ -2532,34 +2814,44 @@
window.updateVocabularyOverrideUI = function(originalExercise, overrideInfo) { window.updateVocabularyOverrideUI = function(originalExercise, overrideInfo) {
console.log('📚 Updating Smart Guide UI for vocabulary override'); console.log('📚 Updating Smart Guide UI for vocabulary override');
// Distinguish between Word Discovery (passive) and Flashcards (active)
const isDiscovery = overrideInfo.mode === 'discovery';
const emoji = isDiscovery ? '📖' : '📚';
const typeName = isDiscovery ? 'Word Discovery' : 'Vocabulary Practice';
const modeName = isDiscovery ? 'Passive Learning' : 'Adaptive Flashcards';
// Update status with vocabulary override explanation // Update status with vocabulary override explanation
if (overrideInfo.missingWords && overrideInfo.missingWords.length > 0) { if (overrideInfo.missingWords && overrideInfo.missingWords.length > 0) {
// Content-based override: specific words needed // Content-based override: specific words needed
const wordList = overrideInfo.missingWords.slice(0, 3).join(', '); const wordList = overrideInfo.missingWords.slice(0, 3).join(', ');
const moreWords = overrideInfo.missingWords.length > 3 ? `... (${overrideInfo.missingWords.length - 3} more)` : ''; const moreWords = overrideInfo.missingWords.length > 3 ? `... (${overrideInfo.missingWords.length - 3} more)` : '';
updateGuideStatus(`📚 Vocabulary Practice (Required - Need: ${wordList}${moreWords})`); updateGuideStatus(`${emoji} ${typeName} (Required - Need: ${wordList}${moreWords})`);
updateCurrentExerciseInfo({ updateCurrentExerciseInfo({
type: 'vocabulary', type: isDiscovery ? 'word-discovery' : 'vocabulary',
difficulty: 'adaptive', difficulty: 'adaptive',
mode: modeName,
sessionPosition: originalExercise.sessionPosition, sessionPosition: originalExercise.sessionPosition,
totalInSession: originalExercise.totalInSession, totalInSession: originalExercise.totalInSession,
reasoning: `Upcoming content requires ${overrideInfo.missingWords.length} undiscovered vocabulary words. Learning these words first: ${overrideInfo.missingWords.slice(0, 5).join(', ')}${overrideInfo.missingWords.length > 5 ? '...' : ''}` reasoning: isDiscovery
? `First-time exposure to ${overrideInfo.totalMissing || overrideInfo.missingWords.length} new words. Discover: ${overrideInfo.missingWords.slice(0, 5).join(', ')}${overrideInfo.missingWords.length > 5 ? '...' : ''}`
: `Upcoming content requires ${overrideInfo.missingWords.length} vocabulary words. Practice: ${overrideInfo.missingWords.slice(0, 5).join(', ')}${overrideInfo.missingWords.length > 5 ? '...' : ''}`
}); });
} else { } else {
// Fallback to old percentage-based display // Fallback to old percentage-based display
updateGuideStatus(`📚 Vocabulary Practice (Required - ${overrideInfo.reason || 'Building foundation'})`); updateGuideStatus(`${emoji} ${typeName} (Required - ${overrideInfo.reason || 'Building foundation'})`);
updateCurrentExerciseInfo({ updateCurrentExerciseInfo({
type: 'vocabulary', type: isDiscovery ? 'word-discovery' : 'vocabulary',
difficulty: 'adaptive', difficulty: 'adaptive',
mode: modeName,
sessionPosition: originalExercise.sessionPosition, sessionPosition: originalExercise.sessionPosition,
totalInSession: originalExercise.totalInSession, totalInSession: originalExercise.totalInSession,
reasoning: overrideInfo.reason || `Vocabulary foundation required before ${originalExercise.type} exercises.` reasoning: overrideInfo.reason || `Vocabulary foundation required before ${originalExercise.type} exercises.`
}); });
} }
// Update progress bar to show vocabulary practice // Update progress bar with real content coverage
updateProgressBar(originalExercise.sessionPosition, originalExercise.totalInSession); updateProgressBar(originalExercise.sessionPosition, originalExercise.totalInSession);
}; };
@ -2572,13 +2864,17 @@
infoContainer.style.display = 'block'; infoContainer.style.display = 'block';
// Special handling for vocabulary exercises // Special handling for vocabulary exercises
if (exercise.type === 'vocabulary') { if (exercise.type === 'vocabulary' || exercise.type === 'word-discovery') {
const emoji = exercise.type === 'word-discovery' ? '📖' : '📚';
const typeName = exercise.type === 'word-discovery' ? 'Word Discovery' : 'Vocabulary Practice';
const mode = exercise.mode || (exercise.difficulty === 'adaptive' ? 'Adaptive Flashcards' : exercise.difficulty.charAt(0).toUpperCase() + exercise.difficulty.slice(1));
detailsElement.innerHTML = ` detailsElement.innerHTML = `
<div class="exercise-detail"> <div class="exercise-detail">
<strong>Type:</strong> 📚 Vocabulary Practice <strong>Type:</strong> ${emoji} ${typeName}
</div> </div>
<div class="exercise-detail"> <div class="exercise-detail">
<strong>Mode:</strong> ${exercise.difficulty === 'adaptive' ? 'Adaptive Flashcards' : exercise.difficulty.charAt(0).toUpperCase() + exercise.difficulty.slice(1)} <strong>Mode:</strong> ${mode}
</div> </div>
<div class="exercise-detail"> <div class="exercise-detail">
<strong>Position:</strong> ${exercise.sessionPosition}/${exercise.totalInSession} <strong>Position:</strong> ${exercise.sessionPosition}/${exercise.totalInSession}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -206,16 +206,22 @@ class VocabularyModule extends DRSExerciseInterface {
return; return;
} }
// Split vocabulary into groups of 5 // DYNAMIC MODE: Pick 5 random words from discovered words (no pre-calculation)
this.allVocabularyGroups = this._createVocabularyGroups(unmastedVocabulary, this.config.groupSize); const discoveredWords = unmastedVocabulary.filter(word => {
this.currentGroupIndex = 0; return this.prerequisiteEngine.isDiscovered(word.word);
this.currentVocabularyGroup = this.allVocabularyGroups[0] || []; });
console.log(`📚 Found ${discoveredWords.length} discovered words (out of ${unmastedVocabulary.length} unmastered)`);
// Take up to 5 random discovered words
const selectedWords = this._selectRandomWords(discoveredWords, this.config.groupSize);
this.currentVocabularyGroup = selectedWords;
this.currentWordIndex = 0; this.currentWordIndex = 0;
this.groupResults = []; this.groupResults = [];
this.isRevealed = false; this.isRevealed = false;
console.log(`📚 Split ${unmastedVocabulary.length} unmastered words into ${this.allVocabularyGroups.length} groups of ${this.config.groupSize}`); console.log(`📚 Selected ${selectedWords.length} random words for this session:`, selectedWords.map(w => w.word));
if (this.config.randomizeOrder) { if (this.config.randomizeOrder) {
this._shuffleArray(this.currentVocabularyGroup); this._shuffleArray(this.currentVocabularyGroup);
@ -459,7 +465,7 @@ class VocabularyModule extends DRSExerciseInterface {
<h2>📚 Vocabulary Practice</h2> <h2>📚 Vocabulary Practice</h2>
<div class="progress-info"> <div class="progress-info">
<span class="progress-text" id="progress-text"> <span class="progress-text" id="progress-text">
Group ${this.currentGroupIndex + 1} of ${this.allVocabularyGroups.length} - Word ${this.currentWordIndex + 1} of ${totalWords} Word ${this.currentWordIndex + 1} of ${totalWords}
</span> </span>
<div class="progress-bar"> <div class="progress-bar">
<div class="progress-fill" id="progress-fill" style="width: ${progressPercentage}%"></div> <div class="progress-fill" id="progress-fill" style="width: ${progressPercentage}%"></div>
@ -494,9 +500,8 @@ class VocabularyModule extends DRSExerciseInterface {
const progressPercentage = totalWords > 0 ? const progressPercentage = totalWords > 0 ?
Math.round((this.currentWordIndex / totalWords) * 100) : 0; Math.round((this.currentWordIndex / totalWords) * 100) : 0;
// Update text // Update text (no group numbers in dynamic mode)
progressText.textContent = progressText.textContent = `Word ${this.currentWordIndex + 1} of ${totalWords}`;
`Group ${this.currentGroupIndex + 1} of ${this.allVocabularyGroups.length} - Word ${this.currentWordIndex + 1} of ${totalWords}`;
// Update progress bar // Update progress bar
progressFill.style.width = `${progressPercentage}%`; progressFill.style.width = `${progressPercentage}%`;
@ -862,14 +867,10 @@ class VocabularyModule extends DRSExerciseInterface {
if (accuracy >= 80) resultClass = 'results-excellent'; if (accuracy >= 80) resultClass = 'results-excellent';
else if (accuracy >= 60) resultClass = 'results-good'; else if (accuracy >= 60) resultClass = 'results-good';
// Check if there are more groups // DYNAMIC MODE: Single "Continue" button - orchestrator decides next exercise
const hasMoreGroups = this.currentGroupIndex < this.allVocabularyGroups.length - 1;
const buttonText = hasMoreGroups ? 'Continue to Next Group' : 'Complete Vocabulary Exercise';
const buttonId = hasMoreGroups ? 'next-group-btn' : 'complete-btn';
const resultsHTML = ` const resultsHTML = `
<div class="group-results-content ${resultClass}"> <div class="group-results-content ${resultClass}">
<h3>📊 Group ${this.currentGroupIndex + 1} Results</h3> <h3>📊 Session Results</h3>
<div class="results-summary"> <div class="results-summary">
<div class="accuracy-display"> <div class="accuracy-display">
<span class="accuracy-number">${accuracy}%</span> <span class="accuracy-number">${accuracy}%</span>
@ -878,13 +879,10 @@ class VocabularyModule extends DRSExerciseInterface {
<div class="count-display"> <div class="count-display">
${correctCount} / ${totalCount} correct ${correctCount} / ${totalCount} correct
</div> </div>
<div class="group-progress">
Group ${this.currentGroupIndex + 1} of ${this.allVocabularyGroups.length}
</div>
</div> </div>
<div class="results-actions"> <div class="results-actions">
<button id="${buttonId}" class="btn btn-primary">${buttonText}</button> <button id="continue-btn" class="btn btn-primary">Continue </button>
</div> </div>
</div> </div>
`; `;
@ -896,17 +894,12 @@ class VocabularyModule extends DRSExerciseInterface {
if (card) card.style.display = 'none'; if (card) card.style.display = 'none';
if (controls) controls.style.display = 'none'; if (controls) controls.style.display = 'none';
// Add button listeners // Add button listener
const nextGroupBtn = document.getElementById('next-group-btn'); const continueBtn = document.getElementById('continue-btn');
const completeBtn = document.getElementById('complete-btn');
if (nextGroupBtn) { if (continueBtn) {
nextGroupBtn.onclick = () => this._moveToNextGroup(); continueBtn.onclick = () => {
} // Complete exercise and let orchestrator decide next step
if (completeBtn) {
completeBtn.onclick = () => {
// Complete exercise directly through orchestrator instead of EventBus
if (this.orchestrator && this.orchestrator.completeExercise) { if (this.orchestrator && this.orchestrator.completeExercise) {
this.orchestrator.completeExercise({ this.orchestrator.completeExercise({
moduleType: 'vocabulary', moduleType: 'vocabulary',
@ -914,7 +907,7 @@ class VocabularyModule extends DRSExerciseInterface {
progress: this.getProgress() progress: this.getProgress()
}); });
} else { } else {
console.log('✅ Vocabulary exercise completed'); console.log('✅ Vocabulary session completed, orchestrator will decide next exercise');
// Fallback: use drsDebug if available // Fallback: use drsDebug if available
if (window.drsDebug?.instance?.completeExercise) { if (window.drsDebug?.instance?.completeExercise) {
window.drsDebug.instance.completeExercise(); window.drsDebug.instance.completeExercise();
@ -924,54 +917,6 @@ class VocabularyModule extends DRSExerciseInterface {
} }
} }
_moveToNextGroup() {
console.log(`🔄 Moving to next vocabulary group (${this.currentGroupIndex + 1} -> ${this.currentGroupIndex + 2})`);
// Check if there's a next group
if (this.currentGroupIndex >= this.allVocabularyGroups.length - 1) {
console.warn('⚠️ No more vocabulary groups available');
return;
}
// Move to next group
this.currentGroupIndex++;
this.currentVocabularyGroup = this.allVocabularyGroups[this.currentGroupIndex];
// Verify the group exists and has words
if (!this.currentVocabularyGroup || this.currentVocabularyGroup.length === 0) {
console.error('❌ Next vocabulary group is empty or undefined');
return;
}
console.log(`📚 Loaded group ${this.currentGroupIndex + 1} with ${this.currentVocabularyGroup.length} words:`,
this.currentVocabularyGroup.map(w => w.word));
this.currentWordIndex = 0;
this.groupResults = [];
this.isRevealed = false;
// Shuffle new group if needed
if (this.config.randomizeOrder) {
this._shuffleArray(this.currentVocabularyGroup);
}
// Hide results and show vocabulary sections
const resultsContainer = document.getElementById('group-results');
const card = document.getElementById('vocabulary-card');
const controls = document.getElementById('exercise-controls');
if (resultsContainer) {
resultsContainer.style.display = 'none';
}
// Show card and controls sections
if (card) card.style.display = 'block';
if (controls) controls.style.display = 'block';
// Present first word of new group
this._presentCurrentWord();
}
_setInputEnabled(enabled) { _setInputEnabled(enabled) {
const input = document.getElementById('translation-input'); const input = document.getElementById('translation-input');
const submitBtn = document.getElementById('submit-btn'); const submitBtn = document.getElementById('submit-btn');
@ -1010,12 +955,25 @@ class VocabularyModule extends DRSExerciseInterface {
} }
} }
_createVocabularyGroups(vocabulary, groupSize) { /**
const groups = []; * Select N random words from an array
for (let i = 0; i < vocabulary.length; i += groupSize) { * @param {Array} words - Array of word objects
groups.push(vocabulary.slice(i, i + groupSize)); * @param {number} count - Number of words to select
* @returns {Array} - Random selection of words
*/
_selectRandomWords(words, count) {
if (words.length <= count) {
return [...words]; // Return all if not enough words
} }
return groups;
// Fisher-Yates shuffle and take first N
const shuffled = [...words];
for (let i = shuffled.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
}
return shuffled.slice(0, count);
} }
_shuffleArray(array) { _shuffleArray(array) {
@ -1289,8 +1247,6 @@ class VocabularyModule extends DRSExerciseInterface {
details: { details: {
correctWords, correctWords,
totalWords, totalWords,
currentGroupIndex: this.currentGroupIndex,
totalGroups: this.allVocabularyGroups ? this.allVocabularyGroups.length : 1,
groupResults: this.groupResults, groupResults: this.groupResults,
masteryPercentage: score masteryPercentage: score
} }
@ -1364,8 +1320,7 @@ class VocabularyModule extends DRSExerciseInterface {
validation: results, validation: results,
context: { context: {
moduleType: 'vocabulary', moduleType: 'vocabulary',
groupIndex: this.currentGroupIndex, dynamicMode: true
totalGroups: this.allVocabularyGroups ? this.allVocabularyGroups.length : 1
} }
}); });
} }
@ -1398,9 +1353,8 @@ class VocabularyModule extends DRSExerciseInterface {
...this.config, ...this.config,
groupSize: this.config.groupSize, groupSize: this.config.groupSize,
masteryThreshold: this.config.masteryThreshold, masteryThreshold: this.config.masteryThreshold,
currentGroupIndex: this.currentGroupIndex, wordCount,
totalGroups: this.allVocabularyGroups ? this.allVocabularyGroups.length : 1, dynamicMode: true // Flag to indicate dynamic word selection
wordCount
} }
}; };
} }

View File

@ -111,9 +111,9 @@ class WordDiscoveryModule extends DRSExerciseInterface {
/** /**
* Show current word with all details * Show current word with all details
*/ */
_showCurrentWord() { async _showCurrentWord() {
if (this.currentWordIndex >= this.currentWords.length) { if (this.currentWordIndex >= this.currentWords.length) {
this._completeDiscovery(); await this._completeDiscovery();
return; return;
} }
@ -249,77 +249,74 @@ class WordDiscoveryModule extends DRSExerciseInterface {
/** /**
* Go to previous word * Go to previous word
*/ */
_previousWord() { async _previousWord() {
if (this.currentWordIndex > 0) { if (this.currentWordIndex > 0) {
this.currentWordIndex--; this.currentWordIndex--;
this._showCurrentWord(); await this._showCurrentWord();
} }
} }
/** /**
* Go to next word * Go to next word
*/ */
_nextWord() { async _nextWord() {
if (this.currentWordIndex < this.currentWords.length - 1) { if (this.currentWordIndex < this.currentWords.length - 1) {
this.currentWordIndex++; this.currentWordIndex++;
this._showCurrentWord(); await this._showCurrentWord();
} }
} }
/** /**
* Complete discovery session * Complete discovery session
*/ */
_completeDiscovery() { async _completeDiscovery() {
// Mark all current words as discovered // Mark all current words as discovered (MUST await to ensure persistence)
this.currentWords.forEach(wordObj => { for (const wordObj of this.currentWords) {
this.prerequisiteEngine.markWordDiscovered(wordObj.word); await this.prerequisiteEngine.markWordDiscovered(wordObj.word, {
sessionId: Date.now(),
moduleType: 'word-discovery',
timestamp: new Date().toISOString()
});
this.discoveredWords.add(wordObj.word); this.discoveredWords.add(wordObj.word);
}); }
console.log(`✅ Discovery completed for ${this.currentWords.length} words`); console.log(`✅ Discovery completed for ${this.currentWords.length} words`);
// Show completion message // Show completion message with single "Continue" button
this.container.innerHTML = ` this.container.innerHTML = `
<div class="discovery-complete"> <div class="discovery-complete">
<h2>🎉 Word Discovery Complete!</h2> <h2>🎉 Word Discovery Complete!</h2>
<p>You've discovered ${this.currentWords.length} new words.</p> <p>You've discovered ${this.currentWords.length} new words.</p>
<p>Now you can practice them with flashcards!</p>
<div class="discovered-words"> <div class="discovered-words">
${this.currentWords.map(w => `<span class="discovered-word">${w.word}</span>`).join('')} ${this.currentWords.map(w => `<span class="discovered-word">${w.word}</span>`).join('')}
</div> </div>
<button id="start-flashcards" class="btn btn-primary"> <button id="continue-btn" class="btn btn-primary">
Start Flashcard Practice Continue
</button> </button>
</div> </div>
`; `;
// Auto-redirect to flashcards after a few seconds // Attach event listener to Continue button
setTimeout(() => { document.getElementById('continue-btn')?.addEventListener('click', () => {
this._redirectToFlashcards(); // Complete exercise and let orchestrator decide next step
}, 3000); if (this.orchestrator && this.orchestrator.completeExercise) {
this.orchestrator.completeExercise({
document.getElementById('start-flashcards')?.addEventListener('click', () => { moduleType: 'word-discovery',
this._redirectToFlashcards(); wordsDiscovered: this.currentWords.length,
words: this.currentWords.map(w => w.word),
score: 100, // Discovery is always successful
completed: true
});
} else {
console.log('✅ Word Discovery completed, orchestrator will decide next exercise');
}
}); });
this.isActive = false; this.isActive = false;
} }
/**
* Redirect to DRS VocabularyModule (flashcard system)
*/
_redirectToFlashcards() {
// Emit completion event to trigger DRS VocabularyModule
this.orchestrator._eventBus.emit('exercise:completed', {
type: 'word-discovery',
words: this.currentWords.map(w => w.word),
nextAction: 'vocabulary-flashcards', // This will trigger VocabularyModule in DRS
nextExerciseType: 'vocabulary-flashcards'
});
}
/** /**
* Validate method (not used for discovery) * Validate method (not used for discovery)
*/ */

View File

@ -27,8 +27,8 @@ class ExerciseFactory {
'grammar-practice-AI': 'GrammarAnalysisModule', 'grammar-practice-AI': 'GrammarAnalysisModule',
'translation': 'TranslationModule', 'translation': 'TranslationModule',
'open-response': 'OpenResponseModule', 'open-response': 'OpenResponseModule',
'phrase': 'PhraseModule', 'phrase': 'TextAnalysisModule', // REPLACED: was PhraseModule, now using TextAnalysisModule
'phrase-practice': 'PhraseModule', 'phrase-practice': 'TextAnalysisModule', // REPLACED: was PhraseModule, now using TextAnalysisModule
'audio': 'AudioModule', 'audio': 'AudioModule',
'listening-comprehension': 'AudioModule', 'listening-comprehension': 'AudioModule',
'listening-comprehension-AI': 'AudioModule', 'listening-comprehension-AI': 'AudioModule',

View File

@ -252,6 +252,12 @@ class PrerequisiteEngine extends ProgressSystemInterface {
* @returns {Object} - Progress statistics * @returns {Object} - Progress statistics
*/ */
getMasteryProgress() { getMasteryProgress() {
// Initialize sets if they don't exist
if (!this.masteredTexts) this.masteredTexts = new Set();
if (!this.masteredDialogs) this.masteredDialogs = new Set();
if (!this.masteredAudios) this.masteredAudios = new Set();
if (!this.masteredImages) this.masteredImages = new Set();
return { return {
vocabulary: { vocabulary: {
total: this.chapterVocabulary.size, total: this.chapterVocabulary.size,
@ -263,6 +269,26 @@ class PrerequisiteEngine extends ProgressSystemInterface {
mastered: this.masteredPhrases.size, mastered: this.masteredPhrases.size,
percentage: Math.round((this.masteredPhrases.size / Math.max(this.contentAnalysis?.phrases.total || 1, 1)) * 100) percentage: Math.round((this.masteredPhrases.size / Math.max(this.contentAnalysis?.phrases.total || 1, 1)) * 100)
}, },
texts: {
total: this.contentAnalysis?.texts.total || 0,
mastered: this.masteredTexts.size,
percentage: Math.round((this.masteredTexts.size / Math.max(this.contentAnalysis?.texts.total || 1, 1)) * 100)
},
dialogs: {
total: this.contentAnalysis?.dialogs.total || 0,
mastered: this.masteredDialogs.size,
percentage: Math.round((this.masteredDialogs.size / Math.max(this.contentAnalysis?.dialogs.total || 1, 1)) * 100)
},
audio: {
total: this.contentAnalysis?.audio.total || 0,
mastered: this.masteredAudios.size,
percentage: Math.round((this.masteredAudios.size / Math.max(this.contentAnalysis?.audio.total || 1, 1)) * 100)
},
images: {
total: this.contentAnalysis?.images.total || 0,
mastered: this.masteredImages.size,
percentage: Math.round((this.masteredImages.size / Math.max(this.contentAnalysis?.images.total || 1, 1)) * 100)
},
grammar: { grammar: {
total: this.contentAnalysis?.grammar.concepts || 0, total: this.contentAnalysis?.grammar.concepts || 0,
mastered: this.masteredGrammar.size, mastered: this.masteredGrammar.size,
@ -697,16 +723,8 @@ class PrerequisiteEngine extends ProgressSystemInterface {
// ======================================== // ========================================
// ProgressSystemInterface REQUIRED METHODS // ProgressSystemInterface REQUIRED METHODS
// ======================================== // ========================================
// Note: markWordDiscovered and markWordMastered are already implemented above (lines 583-655)
async markWordDiscovered(word, metadata = {}) { // They handle both in-memory cache and persistence
this.markDiscovered(word);
await this.progressManager.saveDiscoveredWord(word, metadata);
}
async markWordMastered(word, metadata = {}) {
this.markMastered(word, metadata);
await this.progressManager.saveMasteredWord(word, metadata);
}
isWordDiscovered(word) { isWordDiscovered(word) {
return this.isDiscovered(word); return this.isDiscovered(word);

View File

@ -33,6 +33,7 @@ class Button {
*/ */
_createButton() { _createButton() {
this.element = document.createElement('button'); this.element = document.createElement('button');
this.element.type = 'button'; // CRITICAL: Prevent form submission (default is "submit")
this.element.className = this._getButtonClasses(); this.element.className = this._getButtonClasses();
if (this.config.id) { if (this.config.id) {

View File

@ -347,6 +347,9 @@ class ContentLoader extends Module {
case 'reading': case 'reading':
// Reading = comprehension with real passages // Reading = comprehension with real passages
return await this._generateReadingFromRealContent(realContent, difficulty); return await this._generateReadingFromRealContent(realContent, difficulty);
case 'phrase':
// Phrase comprehension exercises
return this._generatePhraseFromRealContent(realContent, difficulty);
case 'audio': case 'audio':
case 'listening-comprehension-QCM': case 'listening-comprehension-QCM':
case 'listening-comprehension-AI': case 'listening-comprehension-AI':
@ -1812,6 +1815,52 @@ Return ONLY valid JSON:
}; };
} }
_generatePhraseFromRealContent(realContent, difficulty) {
console.log('💬 Generating phrase exercise from real content');
if (!realContent.phrases || Object.keys(realContent.phrases).length === 0) {
throw new Error('No phrases found in content');
}
const phrasesEntries = Object.entries(realContent.phrases);
console.log(`✅ Found ${phrasesEntries.length} phrases available`);
// Select one random phrase
const selectedPhrases = this._selectRandomItems(phrasesEntries, 1);
const [phraseText, phraseData] = selectedPhrases[0];
// Wrap in steps array like text exercises to enable proper validation flow
const steps = [{
id: `phrase-step-1`,
type: 'phrase',
content: {
phrase: {
id: phraseText,
english: phraseText,
text: phraseText,
user_language: phraseData.user_language,
translation: phraseData.user_language,
context: phraseData.context,
pronunciation: phraseData.pronunciation
}
}
}];
return {
id: `phrase-exercise-${Date.now()}`,
type: 'phrase',
title: `Phrase Comprehension: ${realContent.name}`,
description: `Understand and analyze academic phrases from ${realContent.name}`,
difficulty,
steps, // Now has steps array like text exercises
metadata: {
source: 'real-phrases',
chapterInfo: realContent.metadata,
totalPhrasesAvailable: phrasesEntries.length
}
};
}
_generateGrammarFromRealContent(realContent, difficulty) { _generateGrammarFromRealContent(realContent, difficulty) {
if (!realContent.vocabulary) { if (!realContent.vocabulary) {
throw new Error('No vocabulary found in content'); throw new Error('No vocabulary found in content');

View File

@ -40,7 +40,7 @@ class IntelligentSequencer extends Module {
}; };
// Available exercise types and difficulties // Available exercise types and difficulties
this._exerciseTypes = ['text', 'reading', 'audio', 'grammar']; this._exerciseTypes = ['text', 'reading', 'phrase', 'audio', 'grammar'];
this._difficulties = ['easy', 'medium', 'hard']; this._difficulties = ['easy', 'medium', 'hard'];
// Current session state // Current session state
@ -140,10 +140,13 @@ class IntelligentSequencer extends Module {
return null; return null;
} }
const scoredCandidates = candidates.map(candidate => ({ // Calculate scores for all candidates (async)
...candidate, const scoredCandidates = await Promise.all(
score: this._calculateExerciseScore(candidate) candidates.map(async candidate => ({
})); ...candidate,
score: await this._calculateExerciseScore(candidate)
}))
);
// Sort by score (higher is better) // Sort by score (higher is better)
scoredCandidates.sort((a, b) => b.score - a.score); scoredCandidates.sort((a, b) => b.score - a.score);
@ -328,6 +331,10 @@ class IntelligentSequencer extends Module {
// Reading needs predefined exercises or content with questions // Reading needs predefined exercises or content with questions
return this._hasReadingContent(content); return this._hasReadingContent(content);
case 'phrase':
// Phrase comprehension needs phrases object with content
return content.phrases && Object.keys(content.phrases).length > 0;
case 'grammar': case 'grammar':
// Grammar needs varied word types // Grammar needs varied word types
if (!content.vocabulary) return false; if (!content.vocabulary) return false;
@ -387,7 +394,7 @@ class IntelligentSequencer extends Module {
return false; return false;
} }
_calculateExerciseScore(candidate) { async _calculateExerciseScore(candidate) {
// Calculate variety score (avoid recent repetition) // Calculate variety score (avoid recent repetition)
const varietyScore = this._calculateVarietyScore(candidate); const varietyScore = this._calculateVarietyScore(candidate);
@ -397,12 +404,15 @@ class IntelligentSequencer extends Module {
// Calculate freshness score (prefer less practiced combinations) // Calculate freshness score (prefer less practiced combinations)
const freshnessScore = this._calculateFreshnessScore(candidate); const freshnessScore = this._calculateFreshnessScore(candidate);
// Weighted combination // NEW: Calculate content abundance bonus (prefer types with more content)
const abundanceBonus = await this._calculateContentAbundanceBonus(candidate.type);
// Weighted combination with abundance bonus
const totalScore = ( const totalScore = (
varietyScore * this._config.varietyWeight + varietyScore * this._config.varietyWeight +
performanceScore * this._config.performanceWeight + performanceScore * this._config.performanceWeight +
freshnessScore * this._config.freshnessWeight freshnessScore * this._config.freshnessWeight
); ) + abundanceBonus; // Add bonus directly to total
return totalScore; return totalScore;
} }
@ -476,6 +486,76 @@ class IntelligentSequencer extends Module {
return Math.max(1.0 - (comboCount * 0.1), 0.1); return Math.max(1.0 - (comboCount * 0.1), 0.1);
} }
async _calculateContentAbundanceBonus(exerciseType) {
// Give bonus to exercise types with MORE available content
// This makes phrase (53 items) more likely to appear than text (3 items)
const session = this._currentSession;
if (!session) return 0;
try {
const contentPath = `/content/chapters/${session.chapterId || session.bookId}.json`;
const response = await fetch(contentPath);
if (!response.ok) return 0;
const content = await response.json();
let itemCount = 0;
// Count available items for this exercise type
switch (exerciseType) {
case 'phrase':
itemCount = content.phrases ? Object.keys(content.phrases).length : 0;
break;
case 'text':
itemCount = content.texts ? content.texts.length : 0;
break;
case 'reading':
// Count texts + dialogs with questions
const textsWithQ = content.texts ? content.texts.filter(t => t.questions?.length > 0).length : 0;
const dialogsWithQ = content.dialogs ? Object.values(content.dialogs).filter(d => d.questions?.length > 0).length : 0;
itemCount = textsWithQ + dialogsWithQ;
break;
case 'audio':
// Count dialogs
itemCount = content.dialogs ? Object.keys(content.dialogs).length : 0;
break;
case 'grammar':
itemCount = content.grammar ? Object.keys(content.grammar).length : 0;
break;
default:
itemCount = 0;
}
// Calculate bonus based on item count
// 50+ items → 0.5 bonus (HUGE boost)
// 20-49 items → 0.3 bonus (big boost)
// 10-19 items → 0.2 bonus (moderate boost)
// 5-9 items → 0.1 bonus (small boost)
// <5 items → 0 bonus
if (itemCount >= 50) {
console.log(`📊 Content abundance bonus for ${exerciseType}: 0.5 (${itemCount} items)`);
return 0.5;
} else if (itemCount >= 20) {
console.log(`📊 Content abundance bonus for ${exerciseType}: 0.3 (${itemCount} items)`);
return 0.3;
} else if (itemCount >= 10) {
console.log(`📊 Content abundance bonus for ${exerciseType}: 0.2 (${itemCount} items)`);
return 0.2;
} else if (itemCount >= 5) {
console.log(`📊 Content abundance bonus for ${exerciseType}: 0.1 (${itemCount} items)`);
return 0.1;
}
return 0;
} catch (error) {
console.warn(`⚠️ Error calculating content abundance:`, error);
return 0;
}
}
_updatePerformanceTracking(record) { _updatePerformanceTracking(record) {
const type = record.type; const type = record.type;