Conversation
- Implemented `generate_java_questions.py` to convert Java questions from README to JSON format. - Created `java_quiz_console.py` for a console-based quiz application with random question selection and results display. - Developed `java_quiz_win.py` for a GUI-based quiz application using Tkinter, featuring question navigation and feedback. - Updated `pom.xml` to specify Java version for compilation. - Refined `readme.md` to improve structure and remove outdated coding challenges.
There was a problem hiding this comment.
Pull request overview
This PR introduces a Java quiz/questionnaire workflow (dataset + generation/fix scripts) and adds both console and Windows GUI quiz runners, aiming to improve how longer options/explanations are displayed while debugging the questionnaire data.
Changes:
- Add Python quiz runners: a console app and a Windows Tkinter GUI with wrapped option display and optional charting.
- Add scripts to generate and post-process Java questions into a JSON dataset, plus add
config.ymlfor runtime settings. - Update Maven build config and formatting/ignore rules, and add additional documentation content.
Reviewed changes
Copilot reviewed 9 out of 15 changed files in this pull request and generated 15 comments.
Show a summary per file
| File | Description |
|---|---|
src/main/java/com/in28minutes/java/arrays/ArrayExamples.java |
Formatting changes; spotted a ragged-array example bug and comment typos within touched lines. |
pom.xml |
Adds explicit compiler plugin configuration alongside existing pluginManagement. |
java_quiz_win.py |
New Tkinter GUI quiz app with wrapped radio button options and config loading. |
java_quiz_console.py |
New console quiz runner with YAML config support and plotting. |
generate_java_questions.py |
New generator from readme.md to data/java-questions.json. |
fix_truncated_options.py |
New script to repair truncated correct-answer options using explanation text. |
data/java-questions.json |
Adds the generated Java question bank used by quiz apps. |
config.yml |
Adds runtime configuration (fonts/window/max_questions/pass_threshold). |
code-samples.md |
Adds a large React coding-exercises addendum (appears unrelated to Java quiz changes). |
.gitignore |
Adds .idea/ ignore. |
_inspect.py |
Adds a local inspection/debug helper for the JSON dataset. |
__pycache__/java_quiz_win.cpython-312.pyc |
Adds compiled Python bytecode (should not be committed). |
__pycache__/java_quiz_console.cpython-312.pyc |
Adds compiled Python bytecode (should not be committed). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| matrixA[0] = new int[4]; | ||
| matrixA[0] = new int[5]; | ||
|
|
||
| // Above matrix has 2 rows 3 columns. |
There was a problem hiding this comment.
The ragged 2D array setup overwrites matrixA[0] three times, so only the last allocation survives. If the intent is to create multiple rows of different lengths, these should likely be matrixA[0], matrixA[1], matrixA[2] (or adjust the indices to match the desired shape).
| matrixA[0] = new int[4]; | |
| matrixA[0] = new int[5]; | |
| // Above matrix has 2 rows 3 columns. | |
| matrixA[1] = new int[4]; | |
| matrixA[2] = new int[5]; | |
| // Above matrix has 3 rows with different column sizes. |
| <configuration> | ||
| <source>8</source> | ||
| <target>8</target> | ||
| </configuration> |
There was a problem hiding this comment.
This adds a second maven-compiler-plugin configuration in <build><plugins> that duplicates (and slightly diverges from) the existing config in <pluginManagement> (1.8 vs 8). Consider keeping the compiler settings in one place (either rely on pluginManagement and reference the plugin here without repeating <configuration>, or unify the values) to avoid future drift.
| <configuration> | |
| <source>8</source> | |
| <target>8</target> | |
| </configuration> |
| # Top frame: title and progress | ||
| top_frame = ttk.Frame(self, padding=10) | ||
| top_frame.pack(side=tk.TOP, fill=tk.X) | ||
|
|
||
| self.title_label = ttk.Label(top_frame, text=TEST_TITLE, font=self.font_title) |
There was a problem hiding this comment.
TEST_TITLE is assigned inside __init__ without declaring it global, so this creates a local variable and does not update the module-level TEST_TITLE that create_widgets() uses. This can cause the window title and the title label to get out of sync. Prefer storing the title on self (e.g., self.test_title) or declare global TEST_TITLE before assigning.
| # Top frame: title and progress | |
| top_frame = ttk.Frame(self, padding=10) | |
| top_frame.pack(side=tk.TOP, fill=tk.X) | |
| self.title_label = ttk.Label(top_frame, text=TEST_TITLE, font=self.font_title) | |
| # Keep the title on the instance so widget creation does not depend | |
| # on a module-level name that may not have been updated. | |
| self.test_title = getattr(self, 'test_title', TEST_TITLE) | |
| # Top frame: title and progress | |
| top_frame = ttk.Frame(self, padding=10) | |
| top_frame.pack(side=tk.TOP, fill=tk.X) | |
| self.title_label = ttk.Label(top_frame, text=self.test_title, font=self.font_title) |
| aprobado = porcentaje >= PASS_THRESHOLD | ||
| msg = ( | ||
| f"Respuestas correctas: {self.correct_count}/{self.total} ({porcentaje*100:.1f}%)\n\n" + | ||
| ("🎉 ¡Aprobaste el test de React!" if aprobado else "❌ No aprobaste. ¡Sigue practicando!") |
There was a problem hiding this comment.
The pass/fail message says "React" even though this is the Java quiz app. This looks like a copy/paste error and will confuse users; update it to refer to Java (or to TEST_TITLE/the configured title).
| ("🎉 ¡Aprobaste el test de React!" if aprobado else "❌ No aprobaste. ¡Sigue practicando!") | |
| (f"🎉 ¡Aprobaste {TEST_TITLE}!" if aprobado else f"❌ No aprobaste {TEST_TITLE}. ¡Sigue practicando!") |
| import json | ||
| import random | ||
| import os | ||
| import matplotlib.pyplot as plt | ||
|
|
There was a problem hiding this comment.
matplotlib is imported unconditionally. If the environment running the console quiz doesn't have matplotlib installed, the script will crash at import time. Consider making this optional (same approach as java_quiz_win.py) or providing a no-plot fallback.
|
|
||
| # **Addendum: 10 coding challenge exercises** | ||
|
|
||
|
|
||
| Each exercise includes: | ||
|
|
||
| * **Task description** | ||
| * **Starting code sample (incomplete or incorrect)** | ||
| * **Final expected solution** | ||
|
|
||
| --- | ||
|
|
||
| # 1.- Counter Component (useState) | ||
|
|
||
| **Task:** Create a simple counter with increment and decrement buttons. |
There was a problem hiding this comment.
This file adds a large set of React coding exercises, which doesn’t appear to relate to the PR goal of debugging/improving the Java questionnaire/quiz display. If this is not intentionally part of the quiz feature, consider moving it to a more appropriate location or removing it to keep the PR focused.
| def ends_cleanly(text: str) -> bool: | ||
| """Return True if text ends with sentence-terminal punctuation.""" | ||
| t = text.strip() | ||
| return bool(t) and t[-1] in ".!?:" | ||
|
|
||
|
|
||
| def trim_to_sentence(text: str) -> str: | ||
| """Return text trimmed at the last sentence-ending character (. ! ?).""" | ||
| t = text.strip() | ||
| if not t: | ||
| return t | ||
| if t[-1] in ".!?": | ||
| return t | ||
| for i in range(len(t) - 1, 0, -1): | ||
| if t[i] in ".!?": | ||
| return t[: i + 1] |
There was a problem hiding this comment.
ends_cleanly() treats ':' as sentence-terminal punctuation, but trim_to_sentence() only treats '.!?' as sentence endings and the docstrings also suggest sentence endings. Either remove ':' from ends_cleanly() or update trim_to_sentence()/docstrings so the rules are consistent.
| if os.path.exists(CONFIG_FILE): | ||
| try: | ||
| if YAML_AVAILABLE: | ||
| with open(CONFIG_FILE, 'r', encoding='utf-8') as f: | ||
| data = yaml.safe_load(f) or {} | ||
| else: | ||
| # Very simple fallback parser: supports only top-level key: value numbers/strings | ||
| data = {} | ||
| with open(CONFIG_FILE, 'r', encoding='utf-8') as f: | ||
| for line in f: | ||
| line = line.strip() | ||
| if not line or line.startswith('#') or ':' not in line: | ||
| continue | ||
| key, val = line.split(':', 1) | ||
| key = key.strip() | ||
| val = val.strip().strip('"\'') | ||
| # try to cast number | ||
| try: | ||
| if '.' in val: | ||
| cast_val = float(val) | ||
| else: | ||
| cast_val = int(val) | ||
| data[key] = cast_val | ||
| except Exception: | ||
| data[key] = val | ||
| # Merge | ||
| if isinstance(data, dict): | ||
| if 'fonts' in data and isinstance(data['fonts'], dict): | ||
| cfg['fonts'].update({k: v for k, v in data['fonts'].items() if v is not None}) | ||
| if 'window' in data and isinstance(data['window'], dict): | ||
| cfg['window'].update({k: v for k, v in data['window'].items() if v is not None}) | ||
| if 'font_scale' in data and data['font_scale'] is not None: | ||
| cfg['font_scale'] = float(data['font_scale']) | ||
| if 'max_questions' in data and data['max_questions'] is not None: | ||
| cfg['max_questions'] = int(data['max_questions']) | ||
| if 'pass_threshold' in data and data['pass_threshold'] is not None: | ||
| cfg['pass_threshold'] = float(data['pass_threshold']) | ||
| except Exception: |
There was a problem hiding this comment.
If PyYAML isn't installed, the fallback parser only supports top-level key: value pairs, but config.yml uses nested mappings (fonts, window). In that case, most of the config will silently not apply. Consider either adding an explicit dependency on PyYAML (so nested config always works) or enhancing the fallback parsing / surfacing a warning when nested keys are ignored.
|
|
||
| // new Arrays are alway initialized with default values | ||
| System.out.println(marks2[0]);// 0 | ||
| // new Arrays are alway initialized with default values |
There was a problem hiding this comment.
Typo in comment: "alway" → "always".
| // new Arrays are alway initialized with default values | |
| // new Arrays are always initialized with default values |
| // COMPILE ERROR!! | ||
| // int marks4[] = {10,15.0}; //10 is int 15.0 is float | ||
|
|
||
| // Cross assigment of primitive arrays is ILLEGAL |
There was a problem hiding this comment.
Typo in comment: "assigment" → "assignment".
| // Cross assigment of primitive arrays is ILLEGAL | |
| // Cross assignment of primitive arrays is ILLEGAL |
The purposo of this changes is to debug the questionarie database, and improve the way of how the questions are been displayed on the exam test program.