diff --git a/.coveragerc b/.coveragerc index a92b362..6c84ee1 100644 --- a/.coveragerc +++ b/.coveragerc @@ -10,6 +10,6 @@ exclude_lines = raise NotImplementedError [html] -directory = coverage_html +directory = coverage title = CodeExecutor-API Coverage Report show_contexts = true diff --git a/.gitignore b/.gitignore index cbfeb40..28d2f51 100644 --- a/.gitignore +++ b/.gitignore @@ -46,7 +46,7 @@ alembic/versions/__pycache__/ *.exe # Testing / Coverage -coverage_html/ +coverage/ .coverage .pytest_cache/ htmlcov/ \ No newline at end of file diff --git a/API_DOCUMENTATION.md b/API_DOCUMENTATION.md index 11fded4..72b00e9 100644 --- a/API_DOCUMENTATION.md +++ b/API_DOCUMENTATION.md @@ -3,9 +3,11 @@ Dynamic code execution API supporting multiple languages and database-backed problem management. ## Base URL + `http://localhost:3000` ## Interactive Documentation + Interactive docs are available at: [http://localhost:3000/docs](http://localhost:3000/docs) --- @@ -13,13 +15,16 @@ Interactive docs are available at: [http://localhost:3000/docs](http://localhost ## Endpoints ### 1. List Problems + Retrieve a summary of all problems in the database. Supports filtering by category or tag. + - **URL**: `/problems` - **Method**: `GET` - **Query Parameters**: - `category`: Filter by category name (e.g., `/problems?category=Math`) - `tag`: Filter by tag name (e.g., `/problems?tag=String`) - **Response**: `200 OK` + ```json { "status": "success", @@ -30,16 +35,21 @@ Retrieve a summary of all problems in the database. Supports filtering by catego ``` ### 2. Get Problem Details + Retrieve specific problem metadata, configuration, and public test cases. + - **URL**: `/problem/` - **Method**: `GET` - **Response**: `200 OK` ### 3. Execute Code (Problem-based) + Run code against test cases associated with a specific problem. + - **URL**: `/code/` - **Method**: `POST` - **Body**: + ```json { "language": "python", @@ -48,10 +58,13 @@ Run code against test cases associated with a specific problem. ``` ### 4. Custom Execution + Run arbitrary code without a pre-defined problem. + - **URL**: `/run?lang=python` - **Method**: `POST` - **Body**: + ```json { "code": "print('hello world')" @@ -61,6 +74,7 @@ Run arbitrary code without a pre-defined problem. --- ## Supported Languages + - **Python**: `python` - **JavaScript**: `javascript` - **Java**: `java` diff --git a/README.md b/README.md index 84d1d0d..39d3c94 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,7 @@ If you modify the models in `src/models/`, use these commands to sync the databa - **Check Status**: `docker compose --profile local exec code-api alembic current` - **Apply Migrations**: `docker compose --profile local exec code-api alembic upgrade head` - **Generate New Migration**: + ```bash docker compose --profile local exec code-api alembic revision --autogenerate -m "description_of_change" ``` @@ -85,23 +86,63 @@ If you want to connect to **NeonDB** online and migrate it to the latest version 1. **Get Connection String**: Copy your connection string from the [Neon Console](https://console.neon.tech/) (ensure `?sslmode=require` is included). 2. **Apply Migrations**: Run the following command, replacing `YOUR_NEON_URL` with your actual connection string: + ```bash docker compose --profile local exec -e DATABASE_URL="YOUR_NEON_URL" local-code-api alembic upgrade head ``` + 3. **(Optional) Seed Data**: If your Neon database is empty, you can seed it with the default problems: + ```bash docker compose --profile local exec -e DATABASE_URL="YOUR_NEON_URL" local-code-api python3 -m scripts.seed ``` _(Alternatively, you can simply update the `DATABASE_URL` in your `.env` file and run the standard migration commands.)_ -### 🌱 Data Seeding +### 🌱 Data Seeding & Cleanup + +For manual data management, use these commands from the **project root**: + +#### 1️⃣ Java Restroom Seeding (40+ Questions & Riddles) -If you need to re-seed or reset the initial data: +Seed the database with Java MCQs, riddles, and problems tagged as `JAV_RESTROOM`: + +```bash +# Running via Docker (Must rebuild if scripts are modified) +docker compose --profile local up -d --build +docker compose --profile local exec local-code-api python3 -m scripts.seeders.seed_restroom_java + +# Running Locally (Ensure .env is configured or set DATABASE_URL) +export DATABASE_URL=postgresql://postgres:postgres@localhost:5432/code_executor +PYTHONPATH=src python3 src/scripts/seeders/seed_restroom_java.py +``` + +#### 2️⃣ Clear All Database Data + +Delete all entries from all tables (Riddles, Questions, Problems, etc.): + +```bash +# Running via Docker +docker compose --profile local exec local-code-api python3 -m scripts.delete + +# Running Locally +export DATABASE_URL=postgresql://postgres:postgres@localhost:5432/code_executor +PYTHONPATH=src python3 src/scripts/delete.py +``` + +#### 3️⃣ Standard Sample Seeding + +Seed the original set of coding problems (Two Sum, etc.): + +```bash +# Running via Docker (Recommended) +docker compose --profile local exec local-code-api python3 -m scripts.seed -- **Run Seeder**: `docker compose --profile local exec local-code-api python3 -m scripts.seed` - _(The seeder is idempotent and will skip problems that already exist!)_ +# Running Locally +export DATABASE_URL=postgresql://postgres:postgres@localhost:5432/code_executor +PYTHONPATH=src python3 src/scripts/seed.py +``` --- @@ -149,7 +190,7 @@ For the best developer experience, we've included a **Bruno Collection**: Tests are organized by feature group in the `tests/` directory: -``` +```cmd tests/ ├── conftest.py # Shared fixtures (Flask client, DB mocks) ├── problem/ # Problem endpoint tests @@ -160,30 +201,54 @@ tests/ └── docs/ # Documentation endpoint tests ``` -### Run All Tests +### Run with Coverage Report -```bash -python3 -m pytest -``` +The tests automatically generate an HTML report inside the container. To view it locally: -### Coverage Report +```bash +# 1. Run the tests +docker compose --profile local exec local-code-api python3 -m pytest -After running tests, open the interactive HTML coverage report: +# 2. Copy the report from the container to your machine +docker cp codeexecutor-api-local-code-api-1:/usr/src/app/coverage/ ./coverage/ -```bash -open coverage_html/index.html +# 3. Open it +open coverage/index.html ``` The report highlights **exactly which lines** were hit or missed during testing — click any file to see line-by-line coverage. +### Run Locally (Outside Docker) + +If you want to run tests without Docker for faster iteration: + +1. **Install Dependencies**: + + ```bash + pip install Flask gunicorn pytest sqlmodel alembic python-dotenv pydantic-settings esprima javalang pytest-cov pybars3 + ``` + + _(Note: `psycopg2-binary` might fail on some Python versions, but unit tests are mocked so you can skip it.)_ + +2. **Run Tests**: + + ```bash + PYTHONPATH=src python3 -m pytest + ``` + +3. **View Coverage**: + + ```bash + open coverage/index.html + ``` + ### Run a Specific Test Group ```bash -python3 -m pytest tests/problem/ # Problem tests only -python3 -m pytest tests/riddle/ # Riddle tests only +PYTHONPATH=src python3 -m pytest tests/problem/ ``` -> **Note**: Tests mock the database layer so they run locally without Postgres. Install test dependencies first: `pip install pytest pytest-cov` +> **Note**: Tests mock the database layer automatically, so no local Postgres is required. --- diff --git a/bruno/local/Question/get all random questions.bru b/bruno/local/Question/get all random questions.bru index 1be1256..b8a8f1d 100644 --- a/bruno/local/Question/get all random questions.bru +++ b/bruno/local/Question/get all random questions.bru @@ -5,13 +5,13 @@ meta { } get { - url: http://localhost:3000/question/random?tag=trivia + url: http://localhost:3000/question/random?tag=JAV_RESTROOM body: none auth: inherit } params:query { - tag: trivia + tag: JAV_RESTROOM } settings { diff --git a/pytest.ini b/pytest.ini index 9fb4498..3bffd35 100644 --- a/pytest.ini +++ b/pytest.ini @@ -8,5 +8,5 @@ addopts = --cov=services --cov=repositories --cov=api - --cov-report=html:coverage_html + --cov-report=html:coverage --cov-config=.coveragerc diff --git a/src/handlers/chunk_handler.py b/src/handlers/chunk_handler.py index e9bb5ef..ce3ffb8 100644 --- a/src/handlers/chunk_handler.py +++ b/src/handlers/chunk_handler.py @@ -1,21 +1,21 @@ from flask import jsonify, request -from repositories.chunk_repository import ChunkRepository +from services.chunk_service import ChunkService class ChunkHandler: def __init__(self): - self.repo = ChunkRepository() + self.service = ChunkService() def get_all_chunks(self): page = request.args.get('page', default=1, type=int) limit = request.args.get('limit', default=10, type=int) lang = request.args.get('lang') - chunks = self.repo.find_all(page=page, limit=limit, lang=lang) + chunks = self.service.get_all_chunks(page=page, limit=limit, lang=lang) return jsonify(status="success", data=chunks), 200 def get_chunk(self, chunk_id): lang = request.args.get('lang') - chunk = self.repo.get_details(chunk_id, lang=lang) + chunk = self.service.get_chunk(chunk_id, lang=lang) if not chunk: return jsonify(status="error", message="Chunk not found"), 404 return jsonify(status="success", data=chunk), 200 @@ -24,5 +24,5 @@ def get_random_chunks(self): limit = request.args.get('limit', default=1, type=int) lang = request.args.get('lang') - chunks = self.repo.find_random(limit=limit, lang=lang) + chunks = self.service.get_random_chunks(limit=limit, lang=lang) return jsonify(status="success", data=chunks), 200 diff --git a/src/repositories/choice_repository.py b/src/repositories/choice_repository.py index 314ceae..e26ade6 100644 --- a/src/repositories/choice_repository.py +++ b/src/repositories/choice_repository.py @@ -36,3 +36,9 @@ def count_by_question_id(self, question_id: UUID): with self._get_session() as session: statement = select(Choice).where(Choice.question_id == question_id) return len(session.exec(statement).all()) + + def find_all_by_question_id(self, question_id: UUID): + """Fetch all choices that is not hidden for a question.""" + with self._get_session() as session: + statement = select(Choice).where(Choice.question_id == question_id) + return session.exec(statement).all() diff --git a/src/repositories/chunk_repository.py b/src/repositories/chunk_repository.py index f4a4d8b..8e120e1 100644 --- a/src/repositories/chunk_repository.py +++ b/src/repositories/chunk_repository.py @@ -25,17 +25,20 @@ def find_all(self, page=1, limit=10, lang=None): statement = statement.order_by(Chunk.id).offset((page - 1) * limit).limit(limit) + # Use unique() for joinedload with collections results = session.exec(statement).unique().all() chunks = [] for chunk in results: - c_dict = self._serialize_chunk(chunk, lang) - chunks.append(c_dict) + chunks.append(self._serialize_chunk(chunk, lang)) return chunks def _serialize_chunk(self, chunk, lang=None): """Helper to serialize a chunk and optionally filter its templates by language.""" c_dict = chunk.model_dump() - c_dict["templates"] = [] + + # Move templates to config key in response + c_dict["config"] = {"templates": {}} + for t in chunk.templates: # Skip if language filter is active and doesn't match if lang and t.language != lang: @@ -43,13 +46,19 @@ def _serialize_chunk(self, chunk, lang=None): t_dict = { "id": str(t.id), - "language": t.language, "name": t.name, "template_code": t.template_code, "description": t.description, - "snippets": [{"placeholder_key": s.placeholder_key, "code_content": s.code_content} for s in t.snippets] + "snippets": {s.placeholder_key: s.code_content for s in t.snippets} } - c_dict["templates"].append(t_dict) + c_dict["config"]["templates"][t.language] = t_dict + + # Add expectations to config for consistency + if hasattr(chunk, "expectations") and chunk.expectations: + c_dict["expectations"] = [ + {"input": e.input, "output": e.output} for e in chunk.expectations + ] + return c_dict def find_by_id(self, chunk_id): @@ -72,22 +81,19 @@ def get_details(self, chunk_id, lang=None): def find_random(self, limit=1, lang=None): """Fetch random N chunks with their implementation details. Filters by language if provided.""" with self._get_session() as session: - statement = select(Chunk).options( - joinedload(Chunk.templates).joinedload(ChunkTemplate.snippets) - ) - - if lang: - # Require that the chunk HAS a template in that language - statement = statement.join(Chunk.templates).where(ChunkTemplate.language == lang) - - statement = statement.order_by(func.random()).limit(limit) - - results = session.exec(statement).unique().all() + statement = select(Chunk).order_by(func.random()) + # For simplicity, if lang is provided, we fetch more and filter in Python + # or just fetch all and filter. + results = session.exec(statement).all() if not results: return [] chunks = [] for chunk in results: + if lang and lang not in chunk.config.get("templates", {}): + continue chunks.append(self._serialize_chunk(chunk, lang)) + if len(chunks) >= limit: + break return chunks diff --git a/src/repositories/question_repository.py b/src/repositories/question_repository.py index 3d34d64..c801d19 100644 --- a/src/repositories/question_repository.py +++ b/src/repositories/question_repository.py @@ -43,7 +43,9 @@ def find_random_by_tag(self, tag_name: str, amount: int = 1): with self._get_session() as session: # Join with tags to filter, and eagerly load them for the response statement = select(Question).join(Question.tags).where(Tag.name.ilike(tag_name)).options( - joinedload(Question.tags) + joinedload(Question.tags), + joinedload(Question.categories), + joinedload(Question.choices) ) questions = session.exec(statement).unique().all() @@ -52,6 +54,7 @@ def find_random_by_tag(self, tag_name: str, amount: int = 1): # Random selection from results return random.sample(questions, min(len(questions), amount)) + def find_all(self, offset: int = 0, limit: int = 10): """Retrieve questions and total count using pagination.""" with self._get_session() as session: @@ -59,7 +62,11 @@ def find_all(self, offset: int = 0, limit: int = 10): count_stmt = select(func.count()).select_from(Question) total_count = session.exec(count_stmt).one() - statement = select(Question).options(joinedload(Question.choices)).offset(offset).limit(limit) + statement = select(Question).options( + joinedload(Question.choices), + joinedload(Question.tags), + joinedload(Question.categories) + ).offset(offset).limit(limit) questions = session.exec(statement).unique().all() return questions, total_count diff --git a/src/requirements.txt b/src/requirements.txt index 6c74785..0e1300e 100644 --- a/src/requirements.txt +++ b/src/requirements.txt @@ -9,4 +9,5 @@ esprima==4.0.1 javalang==0.13.0 pytest-cov==6.0.0 psycopg2-binary==2.9.6 -pybars3==0.9.7 \ No newline at end of file +pybars3==0.9.7 +tqdm==4.66.1 \ No newline at end of file diff --git a/src/scripts/__init__.py b/src/scripts/__init__.py index 679fff5..3210928 100644 --- a/src/scripts/__init__.py +++ b/src/scripts/__init__.py @@ -1 +1 @@ -from .seed import seed_data +# This file makes the folder a Python package. diff --git a/src/scripts/data/__init__.py b/src/scripts/data/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/scripts/data/java/__init__.py b/src/scripts/data/java/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/scripts/data/java/elevatorhall/__init__.py b/src/scripts/data/java/elevatorhall/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/scripts/data/java/hallway/__init__.py b/src/scripts/data/java/hallway/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/scripts/data/java/hallway/chunks.json b/src/scripts/data/java/hallway/chunks.json new file mode 100644 index 0000000..e69de29 diff --git a/src/scripts/data/java/hallway/problems.json b/src/scripts/data/java/hallway/problems.json new file mode 100644 index 0000000..e69de29 diff --git a/src/scripts/data/java/hallway/questions.json b/src/scripts/data/java/hallway/questions.json new file mode 100644 index 0000000..e69de29 diff --git a/src/scripts/data/java/hallway/riddles.json b/src/scripts/data/java/hallway/riddles.json new file mode 100644 index 0000000..e69de29 diff --git a/src/scripts/data/java/lockerroom/__init__.py b/src/scripts/data/java/lockerroom/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/scripts/data/java/lockerroom/chunks.json b/src/scripts/data/java/lockerroom/chunks.json new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/src/scripts/data/java/lockerroom/chunks.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/src/scripts/data/java/lockerroom/problems.json b/src/scripts/data/java/lockerroom/problems.json new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/src/scripts/data/java/lockerroom/problems.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/src/scripts/data/java/lockerroom/questions.json b/src/scripts/data/java/lockerroom/questions.json new file mode 100644 index 0000000..e54d9cc --- /dev/null +++ b/src/scripts/data/java/lockerroom/questions.json @@ -0,0 +1,1432 @@ +[ + { + "title": "LCK-I", + "text": "Which of the following is a primary goal of Encapsulation?", + "choices": [ + [ + "Allowing any class to modify internal data directly.", + false + ], + [ + "Bundling data and methods together while restricting direct access to some components.", + true + ], + [ + "Making sure a class has only one instance.", + false + ], + [ + "Speeding up the execution of mathematical loops.", + false + ] + ] + }, + { + "title": "LCK-II", + "text": "In Java, which keyword is primarily used to implement the principle of Inheritance?", + "choices": [ + [ + "implements", + false + ], + [ + "static", + false + ], + [ + "extends", + true + ], + [ + "encapsulate", + false + ] + ] + }, + { + "title": "LCK-III", + "text": "Which scenario best demonstrates Polymorphism?", + "choices": [ + [ + "A single Shape variable being used to refer to a Circle, a Square, or a Triangle object.", + true + ], + [ + "Hiding the password variable in a User class.", + false + ], + [ + "Running a program on multiple operating systems.", + false + ], + [ + "Using a for loop to iterate through a list.", + false + ] + ] + }, + { + "title": "LCK-IV", + "text": "Which of these is an example of Abstraction in a Java program?", + "choices": [ + [ + "Writing a very long method with 100 lines of code.", + false + ], + [ + "Using an Interface to define what a class should do without showing how it does it.", + true + ], + [ + "Using the private keyword on all variables.", + false + ], + [ + "Declaring an array with a fixed size.", + false + ] + ] + }, + { + "title": "LCK-V", + "text": "What is the relationship between a Class and an Object?", + "choices": [ + [ + "An object is a template used to create a class.", + false + ], + [ + "A class is an instance of an object in memory.", + false + ], + [ + "A class is the blueprint, and an object is the specific instance created from that blueprint.", + true + ], + [ + "There is no difference; they are synonyms in Java.", + false + ] + ] + }, + { + "title": "LCK-VI", + "text": "To implement Method Overloading, what must be true?", + "choices": [ + [ + "The method names must be different.", + false + ], + [ + "The methods must have the same name but different parameter lists (type or number).", + true + ], + [ + "One method must be in a parent class and the other in a child class.", + false + ], + [ + "The methods must return different data types but have the same parameters.", + false + ] + ] + }, + { + "title": "LCK-VII", + "text": "When a child class provides a specific implementation for a method that is already defined in its parent class, this is known as:", + "choices": [ + [ + "Method Overloading", + false + ], + [ + "Method Overriding", + true + ], + [ + "Method Redundancy", + false + ], + [ + "Method Extraction", + false + ] + ] + }, + { + "title": "LCK-VIII", + "text": "If a variable is declared as static in Java, what does it mean?", + "choices": [ + [ + "Every object of that class has its own unique copy of the variable.", + false + ], + [ + "The variable's value cannot be changed.", + false + ], + [ + "The variable is shared across all instances of the class.", + true + ], + [ + "The variable can only be accessed within the main method.", + false + ] + ] + }, + { + "title": "LCK-IX", + "text": "Why is OOP (Object-Oriented Programming) considered beneficial for large software projects?", + "choices": [ + [ + "It eliminates the need for testing.", + false + ], + [ + "It promotes code modularity, making it easier to debug and scale.", + true + ], + [ + "It allows code to run without a Java Virtual Machine (JVM).", + false + ], + [ + "It converts all text into binary automatically.", + false + ] + ] + }, + { + "title": "LCK-X", + "text": "What is a key characteristic of a Constructor in Java?", + "choices": [ + [ + "It must have the exact same name as the class and no return type.", + true + ], + [ + "It is used to delete objects from memory.", + false + ], + [ + "It must be declared as void.", + false + ], + [ + "It is only called when a method is overloaded.", + false + ] + ] + }, + { + "title": "LCK-XI", + "text": "The this keyword is most commonly used to:", + "choices": [ + [ + "Call a method from a different class.", + false + ], + [ + "Distinguish between class attributes and parameters with the same name.", + true + ], + [ + "Access the private variables of a parent class.", + false + ], + [ + "Terminate a loop early.", + false + ] + ] + }, + { + "title": "LCK-XII", + "text": "Why would a developer use Generics, such as ArrayList?", + "choices": [ + [ + "To allow the list to store any type of data without restriction.", + false + ], + [ + "To ensure type safety by restricting the list to a specific type.", + true + ], + [ + "To make the code run on older versions of Java.", + false + ], + [ + "To automatically sort the data in the list.", + false + ] + ] + }, + { + "title": "LCK-XIII", + "text": "If a variable is marked as \"protected,\" which of the following groups is EXCLUDED from accessing it?", + "choices": [ + [ + "Any class that exists within the same package.", + false + ], + [ + "Any child class (subclass) that inherits from the parent class.", + false + ], + [ + "A completely unrelated class located in a different package.", + true + ], + [ + "The class in which the variable was originally defined.", + false + ] + ] + }, + { + "title": "LCK-XIV", + "text": "What is the most likely cause of a StackOverflowError in a Java application?", + "choices": [ + [ + "A recursive method that never reaches a base case.", + true + ], + [ + "Trying to store a very large string in a variable.", + false + ], + [ + "Running out of RAM on the computer.", + false + ], + [ + "A while loop that runs over thousand times.", + false + ] + ] + }, + { + "title": "LCK-XV", + "text": "Regarding the \"rules of inheritance,\" how do Interfaces and Abstract Classes differ in how they can be used by a single Java class?", + "choices": [ + [ + "A class can inherit from (extend) only one Abstract Class, but it can implement many different Interfaces.", + true + ], + [ + "A class can inherit from many Abstract Classes, but only one Interface.", + false + ], + [ + "A class must implement every Interface in its package, but Abstract Classes are optional.", + false + ], + [ + "There is no difference; Java treats \"extending\" and \"implementing\" as the exact same rule.", + false + ] + ] + }, + { + "title": "LCK-XVI", + "text": "Which statement correctly describes the use of throw?", + "choices": [ + [ + "It is used in a method signature to warn about possible errors.", + false + ], + [ + "It is used inside a method body to explicitly trigger a specific exception.", + true + ], + [ + "It is used to catch an exception after it happens.", + false + ], + [ + "It is used to prevent any exceptions from occurring.", + false + ] + ] + }, + { + "title": "LCK-XVII", + "text": "What is considered a \"bad practice\" when handling exceptions?", + "choices": [ + [ + "Using multiple catch blocks for different error types.", + false + ], + [ + "Using a finally block to close resources.", + false + ], + [ + "Catching an exception and leaving the catch block empty.", + true + ], + [ + "Throwing a custom exception.", + false + ] + ] + }, + { + "title": "LCK-XVIII", + "text": "What does the 'super' keyword do in Java?", + "choices": [ + [ + "It refers to the parent class and allows access to its methods and variables.", + true + ], + [ + "It creates a new instance of the current class.", + false + ], + [ + "It marks a method as final and prevents overriding.", + false + ], + [ + "It terminates the current method execution.", + false + ] + ] + }, + { + "title": "LCK-XIX", + "text": "Which access modifier allows access only within the same class?", + "choices": [ + [ + "public", + false + ], + [ + "protected", + false + ], + [ + "private", + true + ], + [ + "default", + false + ] + ] + }, + { + "title": "LCK-XX", + "text": "Which access modifier allows access within the same package and subclasses?", + "choices": [ + [ + "public", + false + ], + [ + "protected", + true + ], + [ + "private", + false + ], + [ + "default", + false + ] + ] + }, + { + "title": "LCK-XXI", + "text": "What is the default access level (package-private) in Java?", + "choices": [ + [ + "Accessible only within the same class", + false + ], + [ + "Accessible within the same package", + true + ], + [ + "Accessible from anywhere", + false + ], + [ + "Never accessible", + false + ] + ] + }, + { + "title": "LCK-XXII", + "text": "What access modifier allows access from anywhere in the application?", + "choices": [ + [ + "public", + true + ], + [ + "protected", + false + ], + [ + "private", + false + ], + [ + "default", + false + ] + ] + }, + { + "title": "LCK-XXIII", + "text": "What is the main purpose of the 'super()' call in a constructor?", + "choices": [ + [ + "To call the parent class's constructor.", + true + ], + [ + "To create a new instance of the current class.", + false + ], + [ + "To call a method from the current class.", + false + ], + [ + "To initialize static variables.", + false + ] + ] + }, + { + "title": "LCK-XXIV", + "text": "How can you explicitly call a parent class method from a child class?", + "choices": [ + [ + "Using the 'parent' keyword", + false + ], + [ + "Using the 'super' keyword", + true + ], + [ + "Using the 'extends' keyword", + false + ], + [ + "Using the 'this' keyword", + false + ] + ] + }, + { + "title": "LCK-XXV", + "text": "What does the 'new' keyword do in Java?", + "choices": [ + [ + "It declares a new variable.", + false + ], + [ + "It allocates memory for an object and calls its constructor.", + true + ], + [ + "It creates a new class.", + false + ], + [ + "It imports a new package.", + false + ] + ] + }, + { + "title": "LCK-XXVI", + "text": "What happens when you create an object using the 'new' keyword?", + "choices": [ + [ + "A variable is declared and memory is allocated on the stack", + false + ], + [ + "Memory is allocated on the heap and the constructor is called", + true + ], + [ + "A reference is created but no memory is allocated", + false + ], + [ + "The garbage collector is invoked", + false + ] + ] + }, + { + "title": "LCK-XXVII", + "text": "What does it mean for a method to be 'abstract'?", + "choices": [ + [ + "It contains no implementation and must be overridden in subclasses.", + true + ], + [ + "It cannot be called from other classes.", + false + ], + [ + "It has multiple implementations in the same class.", + false + ], + [ + "It is a method that is automatically generated.", + false + ] + ] + }, + { + "title": "LCK-XXVIII", + "text": "What can contain abstract methods in Java?", + "choices": [ + [ + "Only classes", + false + ], + [ + "Abstract classes and interfaces", + true + ], + [ + "Concrete classes and interfaces", + false + ], + [ + "Only regular methods", + false + ] + ] + }, + { + "title": "LCK-XXIX", + "text": "Can you instantiate an abstract class directly?", + "choices": [ + [ + "Yes, always", + false + ], + [ + "No, you must create a subclass that implements all abstract methods", + true + ], + [ + "Yes, but only with parameters", + false + ], + [ + "Only if it has a main method", + false + ] + ] + }, + { + "title": "LCK-XXX", + "text": "What does the 'interface' keyword define in Java?", + "choices": [ + [ + "A contract that classes must follow by implementing its methods.", + true + ], + [ + "A class with only abstract methods.", + false + ], + [ + "A way to inherit from multiple classes.", + false + ], + [ + "A package of related classes.", + false + ] + ] + }, + { + "title": "LCK-XXXI", + "text": "Can a class implement multiple interfaces in Java?", + "choices": [ + [ + "No, a class can implement only one interface", + false + ], + [ + "Yes, a class can implement multiple interfaces", + true + ], + [ + "Only if the interfaces are related", + false + ], + [ + "Only in Java 8 and later", + false + ] + ] + }, + { + "title": "LCK-XXXII", + "text": "What is the 'default' method in an interface used for?", + "choices": [ + [ + "To provide a default constructor.", + false + ], + [ + "To provide a default implementation of a method that implementing classes can override.", + true + ], + [ + "To define methods that must be implemented.", + false + ], + [ + "To create private methods in an interface.", + false + ] + ] + }, + { + "title": "LCK-XXXIII", + "text": "Which of the following is NOT a characteristic of an interface in Java?", + "choices": [ + [ + "It can declare abstract methods.", + false + ], + [ + "It can contain constructor implementations.", + true + ], + [ + "A class can implement multiple interfaces.", + false + ], + [ + "It can declare constants (static final variables).", + false + ] + ] + }, + { + "title": "LCK-XXXIV", + "text": "What is the difference between an abstract class and an interface?", + "choices": [ + [ + "They are identical in functionality.", + false + ], + [ + "A class can extend only one abstract class, but implement multiple interfaces.", + true + ], + [ + "Interfaces can have constructors; abstract classes cannot.", + false + ], + [ + "Abstract classes allow multiple inheritance; interfaces do not.", + false + ] + ] + }, + { + "title": "LCK-XXXV", + "text": "Can an interface extend another interface in Java?", + "choices": [ + [ + "No, interfaces cannot extend other interfaces", + false + ], + [ + "Yes, an interface can extend another interface", + true + ], + [ + "Only if they have the same methods", + false + ], + [ + "Only in Java 9 and later", + false + ] + ] + }, + { + "title": "LCK-XXXVI", + "text": "Which statement is true about the 'finally' block?", + "choices": [ + [ + "It is optional and executes only if an exception occurs.", + false + ], + [ + "It always executes, whether an exception occurs or not.", + true + ], + [ + "It must contain exception handling code.", + false + ], + [ + "It is executed before the try block.", + false + ] + ] + }, + { + "title": "LCK-XXXVII", + "text": "What is the correct order of exception handling in a try-catch-finally block?", + "choices": [ + [ + "finally executes first, then catch, then the rest of the code.", + false + ], + [ + "try executes first, then catch (if needed), then finally always executes.", + true + ], + [ + "catch executes first, then try, then finally.", + false + ], + [ + "finally executes first, then the rest depends on exceptions.", + false + ] + ] + }, + { + "title": "LCK-XXXVIII", + "text": "What is the difference between a checked and an unchecked exception?", + "choices": [ + [ + "Checked exceptions must be caught or declared; unchecked exceptions don't need to be.", + true + ], + [ + "Unchecked exceptions are more severe than checked exceptions.", + false + ], + [ + "Both require the same handling in code.", + false + ], + [ + "There is no difference between them.", + false + ] + ] + }, + { + "title": "LCK-XXXIX", + "text": "Which of the following is a checked exception?", + "choices": [ + [ + "NullPointerException", + false + ], + [ + "IOException", + true + ], + [ + "ArrayIndexOutOfBoundsException", + false + ], + [ + "ArithmeticException", + false + ] + ] + }, + { + "title": "LCK-XL", + "text": "What does the 'throws' keyword specify in a method signature?", + "choices": [ + [ + "The exceptions that the method may throw and not handle internally.", + true + ], + [ + "The exceptions that must be caught by the caller.", + false + ], + [ + "The exceptions that the method will definitely throw.", + false + ], + [ + "The same thing as the 'throw' keyword.", + false + ] + ] + }, + { + "title": "LCK-XLI", + "text": "What is a 'null pointer exception' in Java?", + "choices": [ + [ + "An exception thrown when accessing a method of a null object.", + true + ], + [ + "An exception thrown when declaring a variable.", + false + ], + [ + "An exception that occurs when a pointer is out of bounds.", + false + ], + [ + "An exception that prevents null values from being used.", + false + ] + ] + }, + { + "title": "LCK-XLII", + "text": "What is the main purpose of using 'try-with-resources' in Java?", + "choices": [ + [ + "To automatically allocate memory for objects.", + false + ], + [ + "To automatically close resources (like file streams) after use.", + true + ], + [ + "To prevent exceptions from being thrown.", + false + ], + [ + "To create multiple instances of the same resource.", + false + ] + ] + }, + { + "title": "LCK-XLIII", + "text": "What is the main purpose of the 'finally' block in exception handling?", + "choices": [ + [ + "To handle all types of exceptions.", + false + ], + [ + "To execute code that must run regardless of whether an exception occurred.", + true + ], + [ + "To prevent exceptions from being thrown.", + false + ], + [ + "To retry the code in the try block.", + false + ] + ] + }, + { + "title": "LCK-XLIV", + "text": "What is the purpose of the 'Collection' framework in Java?", + "choices": [ + [ + "To provide a unified way to store and manipulate groups of objects.", + true + ], + [ + "To replace arrays entirely.", + false + ], + [ + "To handle only primitive data types.", + false + ], + [ + "To manage file I/O operations.", + false + ] + ] + }, + { + "title": "LCK-XLV", + "text": "What is the difference between a List and a Set in Java?", + "choices": [ + [ + "A List allows duplicates and maintains order; a Set does not allow duplicates.", + true + ], + [ + "A Set allows duplicates; a List does not.", + false + ], + [ + "They are identical.", + false + ], + [ + "A List is faster than a Set.", + false + ] + ] + }, + { + "title": "LCK-XLVI", + "text": "What is the main difference between ArrayList and LinkedList in Java?", + "choices": [ + [ + "ArrayList is faster for access; LinkedList is faster for insertions/deletions.", + true + ], + [ + "LinkedList is faster for access than ArrayList.", + false + ], + [ + "They have identical performance characteristics.", + false + ], + [ + "ArrayList uses linked nodes; LinkedList uses arrays.", + false + ] + ] + }, + { + "title": "LCK-XLVII", + "text": "What is the primary difference between HashMap and Hashtable in Java?", + "choices": [ + [ + "HashMap is synchronized; Hashtable is not.", + false + ], + [ + "Hashtable is synchronized; HashMap is not.", + true + ], + [ + "They have the same functionality.", + false + ], + [ + "HashMap can store null keys; Hashtable cannot.", + false + ] + ] + }, + { + "title": "LCK-XLVIII", + "text": "What data structure does HashMap use internally?", + "choices": [ + [ + "Linked list", + false + ], + [ + "Array of buckets with hash function", + true + ], + [ + "Tree structure", + false + ], + [ + "Graph structure", + false + ] + ] + }, + { + "title": "LCK-XLIX", + "text": "Can HashMap store null keys and values?", + "choices": [ + [ + "No, neither keys nor values can be null", + false + ], + [ + "Yes, one null key and multiple null values are allowed", + true + ], + [ + "Only null values are allowed, not keys", + false + ], + [ + "Only null keys are allowed, not values", + false + ] + ] + }, + { + "title": "LCK-L", + "text": "What is the relationship between the 'Comparable' and 'Comparator' interfaces?", + "choices": [ + [ + "They are identical and can be used interchangeably.", + false + ], + [ + "'Comparable' defines a single natural ordering; 'Comparator' allows multiple custom orderings.", + true + ], + [ + "'Comparator' is deprecated in favor of 'Comparable'.", + false + ], + [ + "'Comparable' is used for primitive types; 'Comparator' is for objects.", + false + ] + ] + }, + { + "title": "LCK-LI", + "text": "What is the purpose of the 'Comparable' interface?", + "choices": [ + [ + "To define a way for objects to compare themselves to other objects.", + true + ], + [ + "To compare primitive data types.", + false + ], + [ + "To prevent comparison between objects.", + false + ], + [ + "To define constants in a class.", + false + ] + ] + }, + { + "title": "LCK-LII", + "text": "What method must be implemented by a class that implements Comparable?", + "choices": [ + [ + "compare()", + false + ], + [ + "compareTo()", + true + ], + [ + "equals()", + false + ], + [ + "sort()", + false + ] + ] + }, + { + "title": "LCK-LIII", + "text": "How many comparators can be used for sorting a collection?", + "choices": [ + [ + "Only one comparator per collection", + false + ], + [ + "Multiple custom comparators can be defined and used", + true + ], + [ + "Comparators cannot be used with collections", + false + ], + [ + "Only the default comparator can be used", + false + ] + ] + }, + { + "title": "LCK-LIV", + "text": "What is an 'enum' in Java?", + "choices": [ + [ + "A data type that can hold a fixed set of constant values.", + true + ], + [ + "A class with no methods.", + false + ], + [ + "A list of variables.", + false + ], + [ + "A way to create interfaces.", + false + ] + ] + }, + { + "title": "LCK-LV", + "text": "Can an enum implement an interface in Java?", + "choices": [ + [ + "No, enums cannot implement interfaces", + false + ], + [ + "Yes, an enum can implement one or more interfaces", + true + ], + [ + "Only if the interface has no methods", + false + ], + [ + "Only in Java 10 and later", + false + ] + ] + }, + { + "title": "LCK-LVI", + "text": "Can an enum have methods and variables?", + "choices": [ + [ + "No, enums can only contain constants", + false + ], + [ + "Yes, enums can have methods, variables, and constructors", + true + ], + [ + "Only methods are allowed, not variables", + false + ], + [ + "Only in Java 12 and later", + false + ] + ] + }, + { + "title": "LCK-LVII", + "text": "What is Generics in Java primarily used for?", + "choices": [ + [ + "To create classes without specific types", + false + ], + [ + "To provide compile-time type safety and eliminate casting", + true + ], + [ + "To allow unlimited type combinations", + false + ], + [ + "To replace inheritance in Java", + false + ] + ] + }, + { + "title": "LCK-LVIII", + "text": "What is the syntax for declaring a generic class in Java?", + "choices": [ + [ + "class MyClass { }", + false + ], + [ + "class MyClass { }", + true + ], + [ + "class MyClass(T) { }", + false + ], + [ + "class MyClass[T] { }", + false + ] + ] + }, + { + "title": "LCK-LIX", + "text": "What does the 'T' represent in a generic class like 'Box'?", + "choices": [ + [ + "A specific data type like String or Integer", + false + ], + [ + "A type parameter that can be replaced with any type", + true + ], + [ + "Always represents the type 'T'", + false + ], + [ + "A primitive type only", + false + ] + ] + }, + { + "title": "LCK-LX", + "text": "Can you use primitive types as type parameters in generics?", + "choices": [ + [ + "Yes, primitives work directly with generics", + false + ], + [ + "No, you must use wrapper classes like Integer, Double, etc.", + true + ], + [ + "Only for the Integer type", + false + ], + [ + "Only in Java 15 and later", + false + ] + ] + }, + { + "title": "LCK-LXI", + "text": "What is a bounded type parameter in Java generics?", + "choices": [ + [ + "A type parameter with no restrictions", + false + ], + [ + "A type parameter restricted to a specific type or its subtypes", + true + ], + [ + "A parameter that can only be String", + false + ], + [ + "A parameter that has a maximum size", + false + ] + ] + }, + { + "title": "LCK-LXII", + "text": "How do you create an instance of a generic class with a specific type?", + "choices": [ + [ + "Box box = new Box();", + false + ], + [ + "Box box = new Box();", + true + ], + [ + "Box box = new Box();", + false + ], + [ + "Box box = new Box();", + false + ] + ] + }, + { + "title": "LCK-LXIII", + "text": "What is the purpose of wildcard '?' in Java generics?", + "choices": [ + [ + "To represent any specific type", + false + ], + [ + "To allow flexibility when the specific type is unknown or irrelevant", + true + ], + [ + "To create a new generic type", + false + ], + [ + "To represent null types", + false + ] + ] + }, + { + "title": "LCK-LXIV", + "text": "What does List represent in Java?", + "choices": [ + [ + "A list of any type", + true + ], + [ + "A list of type 'Object' only", + false + ], + [ + "An empty list", + false + ], + [ + "A list of null values", + false + ] + ] + }, + { + "title": "LCK-LXV", + "text": "What is the difference between '? extends T' and '? super T' in generics?", + "choices": [ + [ + "'extends' restricts to T and its subclasses; 'super' restricts to T and its superclasses", + true + ], + [ + "They have the same functionality", + false + ], + [ + "'extends' is only for classes; 'super' is only for interfaces", + false + ], + [ + "'super' restricts to T only", + false + ] + ] + } +] \ No newline at end of file diff --git a/src/scripts/data/java/lockerroom/riddles.json b/src/scripts/data/java/lockerroom/riddles.json new file mode 100644 index 0000000..0f350d1 --- /dev/null +++ b/src/scripts/data/java/lockerroom/riddles.json @@ -0,0 +1,302 @@ +[ + { + "text": "A pointed peak with a belt across, I lead the alphabet without a loss. In this code, I take the lead, the very first step you'll need to read.", + "char": "A", + "index": 1, + "difficulty": "Easy" + }, + { + "text": "Two loops stacked upon a line, a buzzing insect shares my sign. I step into the second place, moving forward in this race.", + "char": "B", + "index": 2, + "difficulty": "Hard" + }, + { + "text": "A crescent moon facing the right, an ocean vast but out of sight. I sit right in the middle space, the third lock in this secret place.", + "char": "C", + "index": 3, + "difficulty": "Hard" + }, + { + "text": "A straight back with a rounded front, I start the day and lead the hunt. Penultimate is my domain, the fourth link in this sturdy chain.", + "char": "D", + "index": 4, + "difficulty": "Medium" + }, + { + "text": "Three teeth upon a vertical comb, I'm found at the end of every 'home'. I close this set, the final key, the fifth and last, unlocking thee.", + "char": "E", + "index": 5, + "difficulty": "Medium" + }, + { + "text": "A flag waving on a single pole, I am the spark that starts the 'fire'. I claim the very first position, starting off this secret mission.", + "char": "F", + "index": 1, + "difficulty": "Medium" + }, + { + "text": "An arrow spinning inward tight, the start of 'good' and end of 'dog'. I follow close behind the start, the second piece of this puzzle's heart.", + "char": "G", + "index": 2, + "difficulty": "Medium" + }, + { + "text": "Two tall walls and a bridge between, in 'heaven' and 'hell' I can be seen. I stand at number three, you see, the center of this mystery.", + "char": "H", + "index": 3, + "difficulty": "Easy" + }, + { + "text": "I am the ego, standing alone, a single pillar carved in stone. Number four is where I rest, one step away from finishing the test.", + "char": "I", + "index": 4, + "difficulty": "Hard" + }, + { + "text": "A fishhook waiting for a bite, I bring the 'joy' into the light. The fifth and final slot I claim, the ending of this guessing game.", + "char": "J", + "index": 5, + "difficulty": "Hard" + }, + { + "text": "A straight line with an open beak, I start the 'kite' that children seek. I am the first one in the queue, the starting point revealed to you.", + "char": "K", + "index": 1, + "difficulty": "Easy" + }, + { + "text": "A right angle sitting on the floor, the shape of a loser, but 'love's' true door. Second in line is where I fall, answering the puzzle's call.", + "char": "L", + "index": 2, + "difficulty": "Medium" + }, + { + "text": "Two mountain peaks that touch the sky, turned upside down, a 'W' am I. The third position is my throne, exactly in the middle zone.", + "char": "M", + "index": 3, + "difficulty": "Hard" + }, + { + "text": "A jagged peak, an endless 'no', I point the compass where to go. I take the fourth spot on the board, almost completing the final cord.", + "char": "N", + "index": 4, + "difficulty": "Easy" + }, + { + "text": "A perfect circle, an empty space, surprise is written on my face. The fifth and final number's mine, the last link in the line.", + "char": "O", + "index": 5, + "difficulty": "Medium" + }, + { + "text": "A head on a stick, looking to the right, a 'pirate's' start, prepared to fight. I am the vanguard, number one, the very place this code begun.", + "char": "P", + "index": 1, + "difficulty": "Medium" + }, + { + "text": "A circle with a tiny tail, without a 'U', I often fail. I hold the second spot in line, a quirky piece of this design.", + "char": "Q", + "index": 2, + "difficulty": "Medium" + }, + { + "text": "A pirate's favorite sound to make, a leg kicks out for goodness' sake! Dead center at the number three, the heart of this security.", + "char": "R", + "index": 3, + "difficulty": "Medium" + }, + { + "text": "A winding river, a snake's swift glide, I am the plural at the end of the ride. Position four is where I stand, the second-to-last in this command.", + "char": "S", + "index": 4, + "difficulty": "Hard" + }, + { + "text": "A simple cross, a balanced scale, I end the 'cat' and start the 'tale'. Number five is my decree, the final cipher is the key.", + "char": "T", + "index": 5, + "difficulty": "Easy" + }, + { + "text": "An open cup to catch the rain, I sound like you but have no brain. I am the first to take the stage, the opening letter on this page.", + "char": "U", + "index": 1, + "difficulty": "Easy" + }, + { + "text": "A plunging valley, steep and deep, the Roman numeral five I keep. But here I sit at number two, the second step to see you through.", + "char": "V", + "index": 2, + "difficulty": "Medium" + }, + { + "text": "Two valleys joined or double 'U', I ask 'what', 'where', and 'who'. Third in the sequence is my place, right in the middle of the race.", + "char": "W", + "index": 3, + "difficulty": "Medium" + }, + { + "text": "I mark the spot where treasures hide, a crossing path from side to side. Position four is my domain, near the end of this brain-drain.", + "char": "X", + "index": 4, + "difficulty": "Easy" + }, + { + "text": "A branching road, a question asked, the end of 'day', a simple task. I finish up at number five, the last to keep this code alive.", + "char": "Y", + "index": 5, + "difficulty": "Medium" + }, + { + "text": "A zigzag path, a sleepy sound, the final letter to be found. Yet here I break the natural rule, and stand first to test the fool.", + "char": "Z", + "index": 1, + "difficulty": "Hard" + }, + { + "text": "A triangle with a missing base, the start of the human alphabet race. But here I take the second seat, the next step on this puzzling street.", + "char": "A", + "index": 2, + "difficulty": "Easy" + }, + { + "text": "The most common letter you will see, a horizontal pitchfork facing free. I sit at three, the middle bound, where balance in the code is found.", + "char": "E", + "index": 3, + "difficulty": "Medium" + }, + { + "text": "The seeing orb without the eye, a straight line pointing to the sky. I wait at four, almost the end, a subtle clue for you, my friend.", + "char": "I", + "index": 4, + "difficulty": "Hard" + }, + { + "text": "A ring of gold, a hollow sphere, when you understand, you say 'Oh dear!'. The fifth position is my home, the final stop where you will roam.", + "char": "O", + "index": 5, + "difficulty": "Easy" + }, + { + "text": "A loop on top of a single pole, I pop and ping to play my role. I follow the leader, taking slot two, revealing the next hidden step to you.", + "char": "P", + "index": 2, + "difficulty": "Easy" + }, + { + "text": "A straight-backed guard with an arm and a kick, I start the 'knight' though the 'n' does the trick. I stand at the center, the vital third space, the balancing act in this numeric race.", + "char": "K", + "index": 3, + "difficulty": "Hard" + }, + { + "text": "A sharp right angle, a corner turned square, I am the start of the 'love' in the air. Fourth in the sequence, I patiently wait, just one step away from unlocking the gate.", + "char": "L", + "index": 4, + "difficulty": "Medium" + }, + { + "text": "A circle left open, a crescent of light, I start off the 'cat' prowling into the night. I am the fifth, the final decree, the last puzzle piece to set the lock free.", + "char": "C", + "index": 5, + "difficulty": "Easy" + }, + { + "text": "Like a comb with two teeth or a flag blowing free, I start off the 'future' for you and for me. I am the vanguard, the very first key, unlocking the start of this mystery.", + "char": "F", + "index": 1, + "difficulty": "Medium" + }, + { + "text": "A horseshoe facing the heavens above, I sound like the person you're speaking of. Second in line, I step up to the plate, forging ahead through the cryptographic gate.", + "char": "U", + "index": 2, + "difficulty": "Hard" + }, + { + "text": "A straight wooden bow with a string pulled tight, I bring the 'dawn' after the dark of the night. Dead in the center, at index number three, I hold the middle of this secret key.", + "char": "D", + "index": 3, + "difficulty": "Easy" + }, + { + "text": "An open loop that curls inward and stops, I start the 'gravity' before the apple drops. Almost the end, I take the fourth slot, tightening the loop on the password's knot.", + "char": "G", + "index": 4, + "difficulty": "Hard" + }, + { + "text": "Up, then diagonal, and straight up once more, I sit at the center of the word 'ignore'. The fifth and the final, the last of the line, complete the sequence and the prize is thine.", + "char": "N", + "index": 5, + "difficulty": "Medium" + }, + { + "text": "A loop on a stick with a leg kicking out, I roar and I rumble, I whisper and shout. I stand at the threshold, the very first space, kicking things off in this puzzling chase.", + "char": "R", + "index": 1, + "difficulty": "Easy" + }, + { + "text": "Two bubbles attached to a vertical spine, I am the start of the 'borderline'. Seated at three, the heart of the code, exactly halfway down this winding road.", + "char": "B", + "index": 3, + "difficulty": "Hard" + }, + { + "text": "Twin mountain summits, a valley between, in 'magic' and 'mystery' I'm often seen. I slide into second, continuing the quest, putting your cipher skills to the test.", + "char": "M", + "index": 2, + "difficulty": "Medium" + }, + { + "text": "A flat wooden roof on a pillar so tall, I start off the 'time' that will govern us all. Fourth in the lineup, I stand straight and true, preparing the final transition for you.", + "char": "T", + "index": 4, + "difficulty": "Easy" + }, + { + "text": "A downward plunge and a steep upward climb, the shape of a wedge cutting right through the rhyme. The fifth position is where I descend, marking the cipher's definitive end.", + "char": "V", + "index": 5, + "difficulty": "Hard" + }, + { + "text": "Twin valleys carved out by rivers of old, I spin the 'web' where the secrets unfold. I am the alpha, the number one slot, the starting thread of this intricate plot.", + "char": "W", + "index": 1, + "difficulty": "Medium" + }, + { + "text": "An umbrella handle turned upside down, a jester who juggles to entertain town. I swing into second, the follow-up act, keeping the passkey entirely intact.", + "char": "J", + "index": 2, + "difficulty": "Hard" + }, + { + "text": "A perfect round circle with a tiny kickstand, the 'queen' of the letters ruling the land. I rest in the middle, position number three, the balancing point of the master key.", + "char": "Q", + "index": 3, + "difficulty": "Easy" + }, + { + "text": "A slippery serpent that slithers around, a hissing 'silence' with barely a sound. Second-to-last is the spot that I claim, slot number four in this guessing game.", + "char": "S", + "index": 4, + "difficulty": "Medium" + }, + { + "text": "A fork in the road where you must make a choice, the roaring 'yell' of a powerful voice. The final position, the absolute end, slot number five is the message I send.", + "char": "Y", + "index": 5, + "difficulty": "Hard" + }, + { + "text": "Like goalposts erected upon the green field, I am the 'hero' with sword and with shield. I step up to one, the very first gate, the opening move of this puzzle's fate.", + "char": "H", + "index": 1, + "difficulty": "Easy" + } +] \ No newline at end of file diff --git a/src/scripts/data/java/restroom/__init__.py b/src/scripts/data/java/restroom/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/scripts/data/java/restroom/chunks.json b/src/scripts/data/java/restroom/chunks.json new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/src/scripts/data/java/restroom/chunks.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/src/scripts/data/java/restroom/problems.json b/src/scripts/data/java/restroom/problems.json new file mode 100644 index 0000000..e20f86f --- /dev/null +++ b/src/scripts/data/java/restroom/problems.json @@ -0,0 +1,110 @@ +[ + { + "title": "RST-001: System Logger Offline", + "description": "Error: System logger is offline. Manual log entry required to proceed.\nYou have two variables: level = \"WARNING\" event_id = \"1542\"\nYou must print() the log entry in the exact system format to be authenticated. Example Format: [WARNING] Status: 3842", + "difficulty": "Easy", + "category": "Strings", + "templates": { + "java": "import java.util.Scanner;\npublic class Solution {\n public static void main(String[] args) {\n String level;\n String event_id;\n Scanner sc = new Scanner(System.in);\n level = sc.nextLine();\n event_id = sc.nextLine();\n // Your code here\n }\n}" + }, + "test_cases": [ + { + "input": "WARNING\n1542", + "output": "[WARNING] Status: 1542", + "is_hidden": false + }, + { + "input": "ERROR\n9999", + "output": "[ERROR] Status: 9999", + "is_hidden": false + }, + { + "input": "INFO\n0001", + "output": "[INFO] Status: 0001", + "is_hidden": false + }, + { + "input": "CRITICAL\n7777", + "output": "[CRITICAL] Status: 7777", + "is_hidden": false + }, + { + "input": "DEBUG\n1234", + "output": "[DEBUG] Status: 1234", + "is_hidden": false + } + ] + }, + { + "title": "RST-002: Database Connection String Update", + "description": "// The database moved to a secure port, but our connection string stubbornly refuses to update.\nString dbUrl = \"jdbc:mysql://localhost:80/data\";\ndbUrl.replace(\"80\", \"443\");\nSystem.out.println(dbUrl);", + "difficulty": "Easy", + "category": "Strings", + "templates": { + "java": "import java.util.Scanner;\npublic class Solution {\n public static void main(String[] args) {\n String dbUrl = \"jdbc:mysql://localhost:80/data\";\n Scanner sc = new Scanner(System.in);\n // Your code here\n System.out.println(dbUrl);\n }\n}" + }, + "test_cases": [ + { + "input": "5432", + "output": "jdbc:mysql://localhost:5432/data", + "is_hidden": false + }, + { + "input": "3306", + "output": "jdbc:mysql://localhost:3306/data", + "is_hidden": false + }, + { + "input": "1521", + "output": "jdbc:mysql://localhost:1521/data", + "is_hidden": false + }, + { + "input": "27017", + "output": "jdbc:mysql://localhost:27017/data", + "is_hidden": false + }, + { + "input": "6379", + "output": "jdbc:mysql://localhost:6379/data", + "is_hidden": false + } + ] + }, + { + "title": "RST-003: Oxygen Scrubber Parity Check", + "description": "Error: Oxygen scrubber synchronization fault. Cycle parity check required to clear the fault.\nYou have one variable: int cycleCount;\nInstruction: Using the modulus operator (%), print a status message followed by a boolean evaluation of whether the cycle count is an even number.\nExample Format: Even Cycle Active: true", + "difficulty": "Easy", + "category": "Operators", + "templates": { + "java": "import java.util.Scanner;\npublic class Solution {\n public static void main(String[] args) {\n Scanner sc = new Scanner(System.in);\n int cycleCount = sc.nextInt();\n // Your code here\n }\n}" + }, + "test_cases": [ + { + "input": "87", + "output": "Even Cycle Active: false", + "is_hidden": false + }, + { + "input": "100", + "output": "Even Cycle Active: true", + "is_hidden": false + }, + { + "input": "42", + "output": "Even Cycle Active: true", + "is_hidden": false + }, + { + "input": "15", + "output": "Even Cycle Active: false", + "is_hidden": false + }, + { + "input": "0", + "output": "Even Cycle Active: true", + "is_hidden": false + } + ] + } +] \ No newline at end of file diff --git a/src/scripts/data/java/restroom/questions.json b/src/scripts/data/java/restroom/questions.json new file mode 100644 index 0000000..a452767 --- /dev/null +++ b/src/scripts/data/java/restroom/questions.json @@ -0,0 +1,376 @@ +[ + { + "title": "RST-I", + "text": "Which option best describes the OOP principle of Encapsulation in Java?", + "choices": [ + [ + "Inheritance of properties from a parent class to a child class", + false + ], + [ + "Hiding internal class details and allowing access only through defined methods", + true + ], + [ + "Ability of a class to take on many forms through method overloading", + false + ], + [ + "Creating multiple objects from a single class ", + false + ] + ] + }, + { + "title": "RST-II", + "text": "Which option best describes the principle of Inheritance in Java? ", + "choices": [ + [ + "Hiding internal class details and allowing access only through defined methods", + false + ], + [ + "Ability of a class to take on many forms through method overloading", + false + ], + [ + "Creating multiple objects from a single class", + false + ], + [ + "A child class inheriting properties from a parent class", + true + ] + ] + }, + { + "title": "RST-III", + "text": "Which option best describes the principle of Polymorphism in Java? ", + "choices": [ + [ + "Hiding internal class details and allowing access only through defined methods", + false + ], + [ + "Ability of a class to take on many forms through method overloading", + true + ], + [ + "Creating multiple objects from a single class", + false + ], + [ + "A child class inheriting properties from a parent class", + false + ] + ] + }, + { + "title": "RST-IV", + "text": "Which option best describes the principle of Abstraction in Java? ", + "choices": [ + [ + "Showing only necessary details and hiding unimportant ones\u00a0", + true + ], + [ + "Creating a large number of objects ", + false + ], + [ + "Always using public variables", + false + ], + [ + "Inheriting through multiple layers of classes", + false + ] + ] + }, + { + "title": "RST-V", + "text": "Which of the following best describes a Class in Java? ", + "choices": [ + [ + "A real-world object in memory", + false + ], + [ + "A blueprint for creating objects", + true + ], + [ + "A type of loop structure", + false + ], + [ + "A method inside an object", + false + ] + ] + }, + { + "title": "RST-VI", + "text": "Which best describes Method Overloading? ", + "choices": [ + [ + "A subclass replacing a parent method", + false + ], + [ + "Multiple methods with the same name but different parameters", + true + ], + [ + "A method that runs only once", + false + ], + [ + "A method that cannot be changed", + false + ] + ] + }, + { + "title": "RST-VII", + "text": "Which best describes Method Overriding? ", + "choices": [ + [ + "Changing the name of a method", + false + ], + [ + "A child class writing a new method to replace the parent class's method", + true + ], + [ + "Combining multiple methods into one", + false + ], + [ + "Deleting a method from a class", + false + ] + ] + }, + { + "title": "RST-VIII", + "text": "Which best describes the static keyword in a java object? ", + "choices": [ + [ + "Belongs to object", + false + ], + [ + "Belongs to class", + true + ], + [ + "Used only in constructors", + false + ], + [ + "Deleted after compilation", + false + ] + ] + }, + { + "title": "RST-IX", + "text": "What is the main benefit of using Java Programming for OOP? ", + "choices": [ + [ + "Makes programs faster in every case", + false + ], + [ + "Makes code organized, easy to maintain, and reusable", + true + ], + [ + "No need to use variables", + false + ], + [ + "Replaces everything with loops", + false + ] + ] + }, + { + "title": "RST-X", + "text": "Which of the following best describes a Constructor in Java? ", + "choices": [ + [ + "A special method that is automatically called when an object is created.", + true + ], + [ + "A method that must return an integer.", + false + ], + [ + "A method that can only be called manually.", + false + ], + [ + "A method that always prints output.", + false + ] + ] + }, + { + "title": "RST-XI", + "text": "Which best describes the \u201cthis\u201d keyword in Java class? ", + "choices": [ + [ + "A reference to the current object.", + true + ], + [ + "A reference to the parent class.", + false + ], + [ + "A reference to the main method.", + false + ], + [ + "A reference to all objects.", + false + ] + ] + }, + { + "title": "RST-XII", + "text": "What is a \"Generic\" in Java (e.g., List) used for? ", + "choices": [ + [ + "To speed up compilation.", + false + ], + [ + "To allow methods to return multiple values.", + false + ], + [ + "To enable stronger type checks at compile time and eliminate casting.", + true + ], + [ + "To create dynamic arrays.", + false + ] + ] + }, + { + "title": "RST-XIII", + "text": "Which of the following correctly describes the \"protected\" access modifier in Java? ", + "choices": [ + [ + "Accessible only within the same class.", + false + ], + [ + "Accessible only within the same package.", + false + ], + [ + "Accessible within the same package and by subclasses in other packages.", + true + ], + [ + "Accessible from any class in any package.", + false + ] + ] + }, + { + "title": "RST-XIV", + "text": "Which scenario causes a StackOverflowError? ", + "choices": [ + [ + "Creating too many objects until the Heap is full.", + false + ], + [ + "Deep or infinite recursion where method calls exceed the stack memory limit.", + true + ], + [ + "Accessing an array index that does not exist.", + false + ], + [ + "Dividing an integer by zero.", + false + ] + ] + }, + { + "title": "RST-XV", + "text": "Which of the following is a key difference between an Interface and an Abstract Class? ", + "choices": [ + [ + "An interface can have constructors, while an abstract class cannot.", + false + ], + [ + "A class can extend multiple abstract classes, but only implement one interface.", + false + ], + [ + "An interface defines what to do, An abstract class can provide a partial implementation.", + true + ], + [ + "Abstract classes only allow public methods, while interfaces allow private methods.", + false + ] + ] + }, + { + "title": "RST-XVI", + "text": "What is the difference between throw and throws? ", + "choices": [ + [ + "throw declares an exception; throws creates an exception.", + false + ], + [ + "throw creates an exception; throws declares an exception.", + true + ], + [ + "throw is for checked errors; throws is for unchecked errors.", + false + ], + [ + "throw handles the error; throws ignores the error.", + false + ] + ] + }, + { + "title": "RST-XVII", + "text": "What happens when you catch an exception but leave the block empty? ", + "choices": [ + [ + "The program crashes immediately with an error.", + false + ], + [ + "The exception is ignored and the program continues.", + true + ], + [ + "The compiler will refuse to compile the code.", + false + ], + [ + "The exception is automatically printed to the console.", + false + ] + ] + } +] \ No newline at end of file diff --git a/src/scripts/data/java/restroom/riddles.json b/src/scripts/data/java/restroom/riddles.json new file mode 100644 index 0000000..6b6708f --- /dev/null +++ b/src/scripts/data/java/restroom/riddles.json @@ -0,0 +1,302 @@ +[ + { + "text": "A mountain peak crossed by a trail, the starting breath of every tale. I sit exactly in the middle space, claiming the third and central place.", + "char": "A", + "index": 3, + "difficulty": "Easy" + }, + { + "text": "The right wing of a butterfly, a buzzing sound as I fly by. I take the fourth step in the quest, just one more left to beat the test.", + "char": "B", + "index": 4, + "difficulty": "Medium" + }, + { + "text": "A silver sickle in the sky, a crescent moon that catches the eye. The final piece of the design, the fifth and closing of the line.", + "char": "C", + "index": 5, + "difficulty": "Hard" + }, + { + "text": "A hunter\u2019s bow with a tautened string, the start of \u2018dawn\u2019 and end of \u2018king\u2019. I am the first, the opening door, with four more secrets to explore.", + "char": "D", + "index": 1, + "difficulty": "Easy" + }, + { + "text": "A heavy rake with just three tines, the most used letter in these lines. I step into the second slot, continuing the secret plot.", + "char": "E", + "index": 2, + "difficulty": "Medium" + }, + { + "text": "A weather vane with arrows blown, the start of every \u2018fault\u2019 that's known. I am the third, the middle ground, where perfect symmetry is found.", + "char": "F", + "index": 3, + "difficulty": "Hard" + }, + { + "text": "An open circle turning in, where \u2018game\u2019 and \u2018glory\u2019 both begin. Penultimate is my domain, the fourth link in this sturdy chain.", + "char": "G", + "index": 4, + "difficulty": "Easy" + }, + { + "text": "A ladder missing all but one, the breathless sigh when work is done. The fifth and final lock I keep, the end of the puzzle, dark and deep.", + "char": "H", + "index": 5, + "difficulty": "Medium" + }, + { + "text": "A single needle standing tall, the Roman one, the start of all. I am the pioneer today, the number one who leads the way.", + "char": "I", + "index": 1, + "difficulty": "Hard" + }, + { + "text": "A candy cane flipped upside down, the joyful \u2018jester\u2019 of the town. I follow close behind the lead, the second cipher that you need.", + "char": "J", + "index": 2, + "difficulty": "Easy" + }, + { + "text": "A snapping branch against a tree, the start of every \u2018knight\u2019 you see. Dead center at the number three, the heart of this security.", + "char": "K", + "index": 3, + "difficulty": "Medium" + }, + { + "text": "A corner square, a perfect right, the heavy \u2018lead\u2019 in darkest night. I take the fourth spot on the board, almost completing the final cord.", + "char": "L", + "index": 4, + "difficulty": "Hard" + }, + { + "text": "Twin mountain peaks that touch the sun, a \u2018million\u2019 miles until we\u2019re done. I close the book, the fifth decree, the final cipher is the key.", + "char": "M", + "index": 5, + "difficulty": "Easy" + }, + { + "text": "A lightning bolt that strikes the ground, a stubborn \u2018no\u2019 without a sound. I claim the very first position, starting off this secret mission.", + "char": "N", + "index": 1, + "difficulty": "Medium" + }, + { + "text": "A golden ring without a stone, an empty void left all alone. Second in line is where I fall, answering the puzzle's call.", + "char": "O", + "index": 2, + "difficulty": "Hard" + }, + { + "text": "A butterfly with just one wing, a popping \u2018penny\u2019 for the king. I stand at number three, you see, the center of this mystery.", + "char": "P", + "index": 3, + "difficulty": "Easy" + }, + { + "text": "A magnifying glass held near, to make the \u2018question\u2019 crystal clear. The fourth position I demand, the second-to-last in this command.", + "char": "Q", + "index": 4, + "difficulty": "Medium" + }, + { + "text": "A standing guard who kicks a knee, the roaring sound of the angry sea. Number five is my decree, the final cipher is the key.", + "char": "R", + "index": 5, + "difficulty": "Hard" + }, + { + "text": "A swan\u2019s long neck, a winding stream, the start of every \u2018silent\u2019 dream. I lead the alphabet's new race, taking the very first place.", + "char": "S", + "index": 1, + "difficulty": "Easy" + }, + { + "text": "A hammer poised to strike a nail, the ending of the \u2018cat\u2019 and \u2018tale\u2019. I step into the second place, moving forward in this race.", + "char": "T", + "index": 2, + "difficulty": "Medium" + }, + { + "text": "An empty bowl awaiting soup, an open, upward-facing loop. The third position is my throne, exactly in the middle zone.", + "char": "U", + "index": 3, + "difficulty": "Hard" + }, + { + "text": "A flock of birds in distant flight, a plunging valley out of sight. I take the fourth slot in your quest, just one more left to beat the test.", + "char": "V", + "index": 4, + "difficulty": "Easy" + }, + { + "text": "A jagged wave upon the sea, a double curve of mystery. The fifth and final slot I claim, the ending of this guessing game.", + "char": "W", + "index": 5, + "difficulty": "Medium" + }, + { + "text": "Two clashing swords that meet in strife, the unknown variable in life. I am the vanguard, number one, the very place this code begun.", + "char": "X", + "index": 1, + "difficulty": "Hard" + }, + { + "text": "A slingshot drawn to fire a stone, the ending of the \u2018day\u2019 alone. I hold the second spot in line, a quirky piece of this design.", + "char": "Y", + "index": 2, + "difficulty": "Easy" + }, + { + "text": "The zigzag mark a swordsman leaves, the sleepy sound the dreamer weaves. Dead center at the number three, the heart of this security.", + "char": "Z", + "index": 3, + "difficulty": "Medium" + }, + { + "text": "The pointed nose of a rocket ship, the start of the \u2018apple\u2019 you can grip. Position four is where I stand, the second-to-last in this command.", + "char": "A", + "index": 4, + "difficulty": "Hard" + }, + { + "text": "A pair of glasses turned on end, a \u2018brave\u2019 and bold, courageous friend. I finish up at number five, the last to keep this code alive.", + "char": "B", + "index": 5, + "difficulty": "Easy" + }, + { + "text": "A bitten cookie, curved and sweet, a \u2018clever\u2019 cat upon the street. I start the sequence, fresh and new, the first clue given unto you.", + "char": "C", + "index": 1, + "difficulty": "Medium" + }, + { + "text": "A half-moon resting on a wall, the \u2018dark\u2019 that falls upon us all. But here I sit at number two, the second step to see you through.", + "char": "D", + "index": 2, + "difficulty": "Hard" + }, + { + "text": "A comb designed for giant's hair, an \u2018echo\u2019 fading in the air. I rest in the middle, position three, the balancing point of the master key.", + "char": "E", + "index": 3, + "difficulty": "Easy" + }, + { + "text": "A wooden gibbet standing tall, a \u2018feather\u2019 drifting to the fall. Fourth in the sequence, I patiently wait, just one step away from unlocking the gate.", + "char": "F", + "index": 4, + "difficulty": "Medium" + }, + { + "text": "A curving snake that bites its tail, a \u2018ghost\u2019 that wanders, cold and pale. I am the fifth, the final decree, the last puzzle piece to set the lock free.", + "char": "G", + "index": 5, + "difficulty": "Hard" + }, + { + "text": "Two columns holding up the sky, the \u2018heavy\u2019 heave, the weary sigh. I am the first to take the stage, the opening letter on this page.", + "char": "H", + "index": 1, + "difficulty": "Easy" + }, + { + "text": "An icicle hanging straight and true, an \u2018island\u2019 in the ocean blue. Second in line, I step up to the plate, forging ahead through the cryptographic gate.", + "char": "I", + "index": 2, + "difficulty": "Medium" + }, + { + "text": "A scythe to reap the golden wheat, a \u2018jungle\u2019 filled with humid heat. Dead in the center, at index number three, I hold the middle of this secret key.", + "char": "J", + "index": 3, + "difficulty": "Hard" + }, + { + "text": "A bird\u2019s beak opening to sing, a \u2018kite\u2019 that flies upon the string. Almost the end, I take the fourth slot, tightening the loop on the password's knot.", + "char": "K", + "index": 4, + "difficulty": "Easy" + }, + { + "text": "A heavy boot without a toe, the \u2018light\u2019 that helps the garden grow. The fifth and the final, the last of the line, complete the sequence and the prize is thine.", + "char": "L", + "index": 5, + "difficulty": "Medium" + }, + { + "text": "The steady hum of a busy hive, a \u2018mountain\u2019 where the eagles thrive. I stand at the threshold, the very first space, kicking things off in this puzzling chase.", + "char": "M", + "index": 1, + "difficulty": "Hard" + }, + { + "text": "A rigid seesaw locked in place, the \u2018night\u2019 that covers up the space. I follow the leader, taking slot two, revealing the next hidden step to you.", + "char": "N", + "index": 2, + "difficulty": "Easy" + }, + { + "text": "The quiet eye of a raging storm, an \u2018open\u2019 door to keep you warm. Seated at three, the heart of the code, exactly halfway down this winding road.", + "char": "O", + "index": 3, + "difficulty": "Medium" + }, + { + "text": "A keyhole's upper, rounded half, a \u2018playful\u2019 joke to make you laugh. Fourth in the lineup, I stand straight and true, preparing the final transition for you.", + "char": "P", + "index": 4, + "difficulty": "Hard" + }, + { + "text": "A rolling coin that slips away, a \u2018quiet\u2019 moment in the day. The fifth position is where I descend, marking the cipher's definitive end.", + "char": "Q", + "index": 5, + "difficulty": "Easy" + }, + { + "text": "A sailor's mast with a rolled-up sail, a \u2018roaring\u2019 lion on the trail. I am the alpha, the number one slot, the starting thread of this intricate plot.", + "char": "R", + "index": 1, + "difficulty": "Medium" + }, + { + "text": "A hook that hangs upon the door, the \u2018sand\u2019 that washes on the shore. I swing into second, the follow-up act, keeping the passkey entirely intact.", + "char": "S", + "index": 2, + "difficulty": "Hard" + }, + { + "text": "A balanced scale of justice blind, the \u2018truth\u2019 that you must seek and find. I sit at three, the middle bound, where balance in the code is found.", + "char": "T", + "index": 3, + "difficulty": "Easy" + }, + { + "text": "A gentle smile without a face, an \u2018under\u2019 world beneath this place. Second-to-last is the spot that I claim, slot number four in this guessing game.", + "char": "U", + "index": 4, + "difficulty": "Medium" + }, + { + "text": "A teardrop falling from the sky, a \u2018valley\u2019 where the shadows lie. The final position, the absolute end, slot number five is the message I send.", + "char": "V", + "index": 5, + "difficulty": "Hard" + }, + { + "text": "Two deep ravines beside a hill, a \u2018whisper\u2019 when the wind is still. I step up to one, the very first gate, the opening move of this puzzle's fate.", + "char": "W", + "index": 1, + "difficulty": "Easy" + }, + { + "text": "A windmill's blades that catch the breeze, the \u2018xylophone\u2019 that plays with ease. I slide into second, continuing the quest, putting your cipher skills to the test.", + "char": "X", + "index": 2, + "difficulty": "Medium" + } +] \ No newline at end of file diff --git a/src/scripts/data/java/temp/problems.json b/src/scripts/data/java/temp/problems.json new file mode 100644 index 0000000..411d6b3 --- /dev/null +++ b/src/scripts/data/java/temp/problems.json @@ -0,0 +1,682 @@ +[ + { + "title": "Reverse a String", + "description": "Reverse a given string.", + "difficulty": "Easy", + "category": "Strings", + "templates": { + "java": "public class Solution {\n public String reverseString(String s) {\n // Your code here\n return \"\";\n }\n}", + "python": "def solve():\n # Implement Reverse a String\n pass" + }, + "test_cases": [ + { + "input": "abc", + "output": "cba", + "is_hidden": false + } + ] + }, + { + "title": "Is Palindrome", + "description": "Check if a string is a palindrome.", + "difficulty": "Easy", + "category": "Strings", + "templates": { + "java": "public class Solution {\n public boolean isPalindrome(String s) {\n // Your code here\n return false;\n }\n}", + "python": "def solve():\n # Implement Is Palindrome\n pass" + }, + "test_cases": [ + { + "input": "aba", + "output": "true", + "is_hidden": false + } + ] + }, + { + "title": "Factorial", + "description": "Calculates factorial of n.", + "difficulty": "Easy", + "category": "Math", + "templates": { + "java": "public class Solution {\n public long factorial(int n) {\n // Your code here\n return 0;\n }\n}", + "python": "def solve():\n # Implement Factorial\n pass" + }, + "test_cases": [ + { + "input": "5", + "output": "120", + "is_hidden": false + } + ] + }, + { + "title": "Fibonacci", + "description": "Find nth fibonacci number.", + "difficulty": "Medium", + "category": "Math", + "templates": { + "java": "public class Solution {\n public int fibonacci(int n) {\n // Your code here\n return 0;\n }\n}", + "python": "def solve():\n # Implement Fibonacci\n pass" + }, + "test_cases": [ + { + "input": "10", + "output": "55", + "is_hidden": false + } + ] + }, + { + "title": "Prime Number", + "description": "Check if number is prime.", + "difficulty": "Easy", + "category": "Math", + "templates": { + "java": "public class Solution {\n public boolean isPrime(int n) {\n // Your code here\n return false;\n }\n}", + "python": "def solve():\n # Implement Prime Number\n pass" + }, + "test_cases": [ + { + "input": "7", + "output": "true", + "is_hidden": false + } + ] + }, + { + "title": "Largest in Array", + "description": "Find the largest element in an array.", + "difficulty": "Easy", + "category": "Arrays", + "templates": { + "java": "public class Solution {\n public int findLargest(int[] arr) {\n // Your code here\n return 0;\n }\n}", + "python": "def solve():\n # Implement Largest in Array\n pass" + }, + "test_cases": [ + { + "input": "[1,2,3]", + "output": "3", + "is_hidden": false + } + ] + }, + { + "title": "Sum of Array", + "description": "Find the sum of all elements in an array.", + "difficulty": "Easy", + "category": "Arrays", + "templates": { + "java": "public class Solution {\n public int sumArray(int[] arr) {\n // Your code here\n return 0;\n }\n}", + "python": "def solve():\n # Implement Sum of Array\n pass" + }, + "test_cases": [ + { + "input": "[1,2,3]", + "output": "6", + "is_hidden": false + } + ] + }, + { + "title": "Bubble Sort", + "description": "Sort an array using bubble sort.", + "difficulty": "Easy", + "category": "Sorting", + "templates": { + "java": "public class Solution {\n public int[] bubbleSort(int[] arr) {\n // Your code here\n return arr;\n }\n}", + "python": "def solve():\n # Implement Bubble Sort\n pass" + }, + "test_cases": [ + { + "input": "[3,2,1]", + "output": "[1,2,3]", + "is_hidden": false + } + ] + }, + { + "title": "Linear Search", + "description": "Find index of element in array.", + "difficulty": "Easy", + "category": "Search", + "templates": { + "java": "public class Solution {\n public int linearSearch(int[] arr, int target) {\n // Your code here\n return -1;\n }\n}", + "python": "def solve():\n # Implement Linear Search\n pass" + }, + "test_cases": [ + { + "input": "[1,2,3], 2", + "output": "1", + "is_hidden": false + } + ] + }, + { + "title": "Binary Search", + "description": "Find index using binary search.", + "difficulty": "Medium", + "category": "Search", + "templates": { + "java": "public class Solution {\n public int binarySearch(int[] arr, int target) {\n // Your code here\n return -1;\n }\n}", + "python": "def solve():\n # Implement Binary Search\n pass" + }, + "test_cases": [ + { + "input": "[1,2,3], 2", + "output": "1", + "is_hidden": false + } + ] + }, + { + "title": "Anagram Check", + "description": "Check if two strings are anagrams.", + "difficulty": "Medium", + "category": "Strings", + "templates": { + "java": "public class Solution {\n public boolean isAnagram(String s1, String s2) {\n // Your code here\n return false;\n }\n}", + "python": "def solve():\n # Implement Anagram Check\n pass" + }, + "test_cases": [ + { + "input": "listen, silent", + "output": "true", + "is_hidden": false + } + ] + }, + { + "title": "Count Vowels", + "description": "Count vowels in a string.", + "difficulty": "Easy", + "category": "Strings", + "templates": { + "java": "public class Solution {\n public int countVowels(String s) {\n // Your code here\n return 0;\n }\n}", + "python": "def solve():\n # Implement Count Vowels\n pass" + }, + "test_cases": [ + { + "input": "hello", + "output": "2", + "is_hidden": false + } + ] + }, + { + "title": "Armstrong Number", + "description": "Check if number is Armstrong.", + "difficulty": "Easy", + "category": "Math", + "templates": { + "java": "public class Solution {\n public boolean isArmstrong(int n) {\n // Your code here\n return false;\n }\n}", + "python": "def solve():\n # Implement Armstrong Number\n pass" + }, + "test_cases": [ + { + "input": "153", + "output": "true", + "is_hidden": false + } + ] + }, + { + "title": "Perfect Number", + "description": "Check if number is perfect.", + "difficulty": "Easy", + "category": "Math", + "templates": { + "java": "public class Solution {\n public boolean isPerfect(int n) {\n // Your code here\n return false;\n }\n}", + "python": "def solve():\n # Implement Perfect Number\n pass" + }, + "test_cases": [ + { + "input": "6", + "output": "true", + "is_hidden": false + } + ] + }, + { + "title": "Matrix Addition", + "description": "Add two matrices.", + "difficulty": "Medium", + "category": "Matrix", + "templates": { + "java": "public class Solution {\n public int[][] addMatrices(int[][] a, int[][] b) {\n // Your code here\n return null;\n }\n}", + "python": "def solve():\n # Implement Matrix Addition\n pass" + }, + "test_cases": [ + { + "input": "[[1,1],[1,1]], [[1,1],[1,1]]", + "output": "[[2,2],[2,2]]", + "is_hidden": false + } + ] + }, + { + "title": "Transpose Matrix", + "description": "Transpose a matrix.", + "difficulty": "Medium", + "category": "Matrix", + "templates": { + "java": "public class Solution {\n public int[][] transpose(int[][] matrix) {\n // Your code here\n return null;\n }\n}", + "python": "def solve():\n # Implement Transpose Matrix\n pass" + }, + "test_cases": [ + { + "input": "[[1,2],[3,4]]", + "output": "[[1,3],[2,4]]", + "is_hidden": false + } + ] + }, + { + "title": "GCD of Two Numbers", + "description": "Find GCD.", + "difficulty": "Easy", + "category": "Math", + "templates": { + "java": "public class Solution {\n public int gcd(int a, int b) {\n // Your code here\n return 1;\n }\n}", + "python": "def solve():\n # Implement GCD of Two Numbers\n pass" + }, + "test_cases": [ + { + "input": "12, 18", + "output": "6", + "is_hidden": false + } + ] + }, + { + "title": "LCM of Two Numbers", + "description": "Find LCM.", + "difficulty": "Easy", + "category": "Math", + "templates": { + "java": "public class Solution {\n public int lcm(int a, int b) {\n // Your code here\n return 1;\n }\n}", + "python": "def solve():\n # Implement LCM of Two Numbers\n pass" + }, + "test_cases": [ + { + "input": "12, 18", + "output": "36", + "is_hidden": false + } + ] + }, + { + "title": "Remove Whitespace", + "description": "Remove all whitespace from string.", + "difficulty": "Easy", + "category": "Strings", + "templates": { + "java": "public class Solution {\n public String removeWhitespace(String s) {\n // Your code here\n return \"\";\n }\n}", + "python": "def solve():\n # Implement Remove Whitespace\n pass" + }, + "test_cases": [ + { + "input": "a b c", + "output": "abc", + "is_hidden": false + } + ] + }, + { + "title": "Max Occurrence Char", + "description": "Find char with max occurrence.", + "difficulty": "Medium", + "category": "Strings", + "templates": { + "java": "public class Solution {\n public char maxOccurringChar(String s) {\n // Your code here\n return ' ';\n }\n}", + "python": "def solve():\n # Implement Max Occurrence Char\n pass" + }, + "test_cases": [ + { + "input": "test", + "output": "t", + "is_hidden": false + } + ] + }, + { + "title": "Array to Set", + "description": "Convert array to set.", + "difficulty": "Easy", + "category": "Collections", + "templates": { + "java": "import java.util.*;\npublic class Solution {\n public Set arrayToSet(int[] arr) {\n // Your code here\n return null;\n }\n}", + "python": "def solve():\n # Implement Array to Set\n pass" + }, + "test_cases": [ + { + "input": "[1,2,2]", + "output": "[1,2]", + "is_hidden": false + } + ] + }, + { + "title": "LinkedList Reverse", + "description": "Reverse a linked list.", + "difficulty": "Hard", + "category": "Data Structures", + "templates": { + "java": "public class Solution {\n public ListNode reverseList(ListNode head) {\n // Your code here\n return null;\n }\n}", + "python": "def solve():\n # Implement LinkedList Reverse\n pass" + }, + "test_cases": [ + { + "input": "[1,2,3]", + "output": "[3,2,1]", + "is_hidden": false + } + ] + }, + { + "title": "Valid Parentheses", + "description": "Check if parentheses are valid.", + "difficulty": "Medium", + "category": "Strings", + "templates": { + "java": "public class Solution {\n public boolean isValid(String s) {\n // Your code here\n return false;\n }\n}", + "python": "def solve():\n # Implement Valid Parentheses\n pass" + }, + "test_cases": [ + { + "input": "()[]{}", + "output": "true", + "is_hidden": false + } + ] + }, + { + "title": "Merge Sorted Arrays", + "description": "Merge two sorted arrays.", + "difficulty": "Medium", + "category": "Arrays", + "templates": { + "java": "public class Solution {\n public int[] merge(int[] nums1, int[] nums2) {\n // Your code here\n return null;\n }\n}", + "python": "def solve():\n # Implement Merge Sorted Arrays\n pass" + }, + "test_cases": [ + { + "input": "[1,3,5], [2,4,6]", + "output": "[1,2,3,4,5,6]", + "is_hidden": false + } + ] + }, + { + "title": "Binary Tree Inorder", + "description": "Inorder traversal of binary tree.", + "difficulty": "Medium", + "category": "Data Structures", + "templates": { + "java": "import java.util.*;\npublic class Solution {\n public List inorderTraversal(TreeNode root) {\n // Your code here\n return null;\n }\n}", + "python": "def solve():\n # Implement Binary Tree Inorder\n pass" + }, + "test_cases": [ + { + "input": "[1,null,2,3]", + "output": "[1,3,2]", + "is_hidden": false + } + ] + }, + { + "title": "Pascal's Triangle", + "description": "Generate Pascal's Triangle.", + "difficulty": "Medium", + "category": "Math", + "templates": { + "java": "import java.util.*;\npublic class Solution {\n public List> generate(int numRows) {\n // Your code here\n return null;\n }\n}", + "python": "def solve():\n # Implement Pascal's Triangle\n pass" + }, + "test_cases": [ + { + "input": "5", + "output": "[[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]", + "is_hidden": false + } + ] + }, + { + "title": "Two Sum Problem", + "description": "Find indices that sum to target.", + "difficulty": "Easy", + "category": "Arrays", + "templates": { + "java": "public class Solution {\n public int[] twoSum(int[] nums, int target) {\n // Your code here\n return null;\n }\n}", + "python": "def solve():\n # Implement Two Sum Problem\n pass" + }, + "test_cases": [ + { + "input": "[2,7,11,15], 9", + "output": "[0,1]", + "is_hidden": false + } + ] + }, + { + "title": "Longest Substring", + "description": "Longest substring without repeating chars.", + "difficulty": "Medium", + "category": "Strings", + "templates": { + "java": "public class Solution {\n public int lengthOfLongestSubstring(String s) {\n // Your code here\n return 0;\n }\n}", + "python": "def solve():\n # Implement Longest Substring\n pass" + }, + "test_cases": [ + { + "input": "abcabcbb", + "output": "3", + "is_hidden": false + } + ] + }, + { + "title": "Container Max Water", + "description": "Find container with max water.", + "difficulty": "Medium", + "category": "Arrays", + "templates": { + "java": "public class Solution {\n public int maxArea(int[] height) {\n // Your code here\n return 0;\n }\n}", + "python": "def solve():\n # Implement Container Max Water\n pass" + }, + "test_cases": [ + { + "input": "[1,8,6,2,5,4,8,3,7]", + "output": "49", + "is_hidden": false + } + ] + }, + { + "title": "Integer to Roman", + "description": "Convert integer to roman.", + "difficulty": "Medium", + "category": "Math", + "templates": { + "java": "public class Solution {\n public String intToRoman(int num) {\n // Your code here\n return \"\";\n }\n}", + "python": "def solve():\n # Implement Integer to Roman\n pass" + }, + "test_cases": [ + { + "input": "3", + "output": "III", + "is_hidden": false + } + ] + }, + { + "title": "Roman to Integer", + "description": "Convert roman to integer.", + "difficulty": "Easy", + "category": "Math", + "templates": { + "java": "public class Solution {\n public int romanToInt(String s) {\n // Your code here\n return 0;\n }\n}", + "python": "def solve():\n # Implement Roman to Integer\n pass" + }, + "test_cases": [ + { + "input": "III", + "output": "3", + "is_hidden": false + } + ] + }, + { + "title": "Longest Common Prefix", + "description": "Find longest common prefix.", + "difficulty": "Easy", + "category": "Strings", + "templates": { + "java": "public class Solution {\n public String longestCommonPrefix(String[] strs) {\n // Your code here\n return \"\";\n }\n}", + "python": "def solve():\n # Implement Longest Common Prefix\n pass" + }, + "test_cases": [ + { + "input": "[\"flower\",\"flow\",\"flight\"]", + "output": "fl", + "is_hidden": false + } + ] + }, + { + "title": "3Sum", + "description": "Find all unique triplets that sum to zero.", + "difficulty": "Medium", + "category": "Arrays", + "templates": { + "java": "import java.util.*;\npublic class Solution {\n public List> threeSum(int[] nums) {\n // Your code here\n return null;\n }\n}", + "python": "def solve():\n # Implement 3Sum\n pass" + }, + "test_cases": [ + { + "input": "[-1,0,1,2,-1,-4]", + "output": "[[-1,-1,2],[-1,0,1]]", + "is_hidden": false + } + ] + }, + { + "title": "Letter Combinations", + "description": "Find all letter combinations of phone number.", + "difficulty": "Medium", + "category": "Strings", + "templates": { + "java": "import java.util.*;\npublic class Solution {\n public List letterCombinations(String digits) {\n // Your code here\n return null;\n }\n}", + "python": "def solve():\n # Implement Letter Combinations\n pass" + }, + "test_cases": [ + { + "input": "23", + "output": "[\"ad\",\"ae\",\"af\",\"bd\",\"be\",\"bf\",\"cd\",\"ce\",\"cf\"]", + "is_hidden": false + } + ] + }, + { + "title": "Remove Nth Node", + "description": "Remove nth node from end of list.", + "difficulty": "Medium", + "category": "Data Structures", + "templates": { + "java": "public class Solution {\n public ListNode removeNthFromEnd(ListNode head, int n) {\n // Your code here\n return null;\n }\n}", + "python": "def solve():\n # Implement Remove Nth Node\n pass" + }, + "test_cases": [ + { + "input": "[1,2,3,4,5], 2", + "output": "[1,2,3,5]", + "is_hidden": false + } + ] + }, + { + "title": "Swap Pairs", + "description": "Swap every two adjacent nodes.", + "difficulty": "Medium", + "category": "Data Structures", + "templates": { + "java": "public class Solution {\n public ListNode swapPairs(ListNode head) {\n // Your code here\n return null;\n }\n}", + "python": "def solve():\n # Implement Swap Pairs\n pass" + }, + "test_cases": [ + { + "input": "[1,2,3,4]", + "output": "[2,1,4,3]", + "is_hidden": false + } + ] + }, + { + "title": "Rotate Image", + "description": "Rotate nxn matrix by 90 degrees.", + "difficulty": "Medium", + "category": "Matrix", + "templates": { + "java": "public class Solution {\n public void rotate(int[][] matrix) {\n // Your code here\n }\n}", + "python": "def solve():\n # Implement Rotate Image\n pass" + }, + "test_cases": [ + { + "input": "[[1,2,3],[4,5,6],[7,8,9]]", + "output": "[[7,4,1],[8,5,2],[9,6,3]]", + "is_hidden": false + } + ] + }, + { + "title": "Group Anagrams", + "description": "Group anagrams together.", + "difficulty": "Medium", + "category": "Strings", + "templates": { + "java": "public class Solution {\n public boolean isAnagram(String s1, String s2) {\n // Your code here\n return false;\n }\n}", + "python": "def solve():\n # Implement Group Anagrams\n pass" + }, + "test_cases": [ + { + "input": "[\"eat\",\"tea\",\"tan\",\"ate\",\"nat\",\"bat\"]", + "output": "[[\"bat\"],[\"nat\",\"tan\"],[\"ate\",\"eat\",\"tea\"]]", + "is_hidden": false + } + ] + }, + { + "title": "Spiral Matrix", + "description": "Return all elements in spiral order.", + "difficulty": "Medium", + "category": "Matrix", + "templates": { + "java": "import java.util.*;\npublic class Solution {\n public List spiralOrder(int[][] matrix) {\n // Your code here\n return null;\n }\n}", + "python": "def solve():\n # Implement Spiral Matrix\n pass" + }, + "test_cases": [ + { + "input": "[[1,2,3],[4,5,6],[7,8,9]]", + "output": "[1,2,3,6,9,8,7,4,5]", + "is_hidden": false + } + ] + }, + { + "title": "Jump Game", + "description": "Check if you can reach the last index.", + "difficulty": "Medium", + "category": "Dynamic Programming", + "templates": { + "java": "public class Solution {\n public boolean canJump(int[] nums) {\n // Your code here\n return false;\n }\n}", + "python": "def solve():\n # Implement Jump Game\n pass" + }, + "test_cases": [ + { + "input": "[2,3,1,1,4]", + "output": "true", + "is_hidden": false + } + ] + } +] \ No newline at end of file diff --git a/src/scripts/data/java/temp/questions.json b/src/scripts/data/java/temp/questions.json new file mode 100644 index 0000000..0585096 --- /dev/null +++ b/src/scripts/data/java/temp/questions.json @@ -0,0 +1,882 @@ +[ + { + "title": "Java Restroom Quiz", + "text": "Which part of memory is used for objects in Java?", + "choices": [ + [ + "Stack", + false + ], + [ + "Heap", + true + ], + [ + "Register", + false + ], + [ + "Cache", + false + ] + ] + }, + { + "title": "Java Restroom Quiz", + "text": "Which component is responsible for converting bytecode into machine code?", + "choices": [ + [ + "Compiler", + false + ], + [ + "Interpreter", + false + ], + [ + "JIT Compiler", + true + ], + [ + "Class Loader", + false + ] + ] + }, + { + "title": "String Pool", + "text": "Where are string literals stored in Java memory?", + "choices": [ + [ + "Stack", + false + ], + [ + "String Constant Pool", + true + ], + [ + "Heap directly", + false + ], + [ + "Static area", + false + ] + ] + }, + { + "title": "Object Equality", + "text": "Which method should be overridden when overriding equals() in Java?", + "choices": [ + [ + "toString()", + false + ], + [ + "hashCode()", + true + ], + [ + "clone()", + false + ], + [ + "finalize()", + false + ] + ] + }, + { + "title": "Final Variable", + "text": "What happens when a variable is declared as final?", + "choices": [ + [ + "Value cannot be changed", + true + ], + [ + "Method cannot be overridden", + false + ], + [ + "Class cannot be inherited", + false + ], + [ + "Memory is freed", + false + ] + ] + }, + { + "title": "Abstract Class", + "text": "An abstract class can have...", + "choices": [ + [ + "Only abstract methods", + false + ], + [ + "Only concrete methods", + false + ], + [ + "Both abstract and concrete methods", + true + ], + [ + "Neither", + false + ] + ] + }, + { + "title": "Interface Methods", + "text": "Since Java 8, interfaces can have...", + "choices": [ + [ + "Abstract methods only", + false + ], + [ + "Static methods only", + false + ], + [ + "Default and static methods", + true + ], + [ + "No methods", + false + ] + ] + }, + { + "title": "Unchecked Exception", + "text": "Which of these is an unchecked exception?", + "choices": [ + [ + "IOException", + false + ], + [ + "NullPointerException", + true + ], + [ + "SQLException", + false + ], + [ + "ClassNotFoundException", + false + ] + ] + }, + { + "title": "Static Keyword", + "text": "What does the static keyword do to a variable?", + "choices": [ + [ + "Makes it constant", + false + ], + [ + "Shares it among all instances", + true + ], + [ + "Makes it private", + false + ], + [ + "Makes it thread-safe", + false + ] + ] + }, + { + "title": "Try-With-Resources", + "text": "Try-with-resources was introduced in which Java version?", + "choices": [ + [ + "Java 6", + false + ], + [ + "Java 7", + true + ], + [ + "Java 8", + false + ], + [ + "Java 9", + false + ] + ] + }, + { + "title": "Checked Exception", + "text": "Which exception must be declared or caught at compile time?", + "choices": [ + [ + "NullPointerException", + false + ], + [ + "ArithmeticException", + false + ], + [ + "Checked Exception", + true + ], + [ + "RuntimeException", + false + ] + ] + }, + { + "title": "List vs Set", + "text": "Which collection allows duplicate elements?", + "choices": [ + [ + "List", + true + ], + [ + "Set", + false + ], + [ + "Map", + false + ], + [ + "SortedSet", + false + ] + ] + }, + { + "title": "Garbage Collector", + "text": "Can we force garbage collection in Java?", + "choices": [ + [ + "Yes", + false + ], + [ + "No", + true + ], + [ + "Only in Java 8", + false + ], + [ + "Only with System.gc()", + false + ] + ] + }, + { + "title": "Thread Execution", + "text": "Which method starts a thread's execution?", + "choices": [ + [ + "run()", + false + ], + [ + "start()", + true + ], + [ + "execute()", + false + ], + [ + "begin()", + false + ] + ] + }, + { + "title": "Volatile Keyword", + "text": "The volatile keyword ensures...", + "choices": [ + [ + "Mutual exclusion", + false + ], + [ + "Visibility of changes", + true + ], + [ + "Atomicity", + false + ], + [ + "Deadlock prevention", + false + ] + ] + }, + { + "title": "Singleton Pattern", + "text": "A singleton class has...", + "choices": [ + [ + "Public constructor", + false + ], + [ + "Private constructor", + true + ], + [ + "No constructor", + false + ], + [ + "Protected constructor", + false + ] + ] + }, + { + "title": "Primitive Types", + "text": "How many primitive data types are in Java?", + "choices": [ + [ + "7", + false + ], + [ + "8", + true + ], + [ + "9", + false + ], + [ + "10", + false + ] + ] + }, + { + "title": "Byte Size", + "text": "What is the size of a long in Java?", + "choices": [ + [ + "32 bits", + false + ], + [ + "64 bits", + true + ], + [ + "16 bits", + false + ], + [ + "128 bits", + false + ] + ] + }, + { + "title": "Casting", + "text": "Converting a smaller type to a larger type size is called...", + "choices": [ + [ + "Narrowing", + false + ], + [ + "Widening", + true + ], + [ + "Parsing", + false + ], + [ + "Wrapping", + false + ] + ] + }, + { + "title": "Wrapper Classes", + "text": "Which class is the wrapper for the 'int' primitive?", + "choices": [ + [ + "Int", + false + ], + [ + "Integer", + true + ], + [ + "Int32", + false + ], + [ + "Number", + false + ] + ] + }, + { + "title": "Marker Interface", + "text": "Which of these is a marker interface?", + "choices": [ + [ + "Runnable", + false + ], + [ + "Serializable", + true + ], + [ + "Comparable", + false + ], + [ + "List", + false + ] + ] + }, + { + "title": "Inheritance", + "text": "Java supports which type of inheritance via classes?", + "choices": [ + [ + "Single", + true + ], + [ + "Multiple", + false + ], + [ + "Hybrid", + false + ], + [ + "All", + false + ] + ] + }, + { + "title": "Super Keyword", + "text": "The super keyword is used to refer to...", + "choices": [ + [ + "Current class members", + false + ], + [ + "Parent class members", + true + ], + [ + "Grandparent class", + false + ], + [ + "Subclass", + false + ] + ] + }, + { + "title": "This Keyword", + "text": "The this keyword refers to...", + "choices": [ + [ + "Current instance", + true + ], + [ + "Parent instance", + false + ], + [ + "Static variable", + false + ], + [ + "Class name", + false + ] + ] + }, + { + "title": "Java Compiler", + "text": "Java source code is compiled into...", + "choices": [ + [ + "Machine code", + false + ], + [ + "Bytecode", + true + ], + [ + "Assembly", + false + ], + [ + "Binary", + false + ] + ] + }, + { + "title": "File Extension", + "text": "Compiled Java files have the extension...", + "choices": [ + [ + ".java", + false + ], + [ + ".class", + true + ], + [ + ".exe", + false + ], + [ + ".obj", + false + ] + ] + }, + { + "title": "Constructor", + "text": "A class can have how many constructors?", + "choices": [ + [ + "One", + false + ], + [ + "Two", + false + ], + [ + "Zero", + false + ], + [ + "Multiple", + true + ] + ] + }, + { + "title": "Method Overloading", + "text": "Method overloading depends on change in...", + "choices": [ + [ + "Return type", + false + ], + [ + "Modifiers", + false + ], + [ + "Method signature/parameters", + true + ], + [ + "Exceptions thrown", + false + ] + ] + }, + { + "title": "Method Overriding", + "text": "Overriding occurs in...", + "choices": [ + [ + "Same class", + false + ], + [ + "Subclass", + true + ], + [ + "Superclass", + false + ], + [ + "Static block", + false + ] + ] + }, + { + "title": "Encapsulation", + "text": "Encapsulation is achieved by...", + "choices": [ + [ + "Inheritance", + false + ], + [ + "Interfaces", + false + ], + [ + "Private fields and public getters/setters", + true + ], + [ + "Static methods", + false + ] + ] + }, + { + "title": "Polymorphism", + "text": "Polymorphism which is resolved at runtime is...", + "choices": [ + [ + "Static Binding", + false + ], + [ + "Dynamic Binding", + true + ], + [ + "Compile-time", + false + ], + [ + "Late binding", + false + ] + ] + }, + { + "title": "Packages", + "text": "Which keyword is used to import a package?", + "choices": [ + [ + "package", + false + ], + [ + "using", + false + ], + [ + "import", + true + ], + [ + "include", + false + ] + ] + }, + { + "title": "Main Method", + "text": "The main method must be...", + "choices": [ + [ + "Static", + true + ], + [ + "Private", + false + ], + [ + "Protected", + false + ], + [ + "Non-static", + false + ] + ] + }, + { + "title": "Lambda Expression", + "text": "Lambdas can be used with what type of interfaces?", + "choices": [ + [ + "Marker", + false + ], + [ + "Functional", + true + ], + [ + "Abstract", + false + ], + [ + "Normal", + false + ] + ] + }, + { + "title": "Optional Class", + "text": "Optional class helps avoid...", + "choices": [ + [ + "OutOfMemoryError", + false + ], + [ + "NullPointerException", + true + ], + [ + "StackOverflowError", + false + ], + [ + "IOException", + false + ] + ] + }, + { + "title": "Stream API", + "text": "Which stream operation is a terminal operation?", + "choices": [ + [ + "map", + false + ], + [ + "filter", + false + ], + [ + "collect", + true + ], + [ + "sorted", + false + ] + ] + }, + { + "title": "HashMap vs ConcurrentHashMap", + "text": "Which one is thread-safe?", + "choices": [ + [ + "HashMap", + false + ], + [ + "ConcurrentHashMap", + true + ], + [ + "TreeMap", + false + ], + [ + "IdentityHashMap", + false + ] + ] + }, + { + "title": "Serialization", + "text": "To prevent a field from being serialized, use...", + "choices": [ + [ + "static", + false + ], + [ + "volatile", + false + ], + [ + "transient", + true + ], + [ + "final", + false + ] + ] + }, + { + "title": "Reflection API", + "text": "Reflection allows inspecting...", + "choices": [ + [ + "Only public members", + false + ], + [ + "Classes and members at runtime", + true + ], + [ + "Source code", + false + ], + [ + "Comment lines", + false + ] + ] + }, + { + "title": "Java Versioning", + "text": "LTS stands for...", + "choices": [ + [ + "Long Term Service", + false + ], + [ + "Long Term Support", + true + ], + [ + "List of Thread states", + false + ], + [ + "Local Thread Storage", + false + ] + ] + } +] \ No newline at end of file diff --git a/src/scripts/data/java/temp/riddles.json b/src/scripts/data/java/temp/riddles.json new file mode 100644 index 0000000..861419a --- /dev/null +++ b/src/scripts/data/java/temp/riddles.json @@ -0,0 +1,602 @@ +[ + { + "text": "A pointed peak with a belt across, I lead the alphabet without a loss. In this code, I take the lead, the very first step you'll need to read.", + "char": "A", + "index": 1, + "difficulty": "Easy" + }, + { + "text": "Two loops stacked upon a line, a buzzing insect shares my sign. I step into the second place, moving forward in this race.", + "char": "B", + "index": 2, + "difficulty": "Hard" + }, + { + "text": "A crescent moon facing the right, an ocean vast but out of sight. I sit right in the middle space, the third lock in this secret place.", + "char": "C", + "index": 3, + "difficulty": "Hard" + }, + { + "text": "A straight back with a rounded front, I start the day and lead the hunt. Penultimate is my domain, the fourth link in this sturdy chain.", + "char": "D", + "index": 4, + "difficulty": "Medium" + }, + { + "text": "Three teeth upon a vertical comb, I'm found at the end of every 'home'. I close this set, the final key, the fifth and last, unlocking thee.", + "char": "E", + "index": 5, + "difficulty": "Medium" + }, + { + "text": "A flag waving on a single pole, I am the spark that starts the 'fire'. I claim the very first position, starting off this secret mission.", + "char": "F", + "index": 1, + "difficulty": "Medium" + }, + { + "text": "An arrow spinning inward tight, the start of 'good' and end of 'dog'. I follow close behind the start, the second piece of this puzzle's heart.", + "char": "G", + "index": 2, + "difficulty": "Medium" + }, + { + "text": "Two tall walls and a bridge between, in 'heaven' and 'hell' I can be seen. I stand at number three, you see, the center of this mystery.", + "char": "H", + "index": 3, + "difficulty": "Easy" + }, + { + "text": "I am the ego, standing alone, a single pillar carved in stone. Number four is where I rest, one step away from finishing the test.", + "char": "I", + "index": 4, + "difficulty": "Hard" + }, + { + "text": "A fishhook waiting for a bite, I bring the 'joy' into the light. The fifth and final slot I claim, the ending of this guessing game.", + "char": "J", + "index": 5, + "difficulty": "Hard" + }, + { + "text": "A straight line with an open beak, I start the 'kite' that children seek. I am the first one in the queue, the starting point revealed to you.", + "char": "K", + "index": 1, + "difficulty": "Easy" + }, + { + "text": "A right angle sitting on the floor, the shape of a loser, but 'love's' true door. Second in line is where I fall, answering the puzzle's call.", + "char": "L", + "index": 2, + "difficulty": "Medium" + }, + { + "text": "Two mountain peaks that touch the sky, turned upside down, a 'W' am I. The third position is my throne, exactly in the middle zone.", + "char": "M", + "index": 3, + "difficulty": "Hard" + }, + { + "text": "A jagged peak, an endless 'no', I point the compass where to go. I take the fourth spot on the board, almost completing the final cord.", + "char": "N", + "index": 4, + "difficulty": "Easy" + }, + { + "text": "A perfect circle, an empty space, surprise is written on my face. The fifth and final number's mine, the last link in the line.", + "char": "O", + "index": 5, + "difficulty": "Medium" + }, + { + "text": "A head on a stick, looking to the right, a 'pirate's' start, prepared to fight. I am the vanguard, number one, the very place this code begun.", + "char": "P", + "index": 1, + "difficulty": "Medium" + }, + { + "text": "A circle with a tiny tail, without a 'U', I often fail. I hold the second spot in line, a quirky piece of this design.", + "char": "Q", + "index": 2, + "difficulty": "Medium" + }, + { + "text": "A pirate's favorite sound to make, a leg kicks out for goodness' sake! Dead center at the number three, the heart of this security.", + "char": "R", + "index": 3, + "difficulty": "Medium" + }, + { + "text": "A winding river, a snake's swift glide, I am the plural at the end of the ride. Position four is where I stand, the second-to-last in this command.", + "char": "S", + "index": 4, + "difficulty": "Hard" + }, + { + "text": "A simple cross, a balanced scale, I end the 'cat' and start the 'tale'. Number five is my decree, the final cipher is the key.", + "char": "T", + "index": 5, + "difficulty": "Easy" + }, + { + "text": "An open cup to catch the rain, I sound like you but have no brain. I am the first to take the stage, the opening letter on this page.", + "char": "U", + "index": 1, + "difficulty": "Easy" + }, + { + "text": "A plunging valley, steep and deep, the Roman numeral five I keep. But here I sit at number two, the second step to see you through.", + "char": "V", + "index": 2, + "difficulty": "Medium" + }, + { + "text": "Two valleys joined or double 'U', I ask 'what', 'where', and 'who'. Third in the sequence is my place, right in the middle of the race.", + "char": "W", + "index": 3, + "difficulty": "Medium" + }, + { + "text": "I mark the spot where treasures hide, a crossing path from side to side. Position four is my domain, near the end of this brain-drain.", + "char": "X", + "index": 4, + "difficulty": "Easy" + }, + { + "text": "A branching road, a question asked, the end of 'day', a simple task. I finish up at number five, the last to keep this code alive.", + "char": "Y", + "index": 5, + "difficulty": "Medium" + }, + { + "text": "A zigzag path, a sleepy sound, the final letter to be found. Yet here I break the natural rule, and stand first to test the fool.", + "char": "Z", + "index": 1, + "difficulty": "Hard" + }, + { + "text": "A triangle with a missing base, the start of the human alphabet race. But here I take the second seat, the next step on this puzzling street.", + "char": "A", + "index": 2, + "difficulty": "Easy" + }, + { + "text": "The most common letter you will see, a horizontal pitchfork facing free. I sit at three, the middle bound, where balance in the code is found.", + "char": "E", + "index": 3, + "difficulty": "Medium" + }, + { + "text": "The seeing orb without the eye, a straight line pointing to the sky. I wait at four, almost the end, a subtle clue for you, my friend.", + "char": "I", + "index": 4, + "difficulty": "Hard" + }, + { + "text": "A ring of gold, a hollow sphere, when you understand, you say 'Oh dear!'. The fifth position is my home, the final stop where you will roam.", + "char": "O", + "index": 5, + "difficulty": "Easy" + }, + { + "text": "A loop on top of a single pole, I pop and ping to play my role. I follow the leader, taking slot two, revealing the next hidden step to you.", + "char": "P", + "index": 2, + "difficulty": "Easy" + }, + { + "text": "A straight-backed guard with an arm and a kick, I start the 'knight' though the 'n' does the trick. I stand at the center, the vital third space, the balancing act in this numeric race.", + "char": "K", + "index": 3, + "difficulty": "Hard" + }, + { + "text": "A sharp right angle, a corner turned square, I am the start of the 'love' in the air. Fourth in the sequence, I patiently wait, just one step away from unlocking the gate.", + "char": "L", + "index": 4, + "difficulty": "Medium" + }, + { + "text": "A circle left open, a crescent of light, I start off the 'cat' prowling into the night. I am the fifth, the final decree, the last puzzle piece to set the lock free.", + "char": "C", + "index": 5, + "difficulty": "Easy" + }, + { + "text": "Like a comb with two teeth or a flag blowing free, I start off the 'future' for you and for me. I am the vanguard, the very first key, unlocking the start of this mystery.", + "char": "F", + "index": 1, + "difficulty": "Medium" + }, + { + "text": "A horseshoe facing the heavens above, I sound like the person you're speaking of. Second in line, I step up to the plate, forging ahead through the cryptographic gate.", + "char": "U", + "index": 2, + "difficulty": "Hard" + }, + { + "text": "A straight wooden bow with a string pulled tight, I bring the 'dawn' after the dark of the night. Dead in the center, at index number three, I hold the middle of this secret key.", + "char": "D", + "index": 3, + "difficulty": "Easy" + }, + { + "text": "An open loop that curls inward and stops, I start the 'gravity' before the apple drops. Almost the end, I take the fourth slot, tightening the loop on the password's knot.", + "char": "G", + "index": 4, + "difficulty": "Hard" + }, + { + "text": "Up, then diagonal, and straight up once more, I sit at the center of the word 'ignore'. The fifth and the final, the last of the line, complete the sequence and the prize is thine.", + "char": "N", + "index": 5, + "difficulty": "Medium" + }, + { + "text": "A loop on a stick with a leg kicking out, I roar and I rumble, I whisper and shout. I stand at the threshold, the very first space, kicking things off in this puzzling chase.", + "char": "R", + "index": 1, + "difficulty": "Easy" + }, + { + "text": "Two bubbles attached to a vertical spine, I am the start of the 'borderline'. Seated at three, the heart of the code, exactly halfway down this winding road.", + "char": "B", + "index": 3, + "difficulty": "Hard" + }, + { + "text": "Twin mountain summits, a valley between, in 'magic' and 'mystery' I'm often seen. I slide into second, continuing the quest, putting your cipher skills to the test.", + "char": "M", + "index": 2, + "difficulty": "Medium" + }, + { + "text": "A flat wooden roof on a pillar so tall, I start off the 'time' that will govern us all. Fourth in the lineup, I stand straight and true, preparing the final transition for you.", + "char": "T", + "index": 4, + "difficulty": "Easy" + }, + { + "text": "A downward plunge and a steep upward climb, the shape of a wedge cutting right through the rhyme. The fifth position is where I descend, marking the cipher's definitive end.", + "char": "V", + "index": 5, + "difficulty": "Hard" + }, + { + "text": "Twin valleys carved out by rivers of old, I spin the 'web' where the secrets unfold. I am the alpha, the number one slot, the starting thread of this intricate plot.", + "char": "W", + "index": 1, + "difficulty": "Medium" + }, + { + "text": "An umbrella handle turned upside down, a jester who juggles to entertain town. I swing into second, the follow-up act, keeping the passkey entirely intact.", + "char": "J", + "index": 2, + "difficulty": "Hard" + }, + { + "text": "A perfect round circle with a tiny kickstand, the 'queen' of the letters ruling the land. I rest in the middle, position number three, the balancing point of the master key.", + "char": "Q", + "index": 3, + "difficulty": "Easy" + }, + { + "text": "A slippery serpent that slithers around, a hissing 'silence' with barely a sound. Second-to-last is the spot that I claim, slot number four in this guessing game.", + "char": "S", + "index": 4, + "difficulty": "Medium" + }, + { + "text": "A fork in the road where you must make a choice, the roaring 'yell' of a powerful voice. The final position, the absolute end, slot number five is the message I send.", + "char": "Y", + "index": 5, + "difficulty": "Hard" + }, + { + "text": "Like goalposts erected upon the green field, I am the 'hero' with sword and with shield. I step up to one, the very first gate, the opening move of this puzzle's fate.", + "char": "H", + "index": 1, + "difficulty": "Easy" + }, + { + "text": "A mountain peak crossed by a trail, the starting breath of every tale. I sit exactly in the middle space, claiming the third and central place.", + "char": "A", + "index": 3, + "difficulty": "Easy" + }, + { + "text": "The right wing of a butterfly, a buzzing sound as I fly by. I take the fourth step in the quest, just one more left to beat the test.", + "char": "B", + "index": 4, + "difficulty": "Medium" + }, + { + "text": "A silver sickle in the sky, a crescent moon that catches the eye. The final piece of the design, the fifth and closing of the line.", + "char": "C", + "index": 5, + "difficulty": "Hard" + }, + { + "text": "A hunter\u2019s bow with a tautened string, the start of \u2018dawn\u2019 and end of \u2018king\u2019. I am the first, the opening door, with four more secrets to explore.", + "char": "D", + "index": 1, + "difficulty": "Easy" + }, + { + "text": "A heavy rake with just three tines, the most used letter in these lines. I step into the second slot, continuing the secret plot.", + "char": "E", + "index": 2, + "difficulty": "Medium" + }, + { + "text": "A weather vane with arrows blown, the start of every \u2018fault\u2019 that's known. I am the third, the middle ground, where perfect symmetry is found.", + "char": "F", + "index": 3, + "difficulty": "Hard" + }, + { + "text": "An open circle turning in, where \u2018game\u2019 and \u2018glory\u2019 both begin. Penultimate is my domain, the fourth link in this sturdy chain.", + "char": "G", + "index": 4, + "difficulty": "Easy" + }, + { + "text": "A ladder missing all but one, the breathless sigh when work is done. The fifth and final lock I keep, the end of the puzzle, dark and deep.", + "char": "H", + "index": 5, + "difficulty": "Medium" + }, + { + "text": "A single needle standing tall, the Roman one, the start of all. I am the pioneer today, the number one who leads the way.", + "char": "I", + "index": 1, + "difficulty": "Hard" + }, + { + "text": "A candy cane flipped upside down, the joyful \u2018jester\u2019 of the town. I follow close behind the lead, the second cipher that you need.", + "char": "J", + "index": 2, + "difficulty": "Easy" + }, + { + "text": "A snapping branch against a tree, the start of every \u2018knight\u2019 you see. Dead center at the number three, the heart of this security.", + "char": "K", + "index": 3, + "difficulty": "Medium" + }, + { + "text": "A corner square, a perfect right, the heavy \u2018lead\u2019 in darkest night. I take the fourth spot on the board, almost completing the final cord.", + "char": "L", + "index": 4, + "difficulty": "Hard" + }, + { + "text": "Twin mountain peaks that touch the sun, a \u2018million\u2019 miles until we\u2019re done. I close the book, the fifth decree, the final cipher is the key.", + "char": "M", + "index": 5, + "difficulty": "Easy" + }, + { + "text": "A lightning bolt that strikes the ground, a stubborn \u2018no\u2019 without a sound. I claim the very first position, starting off this secret mission.", + "char": "N", + "index": 1, + "difficulty": "Medium" + }, + { + "text": "A golden ring without a stone, an empty void left all alone. Second in line is where I fall, answering the puzzle's call.", + "char": "O", + "index": 2, + "difficulty": "Hard" + }, + { + "text": "A butterfly with just one wing, a popping \u2018penny\u2019 for the king. I stand at number three, you see, the center of this mystery.", + "char": "P", + "index": 3, + "difficulty": "Easy" + }, + { + "text": "A magnifying glass held near, to make the \u2018question\u2019 crystal clear. The fourth position I demand, the second-to-last in this command.", + "char": "Q", + "index": 4, + "difficulty": "Medium" + }, + { + "text": "A standing guard who kicks a knee, the roaring sound of the angry sea. Number five is my decree, the final cipher is the key.", + "char": "R", + "index": 5, + "difficulty": "Hard" + }, + { + "text": "A swan\u2019s long neck, a winding stream, the start of every \u2018silent\u2019 dream. I lead the alphabet's new race, taking the very first place.", + "char": "S", + "index": 1, + "difficulty": "Easy" + }, + { + "text": "A hammer poised to strike a nail, the ending of the \u2018cat\u2019 and \u2018tale\u2019. I step into the second place, moving forward in this race.", + "char": "T", + "index": 2, + "difficulty": "Medium" + }, + { + "text": "An empty bowl awaiting soup, an open, upward-facing loop. The third position is my throne, exactly in the middle zone.", + "char": "U", + "index": 3, + "difficulty": "Hard" + }, + { + "text": "A flock of birds in distant flight, a plunging valley out of sight. I take the fourth slot in your quest, just one more left to beat the test.", + "char": "V", + "index": 4, + "difficulty": "Easy" + }, + { + "text": "A jagged wave upon the sea, a double curve of mystery. The fifth and final slot I claim, the ending of this guessing game.", + "char": "W", + "index": 5, + "difficulty": "Medium" + }, + { + "text": "Two clashing swords that meet in strife, the unknown variable in life. I am the vanguard, number one, the very place this code begun.", + "char": "X", + "index": 1, + "difficulty": "Hard" + }, + { + "text": "A slingshot drawn to fire a stone, the ending of the \u2018day\u2019 alone. I hold the second spot in line, a quirky piece of this design.", + "char": "Y", + "index": 2, + "difficulty": "Easy" + }, + { + "text": "The zigzag mark a swordsman leaves, the sleepy sound the dreamer weaves. Dead center at the number three, the heart of this security.", + "char": "Z", + "index": 3, + "difficulty": "Medium" + }, + { + "text": "The pointed nose of a rocket ship, the start of the \u2018apple\u2019 you can grip. Position four is where I stand, the second-to-last in this command.", + "char": "A", + "index": 4, + "difficulty": "Hard" + }, + { + "text": "A pair of glasses turned on end, a \u2018brave\u2019 and bold, courageous friend. I finish up at number five, the last to keep this code alive.", + "char": "B", + "index": 5, + "difficulty": "Easy" + }, + { + "text": "A bitten cookie, curved and sweet, a \u2018clever\u2019 cat upon the street. I start the sequence, fresh and new, the first clue given unto you.", + "char": "C", + "index": 1, + "difficulty": "Medium" + }, + { + "text": "A half-moon resting on a wall, the \u2018dark\u2019 that falls upon us all. But here I sit at number two, the second step to see you through.", + "char": "D", + "index": 2, + "difficulty": "Hard" + }, + { + "text": "A comb designed for giant's hair, an \u2018echo\u2019 fading in the air. I rest in the middle, position three, the balancing point of the master key.", + "char": "E", + "index": 3, + "difficulty": "Easy" + }, + { + "text": "A wooden gibbet standing tall, a \u2018feather\u2019 drifting to the fall. Fourth in the sequence, I patiently wait, just one step away from unlocking the gate.", + "char": "F", + "index": 4, + "difficulty": "Medium" + }, + { + "text": "A curving snake that bites its tail, a \u2018ghost\u2019 that wanders, cold and pale. I am the fifth, the final decree, the last puzzle piece to set the lock free.", + "char": "G", + "index": 5, + "difficulty": "Hard" + }, + { + "text": "Two columns holding up the sky, the \u2018heavy\u2019 heave, the weary sigh. I am the first to take the stage, the opening letter on this page.", + "char": "H", + "index": 1, + "difficulty": "Easy" + }, + { + "text": "An icicle hanging straight and true, an \u2018island\u2019 in the ocean blue. Second in line, I step up to the plate, forging ahead through the cryptographic gate.", + "char": "I", + "index": 2, + "difficulty": "Medium" + }, + { + "text": "A scythe to reap the golden wheat, a \u2018jungle\u2019 filled with humid heat. Dead in the center, at index number three, I hold the middle of this secret key.", + "char": "J", + "index": 3, + "difficulty": "Hard" + }, + { + "text": "A bird\u2019s beak opening to sing, a \u2018kite\u2019 that flies upon the string. Almost the end, I take the fourth slot, tightening the loop on the password's knot.", + "char": "K", + "index": 4, + "difficulty": "Easy" + }, + { + "text": "A heavy boot without a toe, the \u2018light\u2019 that helps the garden grow. The fifth and the final, the last of the line, complete the sequence and the prize is thine.", + "char": "L", + "index": 5, + "difficulty": "Medium" + }, + { + "text": "The steady hum of a busy hive, a \u2018mountain\u2019 where the eagles thrive. I stand at the threshold, the very first space, kicking things off in this puzzling chase.", + "char": "M", + "index": 1, + "difficulty": "Hard" + }, + { + "text": "A rigid seesaw locked in place, the \u2018night\u2019 that covers up the space. I follow the leader, taking slot two, revealing the next hidden step to you.", + "char": "N", + "index": 2, + "difficulty": "Easy" + }, + { + "text": "The quiet eye of a raging storm, an \u2018open\u2019 door to keep you warm. Seated at three, the heart of the code, exactly halfway down this winding road.", + "char": "O", + "index": 3, + "difficulty": "Medium" + }, + { + "text": "A keyhole's upper, rounded half, a \u2018playful\u2019 joke to make you laugh. Fourth in the lineup, I stand straight and true, preparing the final transition for you.", + "char": "P", + "index": 4, + "difficulty": "Hard" + }, + { + "text": "A rolling coin that slips away, a \u2018quiet\u2019 moment in the day. The fifth position is where I descend, marking the cipher's definitive end.", + "char": "Q", + "index": 5, + "difficulty": "Easy" + }, + { + "text": "A sailor's mast with a rolled-up sail, a \u2018roaring\u2019 lion on the trail. I am the alpha, the number one slot, the starting thread of this intricate plot.", + "char": "R", + "index": 1, + "difficulty": "Medium" + }, + { + "text": "A hook that hangs upon the door, the \u2018sand\u2019 that washes on the shore. I swing into second, the follow-up act, keeping the passkey entirely intact.", + "char": "S", + "index": 2, + "difficulty": "Hard" + }, + { + "text": "A balanced scale of justice blind, the \u2018truth\u2019 that you must seek and find. I sit at three, the middle bound, where balance in the code is found.", + "char": "T", + "index": 3, + "difficulty": "Easy" + }, + { + "text": "A gentle smile without a face, an \u2018under\u2019 world beneath this place. Second-to-last is the spot that I claim, slot number four in this guessing game.", + "char": "U", + "index": 4, + "difficulty": "Medium" + }, + { + "text": "A teardrop falling from the sky, a \u2018valley\u2019 where the shadows lie. The final position, the absolute end, slot number five is the message I send.", + "char": "V", + "index": 5, + "difficulty": "Hard" + }, + { + "text": "Two deep ravines beside a hill, a \u2018whisper\u2019 when the wind is still. I step up to one, the very first gate, the opening move of this puzzle's fate.", + "char": "W", + "index": 1, + "difficulty": "Easy" + }, + { + "text": "A windmill's blades that catch the breeze, the \u2018xylophone\u2019 that plays with ease. I slide into second, continuing the quest, putting your cipher skills to the test.", + "char": "X", + "index": 2, + "difficulty": "Medium" + } +] \ No newline at end of file diff --git a/src/scripts/data/java/theict/__init__.py b/src/scripts/data/java/theict/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/scripts/delete.py b/src/scripts/delete.py new file mode 100644 index 0000000..292394d --- /dev/null +++ b/src/scripts/delete.py @@ -0,0 +1,52 @@ +import logging +from sqlalchemy import text +from sqlmodel import Session +from infrastructure import engine +from tqdm import tqdm + +logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s') + +def delete_all_data(): + if not engine: + logging.error("No database engine found. Skipping deletion.") + return + + with Session(engine) as session: + logging.info("Deleting all data from database...") + + # Order matters due to foreign key constraints if not using CASCADE + # However, TRUNCATE with CASCADE is the most thorough way + tables = [ + "riddle_tags", + "question_tags", + "question_categories", + "choices", + "questions", + "riddles", + "problem_categories", + "problem_tags", + "test_cases", + "chunks_categories", + "chunks_tags", + "snippets", + "expectations", + "chunk_templates", + "chunks", + "problems", + "categories", + "tags" + ] + + try: + for table in tqdm(tables, desc="Deleting tables", unit="table"): + logging.info(f"Deleting data from {table}...") + session.exec(text(f"DELETE FROM {table}")) + + session.commit() + logging.info("Successfully deleted all data from the database.") + except Exception as e: + session.rollback() + logging.error(f"Error during deletion: {e}") + +if __name__ == "__main__": + delete_all_data() diff --git a/src/scripts/seed.py b/src/scripts/seed.py index ca252ce..c02fdb6 100644 --- a/src/scripts/seed.py +++ b/src/scripts/seed.py @@ -290,7 +290,7 @@ def add_problem(title, description, difficulty, category_list, tag_list, config= { "lang": "javascript", "name": "JavaScript Implementation", - "code": "function solution({{{args}}}) {\n{{{indent logic}}}\n}\n\n// Test here\n{{{test}}}", + "code": "function solution({{{args}}}) {\n{{{logic}}}\n}\n\n// Test here\n{{{test}}}", "snippets": [("args", "x, y"), ("logic", "return x * y;"), ("test", "console.log(solution(1, 2))")] } ], @@ -303,13 +303,13 @@ def add_problem(title, description, difficulty, category_list, tag_list, config= { "lang": "python", "name": "Python Implementation", - "code": "def solution({{{args}}}):\n{{{indent logic}}}\n\n# Test here\n{{{test}}}", + "code": "def solution({{{args}}}):\n{{{logic}}}\n\n# Test here\n{{{test}}}", "snippets": [("args", "x, y"), ("logic", "return x + y"), ("test", "print(solution(2, 4))")] }, { "lang": "javascript", "name": "JavaScript Implementation", - "code": "function solution({{{args}}}) {\n{{{indent logic}}}\n}\n\n// Test here\n{{{test}}}", + "code": "function solution({{{args}}}) {\n{{{logic}}}\n}\n\n// Test here\n{{{test}}}", "snippets": [("args", "x, y"), ("logic", "return x + y;"), ("test", "console.log(solution(2, 4))")] } ], @@ -322,13 +322,13 @@ def add_problem(title, description, difficulty, category_list, tag_list, config= { "lang": "python", "name": "Python Implementation", - "code": "def solution({{{args}}}):\n{{{indent logic}}}\n\n# Test here\n{{{test}}}", + "code": "def solution({{{args}}}):\n{{{logic}}}\n\n# Test here\n{{{test}}}", "snippets": [("args", "x, y"), ("logic", "return x * y"), ("test", "print(solution(3, 6))")] }, { "lang": "javascript", "name": "JavaScript Implementation", - "code": "function solution({{{args}}}) {\n{{{indent logic}}}\n}\n\n// Test here\n{{{test}}}", + "code": "function solution({{{args}}}) {\n{{{logic}}}\n}\n\n// Test here\n{{{test}}}", "snippets": [("args", "x, y"), ("logic", "return x * y;"), ("test", "console.log(solution(3, 6))")] } ], @@ -342,7 +342,7 @@ def add_problem(title, description, difficulty, category_list, tag_list, config= { "lang": "python", "name": "Complex Python Implementation", - "code": "{{{imports}}}\n\n{{{setup}}}\n\ndef utility(v):\n return v * 2\n\ndef solution({{{args}}}):\n{{{indent validation}}}\n{{{indent logic}}}\n\n# Test here\n{{{test}}}", + "code": "{{{imports}}}\n\n{{{setup}}}\n\ndef utility(v):\n return v * 2\n\ndef solution({{{args}}}):\n{{{validation}}}\n{{{logic}}}\n\n# Test here\n{{{test}}}", "snippets": [ ("imports", "import math\nimport random"), ("setup", "OFFSET = 100\ndef get_offset(): return OFFSET"), @@ -355,7 +355,7 @@ def add_problem(title, description, difficulty, category_list, tag_list, config= { "lang": "javascript", "name": "Complex JavaScript Implementation", - "code": "{{{imports}}}\n\n{{{setup}}}\n\nfunction utility(v) {\n return v * 2;\n}\n\nfunction solution({{{args}}}) {\n{{{indent validation}}}\n{{{indent logic}}}\n}\n\n// Test here\n{{{test}}}", + "code": "{{{imports}}}\n\n{{{setup}}}\n\nfunction utility(v) {\n return v * 2;\n}\n\nfunction solution({{{args}}}) {\n{{{validation}}}\n{{{logic}}}\n}\n\n// Test here\n{{{test}}}", "snippets": [ ("imports", "// No imports needed"), ("setup", "const OFFSET = 100;\nfunction getOffset() { return OFFSET; }"), diff --git a/src/scripts/seeders/__init__.py b/src/scripts/seeders/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/scripts/seeders/seed_hallway.py b/src/scripts/seeders/seed_hallway.py new file mode 100644 index 0000000..c5fb9e0 --- /dev/null +++ b/src/scripts/seeders/seed_hallway.py @@ -0,0 +1,224 @@ +import logging +import uuid +import random +import json +import os +from datetime import datetime, timezone +from sqlalchemy import text +from sqlalchemy.orm.attributes import flag_modified +from sqlmodel import Session, select +from infrastructure import engine +from models import ( + Category, Tag, Riddle, Question, Choice, Chunk, ChunkTemplate, Snippet, Expectation, Problem, TestCase +) + +logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s') + +NAMESPACE = uuid.NAMESPACE_DNS + +def get_uuid(name: str) -> uuid.UUID: + """Generate a deterministic UUID based on a string name.""" + return uuid.uuid5(NAMESPACE, name) + +def load_json(filename): + # Base directory for seeding data (one level up from seeders/) + base_path = os.path.join(os.path.dirname(__file__), "..", "data", "java", "hallway") + filepath = os.path.join(base_path, filename) + if not os.path.exists(filepath): + logging.warning(f"File not found: {filepath}") + return [] + with open(filepath, "r") as f: + return json.load(f) + +def seed_hallway_java(): + if not engine: + logging.error("No database engine found. Skipping seeding.") + return + + # Load data from JSON files + QUESTIONS = load_json("questions.json") + RIDDLES = load_json("riddles.json") + CHUNKS = load_json("chunks.json") + PROBLEMS = load_json("problems.json") + + with Session(engine) as session: + logging.info("Starting JAV_HALLWAY JSON-based seeding process...") + + def get_or_create_category(name): + cat_id = get_uuid(f"cat_{name}") + cat = session.exec(select(Category).where(Category.id == cat_id)).first() + if not cat: + cat = session.exec(select(Category).where(Category.name == name)).first() + if not cat: + cat = Category(id=cat_id, name=name) + session.add(cat) + session.commit() + session.refresh(cat) + return cat + + def get_or_create_tag(name): + tag_id = get_uuid(f"tag_{name}") + tag = session.exec(select(Tag).where(Tag.id == tag_id)).first() + if not tag: + tag = session.exec(select(Tag).where(Tag.name == name)).first() + if not tag: + tag = Tag(id=tag_id, name=name) + session.add(tag) + session.commit() + session.refresh(tag) + return tag + + jav_hallway_tag = get_or_create_tag("JAV_HALLWAY") + java_cat = get_or_create_category("Java") + + # 1. Seed Questions + logging.info(f"Seeding {len(QUESTIONS)} Java questions...") + for q_data in QUESTIONS: + q_id = get_uuid(f"jav_hallway_q_{q_data['title']}") + if session.exec(select(Question).where(Question.id == q_id)).first(): + continue + + question = Question( + id=q_id, + title=q_data["title"], + question_text=q_data["text"], + created_at=datetime.now(timezone.utc) + ) + question.tags = [jav_hallway_tag] + question.categories = [java_cat] + session.add(question) + session.flush() + + for i, (choice_text, is_correct) in enumerate(q_data["choices"]): + c_id = get_uuid(f"jav_hallway_c_{q_data['title']}_{i}") + choice = Choice( + id=c_id, + question_id=question.id, + choice_text=choice_text, + is_correct=is_correct + ) + session.add(choice) + + # 2. Seed Riddles + logging.info(f"Seeding {len(RIDDLES)} Java riddles...") + for i, r_data in enumerate(RIDDLES): + r_id = get_uuid(f"jav_hallway_r_{i}") + if session.exec(select(Riddle).where(Riddle.id == r_id)).first(): + continue + + riddle = Riddle( + id=r_id, + riddle_text=r_data["text"], + refer_char=r_data["char"], + refer_index=r_data["index"], + difficulty=r_data["difficulty"] or "Medium", + created_at=datetime.now(timezone.utc) + ) + riddle.tags = [jav_hallway_tag] + session.add(riddle) + + # 3. Seed Chunks + logging.info(f"Seeding {len(CHUNKS)} Java chunks...") + for c_data in CHUNKS: + c_id = get_uuid(f"jav_hallway_chunk_{c_data['title']}") + chunk = session.exec(select(Chunk).where(Chunk.id == c_id)).first() + if not chunk: + chunk = Chunk( + id=c_id, + title=c_data["title"], + difficulty=c_data["difficulty"], + created_at=datetime.now(timezone.utc) + ) + chunk.categories = [get_or_create_category(c_data.get("category", "Java Basics"))] + chunk.tags = [jav_hallway_tag] + session.add(chunk) + session.flush() + else: + # Update basic info + chunk.difficulty = c_data["difficulty"] + # Clear existing templates to re-seed (cascades to snippets) + for t in chunk.templates: + session.delete(t) + session.flush() + + for lang, t_data in c_data["templates"].items(): + template = ChunkTemplate( + chunk_id=chunk.id, + language=lang, + name=t_data["name"], + template_code=t_data["template_code"], + description=t_data.get("description", f"Standard {lang} boilerplate") + ) + session.add(template) + session.flush() + + for key, content in t_data.get("snippets", {}).items(): + s = Snippet(template_id=template.id, placeholder_key=key, code_content=content) + session.add(s) + + if "expectation" in c_data: + # Clear existing expectations + for ex in chunk.expectations: + session.delete(ex) + session.flush() + + ex = Expectation( + chunk_id=chunk.id, + input=c_data["expectation"]["input"], + output=c_data["expectation"]["output"] + ) + session.add(ex) + + # 4. Seed Problems + logging.info(f"Seeding {len(PROBLEMS)} Java problems...") + for p_data in PROBLEMS: + p_id = get_uuid(f"jav_rst_prob_{p_data['title']}") + problem = session.exec(select(Problem).where(Problem.id == p_id)).first() + + if not problem: + problem = Problem( + id=p_id, + title=p_data["title"], + description=p_data["description"], + difficulty=p_data["difficulty"], + config={"templates": p_data.get("templates", {})} + ) + problem.categories = [get_or_create_category(p_data.get("category", "Java Algorithms"))] + problem.tags = [jav_hallway_tag] + session.add(problem) + else: + # Update existing problem + problem.description = p_data["description"] + problem.difficulty = p_data["difficulty"] + # Update templates in config + config = problem.config or {} + config["templates"] = p_data.get("templates", {}) + problem.config = config + flag_modified(problem, "config") + session.add(problem) + + session.flush() + + if "test_cases" in p_data: + # Clear existing test cases to avoid UniqueViolation + for tc in problem.test_cases: + session.delete(tc) + session.flush() + + for i, tc_data in enumerate(p_data["test_cases"]): + tc_id = get_uuid(f"jav_hallway_tc_{p_data['title']}_{i}") + tc = TestCase( + id=tc_id, + problem_id=p_id, + input=str(tc_data["input"]), + output=str(tc_data["output"]), + is_hidden=tc_data.get("is_hidden", True), + sort_order=i + 1 + ) + session.add(tc) + + session.commit() + logging.info("JAV_HALLWAY JSON-based seeding completed successfully.") + +if __name__ == "__main__": + seed_hallway_java() diff --git a/src/scripts/seeders/seed_lockerroom_java.py b/src/scripts/seeders/seed_lockerroom_java.py new file mode 100644 index 0000000..73999dc --- /dev/null +++ b/src/scripts/seeders/seed_lockerroom_java.py @@ -0,0 +1,224 @@ +import logging +import uuid +import random +import json +import os +from datetime import datetime, timezone +from sqlalchemy import text +from sqlalchemy.orm.attributes import flag_modified +from sqlmodel import Session, select +from infrastructure import engine +from models import ( + Category, Tag, Riddle, Question, Choice, Chunk, ChunkTemplate, Snippet, Expectation, Problem, TestCase +) + +logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s') + +NAMESPACE = uuid.NAMESPACE_DNS + +def get_uuid(name: str) -> uuid.UUID: + """Generate a deterministic UUID based on a string name.""" + return uuid.uuid5(NAMESPACE, name) + +def load_json(filename): + # Base directory for seeding data (one level up from seeders/) + base_path = os.path.join(os.path.dirname(__file__), "..", "data", "java", "lockerroom") + filepath = os.path.join(base_path, filename) + if not os.path.exists(filepath): + logging.warning(f"File not found: {filepath}") + return [] + with open(filepath, "r") as f: + return json.load(f) + +def seed_lockerroom_java(): + if not engine: + logging.error("No database engine found. Skipping seeding.") + return + + # Load data from JSON files + QUESTIONS = load_json("questions.json") + RIDDLES = load_json("riddles.json") + CHUNKS = load_json("chunks.json") + PROBLEMS = load_json("problems.json") + + with Session(engine) as session: + logging.info("Starting JAV_LOCKERROOM JSON-based seeding process...") + + def get_or_create_category(name): + cat_id = get_uuid(f"cat_{name}") + cat = session.exec(select(Category).where(Category.id == cat_id)).first() + if not cat: + cat = session.exec(select(Category).where(Category.name == name)).first() + if not cat: + cat = Category(id=cat_id, name=name) + session.add(cat) + session.commit() + session.refresh(cat) + return cat + + def get_or_create_tag(name): + tag_id = get_uuid(f"tag_{name}") + tag = session.exec(select(Tag).where(Tag.id == tag_id)).first() + if not tag: + tag = session.exec(select(Tag).where(Tag.name == name)).first() + if not tag: + tag = Tag(id=tag_id, name=name) + session.add(tag) + session.commit() + session.refresh(tag) + return tag + + jav_lockerroom_tag = get_or_create_tag("JAV_LOCKERROOM") + java_cat = get_or_create_category("Java") + + # 1. Seed Questions + logging.info(f"Seeding {len(QUESTIONS)} Java questions...") + for q_data in QUESTIONS: + q_id = get_uuid(f"jav_lockerroom_q_{q_data['title']}") + if session.exec(select(Question).where(Question.id == q_id)).first(): + continue + + question = Question( + id=q_id, + title=q_data["title"], + question_text=q_data["text"], + created_at=datetime.now(timezone.utc) + ) + question.tags = [jav_lockerroom_tag] + question.categories = [java_cat] + session.add(question) + session.flush() + + for i, (choice_text, is_correct) in enumerate(q_data["choices"]): + c_id = get_uuid(f"jav_lockerroom_c_{q_data['title']}_{i}") + choice = Choice( + id=c_id, + question_id=question.id, + choice_text=choice_text, + is_correct=is_correct + ) + session.add(choice) + + # 2. Seed Riddles + logging.info(f"Seeding {len(RIDDLES)} Java riddles...") + for i, r_data in enumerate(RIDDLES): + r_id = get_uuid(f"jav_lockerroom_r_{i}") + if session.exec(select(Riddle).where(Riddle.id == r_id)).first(): + continue + + riddle = Riddle( + id=r_id, + riddle_text=r_data["text"], + refer_char=r_data["char"], + refer_index=r_data["index"], + difficulty=r_data["difficulty"] or "Medium", + created_at=datetime.now(timezone.utc) + ) + riddle.tags = [jav_lockerroom_tag] + session.add(riddle) + + # 3. Seed Chunks + logging.info(f"Seeding {len(CHUNKS)} Java chunks...") + for c_data in CHUNKS: + c_id = get_uuid(f"jav_lockerroom_chunk_{c_data['title']}") + chunk = session.exec(select(Chunk).where(Chunk.id == c_id)).first() + if not chunk: + chunk = Chunk( + id=c_id, + title=c_data["title"], + difficulty=c_data["difficulty"], + created_at=datetime.now(timezone.utc) + ) + chunk.categories = [get_or_create_category(c_data.get("category", "Java Basics"))] + chunk.tags = [jav_lockerroom_tag] + session.add(chunk) + session.flush() + else: + # Update basic info + chunk.difficulty = c_data["difficulty"] + # Clear existing templates to re-seed (cascades to snippets) + for t in chunk.templates: + session.delete(t) + session.flush() + + for lang, t_data in c_data["templates"].items(): + template = ChunkTemplate( + chunk_id=chunk.id, + language=lang, + name=t_data["name"], + template_code=t_data["template_code"], + description=t_data.get("description", f"Standard {lang} boilerplate") + ) + session.add(template) + session.flush() + + for key, content in t_data.get("snippets", {}).items(): + s = Snippet(template_id=template.id, placeholder_key=key, code_content=content) + session.add(s) + + if "expectation" in c_data: + # Clear existing expectations + for ex in chunk.expectations: + session.delete(ex) + session.flush() + + ex = Expectation( + chunk_id=chunk.id, + input=c_data["expectation"]["input"], + output=c_data["expectation"]["output"] + ) + session.add(ex) + + # 4. Seed Problems + logging.info(f"Seeding {len(PROBLEMS)} Java problems...") + for p_data in PROBLEMS: + p_id = get_uuid(f"jav_rst_prob_{p_data['title']}") + problem = session.exec(select(Problem).where(Problem.id == p_id)).first() + + if not problem: + problem = Problem( + id=p_id, + title=p_data["title"], + description=p_data["description"], + difficulty=p_data["difficulty"], + config={"templates": p_data.get("templates", {})} + ) + problem.categories = [get_or_create_category(p_data.get("category", "Java Algorithms"))] + problem.tags = [jav_lockerroom_tag] + session.add(problem) + else: + # Update existing problem + problem.description = p_data["description"] + problem.difficulty = p_data["difficulty"] + # Update templates in config + config = problem.config or {} + config["templates"] = p_data.get("templates", {}) + problem.config = config + flag_modified(problem, "config") + session.add(problem) + + session.flush() + + if "test_cases" in p_data: + # Clear existing test cases to avoid UniqueViolation + for tc in problem.test_cases: + session.delete(tc) + session.flush() + + for i, tc_data in enumerate(p_data["test_cases"]): + tc_id = get_uuid(f"jav_lockerroom_tc_{p_data['title']}_{i}") + tc = TestCase( + id=tc_id, + problem_id=p_id, + input=str(tc_data["input"]), + output=str(tc_data["output"]), + is_hidden=tc_data.get("is_hidden", True), + sort_order=i + 1 + ) + session.add(tc) + + session.commit() + logging.info("JAV_LOCKERROOM JSON-based seeding completed successfully.") + +if __name__ == "__main__": + seed_lockerroom_java() diff --git a/src/scripts/seeders/seed_restroom_java.py b/src/scripts/seeders/seed_restroom_java.py new file mode 100644 index 0000000..38d993a --- /dev/null +++ b/src/scripts/seeders/seed_restroom_java.py @@ -0,0 +1,225 @@ +import logging +import uuid +import random +import json +import os +from datetime import datetime, timezone +from sqlalchemy import text +from sqlalchemy.orm.attributes import flag_modified +from sqlmodel import Session, select +from tqdm import tqdm +from infrastructure import engine +from models import ( + Category, Tag, Riddle, Question, Choice, Chunk, ChunkTemplate, Snippet, Expectation, Problem, TestCase +) + +logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s') + +NAMESPACE = uuid.NAMESPACE_DNS + +def get_uuid(name: str) -> uuid.UUID: + """Generate a deterministic UUID based on a string name.""" + return uuid.uuid5(NAMESPACE, name) + +def load_json(filename): + # Base directory for seeding data (one level up from seeders/) + base_path = os.path.join(os.path.dirname(__file__), "..", "data", "java", "restroom") + filepath = os.path.join(base_path, filename) + if not os.path.exists(filepath): + logging.warning(f"File not found: {filepath}") + return [] + with open(filepath, "r") as f: + return json.load(f) + +def seed_restroom_java(): + if not engine: + logging.error("No database engine found. Skipping seeding.") + return + + # Load data from JSON files + QUESTIONS = load_json("questions.json") + RIDDLES = load_json("riddles.json") + CHUNKS = load_json("chunks.json") + PROBLEMS = load_json("problems.json") + + with Session(engine) as session: + logging.info("Starting JAV_RESTROOM JSON-based seeding process...") + + def get_or_create_category(name): + cat_id = get_uuid(f"cat_{name}") + cat = session.exec(select(Category).where(Category.id == cat_id)).first() + if not cat: + cat = session.exec(select(Category).where(Category.name == name)).first() + if not cat: + cat = Category(id=cat_id, name=name) + session.add(cat) + session.commit() + session.refresh(cat) + return cat + + def get_or_create_tag(name): + tag_id = get_uuid(f"tag_{name}") + tag = session.exec(select(Tag).where(Tag.id == tag_id)).first() + if not tag: + tag = session.exec(select(Tag).where(Tag.name == name)).first() + if not tag: + tag = Tag(id=tag_id, name=name) + session.add(tag) + session.commit() + session.refresh(tag) + return tag + + jav_restroom_tag = get_or_create_tag("JAV_RESTROOM") + java_cat = get_or_create_category("Java") + + # 1. Seed Questions + logging.info(f"Seeding {len(QUESTIONS)} Java questions...") + for q_data in QUESTIONS: + q_id = get_uuid(f"jav_rst_q_{q_data['title']}") + if session.exec(select(Question).where(Question.id == q_id)).first(): + continue + + question = Question( + id=q_id, + title=q_data["title"], + question_text=q_data["text"], + created_at=datetime.now(timezone.utc) + ) + question.tags = [jav_restroom_tag] + question.categories = [java_cat] + session.add(question) + session.flush() + + for i, (choice_text, is_correct) in enumerate(q_data["choices"]): + c_id = get_uuid(f"jav_rst_c_{q_data['title']}_{i}") + choice = Choice( + id=c_id, + question_id=question.id, + choice_text=choice_text, + is_correct=is_correct + ) + session.add(choice) + + # 2. Seed Riddles + logging.info(f"Seeding {len(RIDDLES)} Java riddles...") + for i, r_data in enumerate(RIDDLES): + r_id = get_uuid(f"jav_rst_r_{i}") + if session.exec(select(Riddle).where(Riddle.id == r_id)).first(): + continue + + riddle = Riddle( + id=r_id, + riddle_text=r_data["text"], + refer_char=r_data["char"], + refer_index=r_data["index"], + difficulty=r_data["difficulty"] or "Medium", + created_at=datetime.now(timezone.utc) + ) + riddle.tags = [jav_restroom_tag] + session.add(riddle) + + # 3. Seed Chunks + logging.info(f"Seeding {len(CHUNKS)} Java chunks...") + for c_data in CHUNKS: + c_id = get_uuid(f"jav_rst_chunk_{c_data['title']}") + chunk = session.exec(select(Chunk).where(Chunk.id == c_id)).first() + if not chunk: + chunk = Chunk( + id=c_id, + title=c_data["title"], + difficulty=c_data["difficulty"], + created_at=datetime.now(timezone.utc) + ) + chunk.categories = [get_or_create_category(c_data.get("category", "Java Basics"))] + chunk.tags = [jav_restroom_tag] + session.add(chunk) + session.flush() + else: + # Update basic info + chunk.difficulty = c_data["difficulty"] + # Clear existing templates to re-seed (cascades to snippets) + for t in chunk.templates: + session.delete(t) + session.flush() + + for lang, t_data in c_data["templates"].items(): + template = ChunkTemplate( + chunk_id=chunk.id, + language=lang, + name=t_data["name"], + template_code=t_data["template_code"], + description=t_data.get("description", f"Standard {lang} boilerplate") + ) + session.add(template) + session.flush() + + for key, content in t_data.get("snippets", {}).items(): + s = Snippet(template_id=template.id, placeholder_key=key, code_content=content) + session.add(s) + + if "expectation" in c_data: + # Clear existing expectations + for ex in chunk.expectations: + session.delete(ex) + session.flush() + + ex = Expectation( + chunk_id=chunk.id, + input=c_data["expectation"]["input"], + output=c_data["expectation"]["output"] + ) + session.add(ex) + + # 4. Seed Problems + logging.info(f"Seeding {len(PROBLEMS)} Java problems...") + for p_data in PROBLEMS: + p_id = get_uuid(f"jav_rst_prob_{p_data['title']}") + problem = session.exec(select(Problem).where(Problem.id == p_id)).first() + + if not problem: + problem = Problem( + id=p_id, + title=p_data["title"], + description=p_data["description"], + difficulty=p_data["difficulty"], + config={"templates": p_data.get("templates", {})} + ) + problem.categories = [get_or_create_category(p_data.get("category", "Java Algorithms"))] + problem.tags = [jav_restroom_tag] + session.add(problem) + else: + # Update existing problem + problem.description = p_data["description"] + problem.difficulty = p_data["difficulty"] + # Update templates in config + config = problem.config or {} + config["templates"] = p_data.get("templates", {}) + problem.config = config + flag_modified(problem, "config") + session.add(problem) + + session.flush() + + if "test_cases" in p_data: + # Clear existing test cases to avoid UniqueViolation + for tc in problem.test_cases: + session.delete(tc) + session.flush() + + for i, tc_data in enumerate(p_data["test_cases"]): + tc_id = get_uuid(f"jav_rst_tc_{p_data['title']}_{i}") + tc = TestCase( + id=tc_id, + problem_id=p_id, + input=str(tc_data["input"]), + output=str(tc_data["output"]), + is_hidden=tc_data.get("is_hidden", True), + sort_order=i + 1 + ) + session.add(tc) + + session.commit() + logging.info("JAV_RESTROOM JSON-based seeding completed successfully.") + +if __name__ == "__main__": + seed_restroom_java() diff --git a/src/services/__init__.py b/src/services/__init__.py index 6afa995..689ddec 100644 --- a/src/services/__init__.py +++ b/src/services/__init__.py @@ -3,3 +3,4 @@ from .random_service import RandomService from .question_service import QuestionService from .riddle_service import RiddleService +from .chunk_service import ChunkService diff --git a/src/services/chunk_service.py b/src/services/chunk_service.py new file mode 100644 index 0000000..0dd2824 --- /dev/null +++ b/src/services/chunk_service.py @@ -0,0 +1,55 @@ +import re +from repositories.chunk_repository import ChunkRepository + +class ChunkService: + def __init__(self): + self.repo = ChunkRepository() + + def _process_chunk(self, chunk): + + if not chunk: + return None + + cmt_map = { + "python": "# TODO: {} here", + "c": "// TODO: {} here", + "cpp": "// TODO: {} here", + "java": "// TODO: {} here", + "default": "// TODO: {} here" + } + + templates = chunk.get("config", {}).get("templates", {}) + for lang, t_dict in templates.items(): + cmt_pat = cmt_map.get(lang.lower(), cmt_map["default"]) + tc = t_dict.get("template_code") + if tc: + processed = re.sub( + r'\{{3}\s*(\w+)\s*\}{3}', + lambda m: f"\n{cmt_pat.format(m.group(1))}\n", + tc + ) + t_dict["template_code"] = [line for line in processed.split('\n') if line] + + # Transform snippets dict into parallel arrays + snippets_dict = t_dict.get("snippets", {}) + if isinstance(snippets_dict, dict): + keys = list(snippets_dict.keys()) + values = [snippets_dict[k] for k in keys] + t_dict["snippets"] = keys + t_dict["code_content"] = values + + return chunk + + def get_all_chunks(self, page=1, limit=10, lang=None): + chunks = self.repo.find_all(page=page, limit=limit, lang=lang) + return [self._process_chunk(c) for c in chunks] + + def get_chunk(self, chunk_id, lang=None): + chunk = self.repo.get_details(chunk_id, lang=lang) + if chunk: + return self._process_chunk(chunk) + return None + + def get_random_chunks(self, limit=1, lang=None): + chunks = self.repo.find_random(limit=limit, lang=lang) + return [self._process_chunk(c) for c in chunks] diff --git a/src/services/question_service.py b/src/services/question_service.py index d3a0e61..c4ccdf0 100644 --- a/src/services/question_service.py +++ b/src/services/question_service.py @@ -106,15 +106,25 @@ def update_choice(self, choice_id: str, update_data: dict): def get_random_questions(self, tag_name: str, amount: int = 1): """Fetch N random questions by tag.""" + questions = self.question_repo.find_random_by_tag(tag_name, amount) return [ { "id": str(q.id), "title": q.title, "question_text": q.question_text, - "tags": [t.name for t in q.tags] + "choices": [ + { + "id": str(c.id), + "choice_text": c.choice_text, + "is_correct": c.is_correct + } for c in q.choices + ], + "tags": [t.name for t in q.tags], + "categories": [c.name for c in q.categories] } for q in questions ] + def list_all_questions(self, page: int = 1, page_size: int = 10): """List questions with pagination and metadata.""" import math diff --git a/src/verify_fix.py b/src/verify_fix.py new file mode 100644 index 0000000..abb7eed --- /dev/null +++ b/src/verify_fix.py @@ -0,0 +1,50 @@ + +import sys +import os +from uuid import UUID + +# Add src to path +sys.path.append(os.path.dirname(os.path.abspath(__file__))) + +from services.question_service import QuestionService +from repositories.question_repository import QuestionRepository +from models.base import Question, Tag, Choice +from infrastructure import SessionLocal + +def verify(): + service = QuestionService() + + # Try to find a tag to test with + with SessionLocal() as session: + tag = session.query(Tag).first() + if not tag: + print("No tags found in database. Cannot run verification. Please seed the database first.") + return + tag_name = tag.name + print(f"Testing with tag: {tag_name}") + + try: + results = service.get_random_questions(tag_name, amount=1) + print("Success! get_random_questions executed without DetachedInstanceError.") + print(f"Results: {results}") + + # Verify structure + if results: + q = results[0] + if 'choices' in q and isinstance(q['choices'], list): + print(f"Verified: 'choices' is a list with {len(q['choices'])} items.") + else: + print("Error: 'choices' is missing or not a list in the response.") + + if 'tags' in q and isinstance(q['tags'], list): + print(f"Verified: 'tags' is a list with {len(q['tags'])} items.") + + if 'categories' in q and isinstance(q['categories'], list): + print(f"Verified: 'categories' is a list with {len(q['categories'])} items.") + except Exception as e: + print(f"Failed: {type(e).__name__}: {e}") + import traceback + traceback.print_exc() + +if __name__ == "__main__": + verify() diff --git a/tests/conftest.py b/tests/conftest.py index 940f04e..1cd7bd6 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -21,7 +21,11 @@ import pytest +# If running in Docker, the app root IS /usr/src/app, but tests expect src/ +# If src/ doesn't exist, we add the current directory to path. SRC_DIR = os.path.join(os.path.dirname(__file__), '..', 'src') +if not os.path.exists(SRC_DIR): + SRC_DIR = os.path.join(os.path.dirname(__file__), '..') sys.path.insert(0, os.path.abspath(SRC_DIR)) @@ -38,10 +42,11 @@ repos_mock = MagicMock() sys.modules.setdefault('repositories', repos_mock) sys.modules.setdefault('repositories.problem_repository', repos_mock) -sys.modules.setdefault('repositories.testcase_repository', repos_mock) +sys.modules.setdefault('repositories.test_case_repository', repos_mock) sys.modules.setdefault('repositories.question_repository', repos_mock) sys.modules.setdefault('repositories.choice_repository', repos_mock) sys.modules.setdefault('repositories.riddle_repository', repos_mock) +sys.modules.setdefault('repositories.chunk_repository', repos_mock) # Mock scripts (seed, etc.) sys.modules.setdefault('scripts', MagicMock())