diff --git a/.gitignore b/.gitignore
index cbf62b7..b4f38d7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,3 @@
# Claude Code settings
.claude/
-.vscode/
\ No newline at end of file
+.vscode
\ No newline at end of file
diff --git a/submissions/week-1/dmgaye96/tetris.html b/submissions/week-1/dmgaye96/tetris.html
index a635b99..409e537 100644
--- a/submissions/week-1/dmgaye96/tetris.html
+++ b/submissions/week-1/dmgaye96/tetris.html
@@ -2,293 +2,587 @@
-Colorful Tetris
+
+🎮 Tetris
-
Tetris
-
-
- Controls:
- ← / → – Move left / right
- ↑ – Rotate
- ↓ – Soft drop
- Space – Hard drop
- P – Pause / Resume
- R – Restart game
-
-
-
+
+
+
+
Score
+
0
+
+
+
Level
+
1
+
+
+
Lines
+
0
+
+
+
Next
+
+
+
+ ←→ Move
+ ↑ Rotate
+ ↓ Soft Drop
+ Space Hard Drop
+ P Pause
+
+
-
- Score: 0 | Level: 1
+
+
+
+
🎮 TETRIS
+
Classic block-stacking game
+
+
+
+
⏸ PAUSED
+
+
+
+
💥 GAME OVER
+
Final Score: 0
+
+
+
+
+
diff --git a/submissions/week-1/okhaleel/NOTES.md b/submissions/week-1/okhaleel/NOTES.md
new file mode 100644
index 0000000..b070185
--- /dev/null
+++ b/submissions/week-1/okhaleel/NOTES.md
@@ -0,0 +1,24 @@
+# Week 1 Notes — [OKHALEEL]
+
+## Hardware
+- **Device type:** (UNICEF standard laptop - Gen5 Intel(R) Core(TM) Ultra 7 155U (1.70 GHz))
+- **RAM:** 32GB
+- **GPU / AI acceleration:** Standard/built-in GPU
+- **OS:** Windows 11 24H2
+
+## Setup
+- **Inference engine used:** LM Studio
+- **Model used:** qwen3.6-35b-a3b
+- **Time to get running (approx):** 29m
+
+## Experience
+- **What worked well:** The setup and the generation of a working/runnable single HTML file from the first attempt.
+- **What was harder than expected:** Addressing perforamce issues
+- **Did you hit any blockers? How did you resolve them:** I noticed some commands/syntax needed correction, so I updated them. I also tried different setups to explore the impact on performance. LMS with Qwen-35b 29m and the file worked fine 4.8 t/s, Qwen-9b 27m (but the game did not run), Gemma-4-12B-QAT 58m 2.7 t/s game ran but not functioning correctly.
+I also tried some CPU/GPU tweakings such as numbre of GPU offload layers, set processor affinity but did not noticed much difference.
+Researched why the NPU was not utilized.. the understanding I got was that tools such as LMS, llama.cpp, Ollama have no NPU support, they only use CPU/GPU. NPU works with specific models such as OpenVINO, ONNX Runtime, and Intel NPU SDK. It activates only for specific AI workloads, not general use. Also that NPU advantage is efficiency (battery/heat) not performance, so it is NOT faster than GPU for LLMs.
+
+## Observations for the Assessment
+- **Would you recommend this setup to a colleague on the same hardware? Why / why not:** yes, but higher specs would be better
+- **Any use cases this hardware/model combo seems well-suited for:** Basic apps, generating scripts
+- **Any use cases it clearly won't handle:** Large development, Advanced Apps
\ No newline at end of file
diff --git a/submissions/week-1/okhaleel/TM Perf Gemma.jpg b/submissions/week-1/okhaleel/TM Perf Gemma.jpg
new file mode 100644
index 0000000..5f60810
Binary files /dev/null and b/submissions/week-1/okhaleel/TM Perf Gemma.jpg differ
diff --git a/submissions/week-1/okhaleel/TM Perf qwen35b.jpg b/submissions/week-1/okhaleel/TM Perf qwen35b.jpg
new file mode 100644
index 0000000..7efd9ac
Binary files /dev/null and b/submissions/week-1/okhaleel/TM Perf qwen35b.jpg differ
diff --git a/submissions/week-1/okhaleel/opencode finished.jpg b/submissions/week-1/okhaleel/opencode finished.jpg
new file mode 100644
index 0000000..b782cdf
Binary files /dev/null and b/submissions/week-1/okhaleel/opencode finished.jpg differ
diff --git a/submissions/week-1/okhaleel/tetris running 2.jpg b/submissions/week-1/okhaleel/tetris running 2.jpg
new file mode 100644
index 0000000..9a918e9
Binary files /dev/null and b/submissions/week-1/okhaleel/tetris running 2.jpg differ
diff --git a/submissions/week-1/okhaleel/tetris.html b/submissions/week-1/okhaleel/tetris.html
new file mode 100644
index 0000000..53f8a58
--- /dev/null
+++ b/submissions/week-1/okhaleel/tetris.html
@@ -0,0 +1,513 @@
+
+
+
+
+
+Tetris
+
+
+
+
+
+
+
Next
+
+
+
+
Score
+
0
+
+
+
Level
+
1
+
+
+
Lines
+
0
+
+
+
+
+
+
TETRIS
+
Classic block game
+
+
+
+
+
+
Controls
+ ←→ Move
+ ↑ Rotate
+ ↓ Soft Drop
+ Space Hard Drop
+ P Pause
+ Esc Quit
+
+
+
+
+
+
+
diff --git a/submissions/week-2/DiegoPICT/.gitignore b/submissions/week-2/DiegoPICT/.gitignore
new file mode 100644
index 0000000..d0af62e
--- /dev/null
+++ b/submissions/week-2/DiegoPICT/.gitignore
@@ -0,0 +1,3 @@
+.venv
+data/
+__pycache__/
diff --git a/submissions/week-2/DiegoPICT/NOTES.md b/submissions/week-2/DiegoPICT/NOTES.md
new file mode 100644
index 0000000..c788d73
--- /dev/null
+++ b/submissions/week-2/DiegoPICT/NOTES.md
@@ -0,0 +1,23 @@
+# Week 2 Notes — DiegoPICT
+
+## Setup
+- **IDE used:** VS Code + WSL
+- **AI coding extension / tool:** Pi Coding Agent (terminal-based) with local model backends via Unsloth Studio and LM Studio
+- **Model used:** Gemma 4 12B and Qwen 3.6 27B (combined workflow)
+- **Any configuration changes from Week 1:** Moved from single-file flow to a web-hosted Flask app structure (`templates/` + `static/`) with persistent score storage and LAN access testing from other devices.
+
+## Features Added
+1. Added a persistent leaderboard backed by TinyDB, exposed via `GET /api/scores` and `POST /api/scores`.
+2. Added post-game score submission UI (name input + submit action + confirmation state), with leaderboard auto-refresh.
+3. Added welcome screen + game entry flow and high-score preview on the landing page.
+4. Enabled hosted local gameplay so the app can be played from other devices on my home LAN.
+
+## Experience
+- **How did working in an IDE differ from chat UI in Week 1:** IDE workflow was faster and more practical for full implementation because I could iterate code, run server, inspect logs, and test browser behavior in one place.
+- **What the local model did well in this workflow:** Gemma 4 12B (Unsloth Studio) generated a working baseline web-hosted app on first try; overall model assistance was strong for scaffolding, wiring endpoints, and quick UI integration.
+- **Where it fell short or needed manual correction:** Pi Coding Agent timed out multiple times and required manual retries; Gemma 12B frequently struggled with tool calling (wrong/failed command generation for file edits and related actions), especially during longer sessions.
+- **Estimated time spent with AI assistance vs. manual editing:** ~70% AI-assisted, ~30% manual retries, debugging, and cleanup.
+
+## Observations for the Assessment
+- **Is IDE-connected local AI a viable daily coding workflow on your hardware? Why / why not:** Yes, with caveats. It is viable and productive, but reliability depends heavily on model size/capability and tool-calling stability at local inference speeds.
+- **Compared to cloud AI coding tools you've used (if any) — what's the practical gap:** Local setup gives better control/privacy and excellent responsiveness for simple tasks, but cloud tools are generally more consistent on complex multi-step tool use. Practical takeaway: a hybrid local strategy worked best here (small model for quick edits, larger model fallback when tool calling repeatedly fails).
diff --git a/submissions/week-2/DiegoPICT/README.md b/submissions/week-2/DiegoPICT/README.md
new file mode 100644
index 0000000..4a1e6a6
--- /dev/null
+++ b/submissions/week-2/DiegoPICT/README.md
@@ -0,0 +1,59 @@
+# Neon Tetris
+
+A retro-inspired, neon-themed Tetris game built with HTML5 Canvas and served via a Python backend.
+
+## Overview
+Neon Tetris is a web-based implementation of the classic block-stacking puzzle game. It features a vibrant "Neon" aesthetic, smooth gameplay mechanics, and is designed to be served as a web application with a centralized scoreboard and a themed landing experience.
+
+## Features
+- **Core Gameplay:** Full Tetris mechanics including rotation, line clearing, and hard drops.
+- **Neon Aesthetic:** High-contrast visuals with glowing effects and a dark theme.
+- **Responsive Controls:** Support for both Arrow keys and WASD.
+- **Welcome Screen:** A themed landing page to introduce the game.
+- **Scoreboard:** A persistent leaderboard to track and display high scores.
+
+## Tech Stack
+- **Frontend:** HTML5, CSS3, JavaScript (Canvas API).
+- **Backend:** Python (Flask/FastAPI) to serve the application and manage scoreboard data.
+
+## Getting Started
+
+### Prerequisites
+- Python 3.x
+- pip (Python package manager)
+
+### Installation
+1. Clone the repository:
+ ```bash
+ git clone
+ cd tetris
+ ```
+2. Create a virtual environment:
+ ```bash
+ python -m venv venv
+ source venv/bin/activate # On Windows: venv\Scripts\activate
+ ```
+3. Install dependencies:
+ ```bash
+ pip install -r requirements.txt
+ ```
+
+### Running the Game
+To start the server:
+```bash
+python main.py
+```
+The game will be available at `http://0.0.0.0:5000`.
+
+## Project Structure
+- `main.py`: Python backend server.
+- `static/`: Contains CSS and JS assets.
+- `templates/`: Contains HTML templates (Welcome screen, Game screen).
+- `requirements.txt`: Python dependencies.
+
+## Roadmap
+- [ ] Migrate standalone `tetris.html` into a template-based structure.
+- [ ] Create the Neon-themed Welcome Screen.
+- [ ] Implement a persistent Scoreboard (SQLite or JSON-based).
+- [ ] Add "Ghost Piece" preview.
+- [ ] Implement dynamic difficulty (speed scaling).
diff --git a/submissions/week-2/DiegoPICT/SCOREBOARD.md b/submissions/week-2/DiegoPICT/SCOREBOARD.md
new file mode 100644
index 0000000..fd2ff71
--- /dev/null
+++ b/submissions/week-2/DiegoPICT/SCOREBOARD.md
@@ -0,0 +1,62 @@
+# Scoreboard Implementation Plan
+
+This document outlines the plan for implementing a persistent scoreboard in the Neon Tetris game.
+
+## Coding Principles
+- Less Code is More
+- Simple UI with consistent theme
+- Is Mobile-aware, when mobile in portrait is detected, it suggest landscape
+- Dont bloat, bandaid, if you get in trouble stop/ask.
+
+## Objectives
+- Allow players to submit their scores when the game ends.
+- Suggest a random fun default short player name from a randomized list in the savegame json - this is to make the UI as simple and unobtrusive as possible desktop/mobile
+- Persist scores across server restarts.
+- Display a leaderboard of high scores to players.
+- Maintain the "Neon" aesthetic in the scoreboard UI.
+- Ultra simplified UI
+
+## Implementation Plan
+
+### 1. Data Storage (JSON-based)
+For the initial implementation, we will use a simple JSON file to store scores. This avoids the overhead of a full database while providing persistence.
+- **File:** `data/scores.json`
+- **Structure:**
+ ```json
+ {
+ "scores": [],
+ "default_names": ["Arthur", "Ford", "Zaphod", "Trillian", "Marvin", "Slartibartle", "Heart", "Beeblebrox"]
+ }
+ ```
+
+### 2. Backend API (Flask)
+We will add two new routes to `main.py`:
+- **GET `/api/scores`**: Returns the top 10 scores from the JSON file.
+- **POST `/api/scores`**: Receives a JSON object containing the player's name and score, validates the input, then appends it to the file (sorted by score descending).
+
+### 3. Frontend Integration (JavaScript)
+We will update `static/js/game.js` to:
+- **Fetch Scores:** Call the `/api/scores` endpoint when the game page loads and display the results.
+- **Submit Score:** When `gameOver` is true, show an input field for the player's name and a "Submit" button.
+- **Handle Submission:** Use `fetch()` to send the name and score to the `/api/scores` endpoint and then refresh the leaderboard.
+
+### 4. UI/UX Enhancements
+- **Leaderboard Component:** Create a new section in `templates/game.html` to display the scores.
+- **Styling:** Use the existing neon theme (cyan accents, dark background) for the scoreboard container.
+- **Animations:** Add a slight fade-in effect when the leaderboard is updated.
+
+## Roadmap Checklist
+- [x] Create `data/scores.json` and basic schema.
+- [x] Implement `GET /api/scores` in `main.py`.
+- [x] Implement `POST /api/scores` in `main.py`.
+- [ ] Update `game.js` to fetch and display scores on load.
+- [ ] Add "Game Over" score submission UI to `game.html`.
+- [ ] Connect "Submit" button to the backend API.
+- [ ] Style the leaderboard to match the Neon theme.
+- [x] Add scoreboard to homepage (`templates/index.html`).
+
+## Recent Progress
+- Initialized `data/scores.json` with Douglas Adams character names.
+- Created `save_controller.py` using `tinydb` for score management.
+- Implemented `/api/scores` endpoints in `main.py`.
+- Added scoreboard display and auto-loading logic to `templates/index.html`.
diff --git a/submissions/week-2/DiegoPICT/main.py b/submissions/week-2/DiegoPICT/main.py
new file mode 100644
index 0000000..100336a
--- /dev/null
+++ b/submissions/week-2/DiegoPICT/main.py
@@ -0,0 +1,78 @@
+import logging
+import traceback
+from flask import Flask, render_template, request, jsonify
+from save_controller import SaveController
+
+app = Flask(__name__)
+app.logger.setLevel(logging.DEBUG)
+handler = logging.StreamHandler()
+handler.setLevel(logging.DEBUG)
+formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+handler.setFormatter(formatter)
+app.logger.addHandler(handler)
+save_controller = SaveController()
+
+@app.after_request
+def add_cors_headers(response):
+ response.headers['Access-Control-Allow-Origin'] = '*'
+ response.headers['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS'
+ response.headers['Access-Control-Allow-Headers'] = 'Content-Type'
+ return response
+
+@app.route('/')
+def index():
+ # Serve the welcome screen at the root URL
+ return render_template('index.html')
+
+@app.route('/game')
+def game():
+ default_names = save_controller.get_default_names()
+ return render_template('game.html', default_names=default_names)
+
+@app.route('/api/scores', methods=['GET'])
+def get_scores():
+ scores = save_controller.get_top_scores(limit=10)
+ # Strip TinyDB internal _id fields from response
+ clean = [{"name": s["name"], "score": s["score"], "date": s.get("date", "")} for s in scores]
+ return jsonify({"scores": clean})
+
+@app.route('/api/scores', methods=['POST'])
+def post_score():
+ try:
+ # Log raw request details for debugging
+ app.logger.info(f"[SCORE] Content-Type: {request.content_type}")
+ app.logger.info(f"[SCORE] Raw data: {request.get_data(as_text=True)}")
+
+ data = request.json
+
+ if data is None:
+ app.logger.warning("[SCORE] request.json returned None (not valid JSON)")
+ return jsonify({"error": "Invalid or missing JSON body"}), 400
+
+ app.logger.info(f"[SCORE] Parsed JSON type: {type(data).__name__}, value: {data}")
+
+ if not isinstance(data, dict):
+ app.logger.error(f"[SCORE] Expected a JSON object (dict) but got {type(data).__name__}: {data}")
+ return jsonify({"error": f"Expected JSON object, got {type(data).__name__}"}), 400
+
+ name = (data.get('name') or '').strip()
+ score = data.get('score')
+
+ app.logger.info(f"[SCORE] Extracted -> name='{name}', score={score} (type: {type(score).__name__ if score is not None else 'None'})")
+
+ if not name or score is None:
+ app.logger.warning(f"[SCORE] Validation failed: name='{name}', score={score}")
+ return jsonify({"error": "Missing name or score"}), 400
+
+ int_score = int(score)
+ app.logger.info(f"[SCORE] Inserting into DB -> name='{name}', score={int_score}")
+ save_controller.add_score(name, int_score)
+ app.logger.info(f"[SCORE] Score saved successfully for '{name}'")
+ return jsonify({"status": "success"}), 201
+ except Exception as e:
+ app.logger.error(f"[SCORE] Unhandled exception: {e}\n{traceback.format_exc()}")
+ return jsonify({"error": str(e)}), 500
+
+if __name__ == '__main__':
+ # Run the app on 0.0.0.0:5000
+ app.run(host='0.0.0.0', port=5000, debug=True)
diff --git a/submissions/week-2/DiegoPICT/requirements.txt b/submissions/week-2/DiegoPICT/requirements.txt
new file mode 100644
index 0000000..adc5fe4
--- /dev/null
+++ b/submissions/week-2/DiegoPICT/requirements.txt
@@ -0,0 +1,2 @@
+Flask==3.0.3
+tinydb
diff --git a/submissions/week-2/DiegoPICT/save_controller.py b/submissions/week-2/DiegoPICT/save_controller.py
new file mode 100644
index 0000000..451fb9b
--- /dev/null
+++ b/submissions/week-2/DiegoPICT/save_controller.py
@@ -0,0 +1,41 @@
+import logging
+from tinydb import TinyDB, Query
+from datetime import datetime
+
+logger = logging.getLogger(__name__)
+logger.setLevel(logging.DEBUG)
+
+class SaveController:
+ def __init__(self, db_path='data/scores.json'):
+ self.db = TinyDB(db_path)
+ self.scores = self.db.table('scores')
+ self.config = self.db.table('config')
+
+ # Initialize config if it doesn't exist
+ if not self.config.all():
+ self.config.insert({'default_names': [
+ "Arthur", "Ford", "Zaphod", "Trillian",
+ "Marvin", "Slartibartle", "Heart", "Beeblebrox"
+ ]})
+
+ def get_top_scores(self, limit=10):
+ all_scores = self.scores.all()
+ sorted_scores = sorted(all_scores, key=lambda x: x['score'], reverse=True)
+ return sorted_scores[:limit]
+
+ def add_score(self, name, score):
+ new_score = {
+ "name": name,
+ "score": int(score),
+ "date": datetime.now().strftime("%Y-%m-%d")
+ }
+ logger.info(f"[DB] Inserting score: {new_score}")
+ doc_id = self.scores.insert(new_score)
+ logger.info(f"[DB] Score inserted with doc_id={doc_id}")
+ return True
+
+ def get_default_names(self):
+ docs = self.config.all()
+ if not docs:
+ return []
+ return docs[0].get('default_names', [])
diff --git a/submissions/week-2/DiegoPICT/static/css/style.css b/submissions/week-2/DiegoPICT/static/css/style.css
new file mode 100644
index 0000000..34f7852
--- /dev/null
+++ b/submissions/week-2/DiegoPICT/static/css/style.css
@@ -0,0 +1,167 @@
+/*
+ * Neon Tetris Styles
+ */
+:root {
+ --bg-color: #0a0a0c;
+ --panel-color: #1a1a2e;
+ --text-color: #e0e0e0;
+ --accent-color: #00f2ff;
+}
+
+body {
+ background-color: var(--bg-color);
+ color: var(--text-color);
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ height: 100vh;
+ margin: 0;
+ overflow: hidden;
+}
+
+.game-container {
+ display: flex;
+ gap: 20px;
+ padding: 20px;
+ border: 2px solid var(--accent-color);
+ border-radius: 10px;
+ background: var(--panel-color);
+ box-shadow: 0 0 20px rgba(0, 242, 255, 0.2);
+}
+
+canvas {
+ border: 2px solid #333;
+ background-color: #000;
+ box-shadow: inset 0 0 10px #000;
+}
+
+.stats-side {
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ min-width: 150px;
+}
+
+.stat-box {
+ background: rgba(0, 0, 0, 0.3);
+ padding: 15px;
+ border-radius: 8px;
+ border-left: 4px solid var(--accent-color);
+}
+
+h1 {
+ margin: 0 0 10px 0;
+ font-size: 1.5rem;
+ text-transform: uppercase;
+ letter-spacing: 2px;
+ color: var(--accent-color);
+ text-shadow: 0 0 10px rgba(0, 242, 255, 0.5);
+}
+
+.controls-hint {
+ margin-top: 20px;
+ font-size: 0.8rem;
+ color: #888;
+ text-align: center;
+}
+
+#game-over {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ background: rgba(0, 0, 0, 0.9);
+ padding: 40px;
+ border: 2px solid red;
+ text-align: center;
+ display: none;
+ z-index: 10;
+}
+
+button {
+ background: var(--accent-color);
+ border: none;
+ padding: 10px 20px;
+ font-weight: bold;
+ cursor: pointer;
+ border-radius: 5px;
+ margin-top: 10px;
+}
+
+button.secondary-btn {
+ background: #444;
+}
+
+/* Submit Score Form */
+.submit-score-container {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 10px;
+ margin-top: 20px;
+}
+
+#player-name {
+ padding: 10px;
+ border-radius: 5px;
+ border: 1px solid var(--accent-color);
+ background: #000;
+ color: white;
+ text-align: center;
+ width: 200px;
+ font-size: 1rem;
+}
+
+#player-name:focus {
+ outline: none;
+ box-shadow: 0 0 8px rgba(0, 242, 255, 0.5);
+}
+
+/* Leaderboard */
+.leaderboard-container {
+ margin-top: 30px;
+ text-align: center;
+ width: 300px;
+}
+
+.leaderboard-container h3 {
+ color: var(--accent-color);
+ letter-spacing: 2px;
+ font-size: 1rem;
+ margin-bottom: 10px;
+ text-shadow: 0 0 8px rgba(0, 242, 255, 0.4);
+}
+
+#leaderboard-list {
+ display: flex;
+ flex-direction: column;
+ gap: 4px;
+}
+
+.leaderboard-entry {
+ background: var(--panel-color);
+ padding: 8px 12px;
+ border-radius: 5px;
+ border-left: 3px solid var(--accent-color);
+ display: flex;
+ justify-content: space-between;
+ font-size: 0.9rem;
+}
+
+.leaderboard-entry .rank {
+ color: #888;
+ min-width: 25px;
+}
+
+.leaderboard-entry .name {
+ flex-grow: 1;
+ text-align: left;
+ padding-left: 8px;
+}
+
+.leaderboard-entry .score-val {
+ color: var(--accent-color);
+ font-weight: bold;
+}
diff --git a/submissions/week-2/DiegoPICT/static/js/game.js b/submissions/week-2/DiegoPICT/static/js/game.js
new file mode 100644
index 0000000..a3d38af
--- /dev/null
+++ b/submissions/week-2/DiegoPICT/static/js/game.js
@@ -0,0 +1,378 @@
+const canvas = document.getElementById('tetris');
+const context = canvas.getContext('2d');
+const scoreElement = document.getElementById('score');
+const linesElement = document.getElementById('lines');
+
+context.scale(20, 20);
+
+// Piece shapes
+function createPiece(type) {
+ if (type === 'I') {
+ return [
+ [0, 1, 0, 0],
+ [0, 1, 0, 0],
+ [0, 1, 0, 0],
+ [0, 1, 0, 0],
+ ];
+ } else if (type === 'L') {
+ return [
+ [0, 2, 0],
+ [0, 2, 0],
+ [0, 2, 2],
+ ];
+ } else if (type === 'J') {
+ return [
+ [0, 3, 0],
+ [0, 3, 0],
+ [3, 3, 0],
+ ];
+ } else if (type === 'O') {
+ return [
+ [4, 4],
+ [4, 4],
+ ];
+ } else if (type === 'Z') {
+ return [
+ [5, 5, 0],
+ [0, 5, 5],
+ [0, 0, 0],
+ ];
+ } else if (type === 'S') {
+ return [
+ [0, 6, 6],
+ [6, 6, 0],
+ [0, 0, 0],
+ ];
+ } else if (type === 'T') {
+ return [
+ [0, 7, 0],
+ [7, 7, 7],
+ [0, 0, 0],
+ ];
+ }
+}
+
+// Colors for the pieces
+const colors = [
+ null,
+ '#00f2ff', // I - Cyan
+ '#ff9d00', // L - Orange
+ '#3d5afe', // J - Blue
+ '#ffff00', // O - Yellow
+ '#ff0066', // Z - Pink/Red
+ '#00ff66', // S - Green
+ '#9c27b0', // T - Purple
+];
+
+function createMatrix(w, h) {
+ const matrix = [];
+ while (h--) {
+ matrix.push(new Array(w).fill(0));
+ }
+ return matrix;
+}
+
+function draw() {
+ // Fill background
+ context.fillStyle = '#000';
+ context.fillRect(0, 0, canvas.width, canvas.height);
+
+ drawMatrix(arena, {x: 0, y: 0});
+ drawMatrix(player.matrix, player.pos);
+}
+
+function drawMatrix(matrix, offset) {
+ matrix.forEach((row, y) => {
+ row.forEach((value, x) => {
+ if (value !== 0) {
+ // Block body
+ context.fillStyle = colors[value];
+ context.fillRect(x + offset.x, y + offset.y, 1, 1);
+
+ // Block border/glow
+ context.strokeStyle = 'rgba(255,255,255,0.5)';
+ context.lineWidth = 0.05;
+ context.strokeRect(x + offset.x, y + offset.y, 1, 1);
+ }
+ });
+ });
+}
+
+function merge(arena, player) {
+ player.matrix.forEach((row, y) => {
+ row.forEach((value, x) => {
+ if (value !== 0) {
+ arena[y + player.pos.y][x + player.pos.x] = value;
+ }
+ });
+ });
+}
+
+function rotate(matrix, dir) {
+ for (let y = 0; y < matrix.length; ++y) {
+ for (let x = 0; x < y; ++x) {
+ [
+ matrix[x][y],
+ matrix[y][x],
+ ] = [
+ matrix[y][x],
+ matrix[x][y],
+ ];
+ }
+ }
+ if (dir > 0) {
+ matrix.forEach(row => row.reverse());
+ } else {
+ matrix.reverse();
+ }
+}
+
+function playerDrop() {
+ player.pos.y++;
+ if (collide(arena, player)) {
+ player.pos.y--;
+ merge(arena, player);
+ playerReset();
+ arenaSweep();
+ updateScore();
+ }
+ dropCounter = 0;
+}
+
+function playerMove(dir) {
+ player.pos.x += dir;
+ if (collide(arena, player)) {
+ player.pos.x -= dir;
+ }
+}
+
+function playerReset() {
+ const pieces = 'TJLOSIZ';
+ player.matrix = createPiece(pieces[pieces.length * Math.random() | 0]);
+ player.pos.y = 0;
+ player.pos.x = (arena[0].length / 2 | 0) -
+ (player.matrix[0].length / 2 | 0);
+
+ if (collide(arena, player)) {
+ // Game Over
+ document.getElementById('game-over').style.display = 'block';
+ document.getElementById('final-score').innerText = score;
+ gameOver = true;
+ // Reset form state: show input form, hide confirm message
+ document.getElementById('score-form').style.display = 'flex';
+ document.getElementById('score-confirm').style.display = 'none';
+ setRandomDefaultName();
+ }
+}
+
+function playerRotate(dir) {
+ const pos = player.pos.x;
+ let offset = 1;
+ rotate(player.matrix, dir);
+ while (collide(arena, player)) {
+ player.pos.x += offset;
+ offset = -(offset + (offset > 0 ? 1 : -1));
+ if (offset > player.matrix[0].length) {
+ rotate(player.matrix, -dir);
+ player.pos.x = pos;
+ return;
+ }
+ }
+}
+
+function collide(arena, player) {
+ const [m, o] = [player.matrix, player.pos];
+ for (let y = 0; y < m.length; ++y) {
+ for (let x = 0; x < m[y].length; ++x) {
+ if (m[y][x] !== 0 &&
+ (arena[y + o.y] && arena[y + o.y][x + o.x]) !== 0) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+function arenaSweep() {
+ let rowCount = 1;
+ outer: for (let y = arena.length - 1; y > 0; --y) {
+ for (let x = 0; x < arena[y].length; ++x) {
+ if (arena[y][x] === 0) {
+ continue outer;
+ }
+ }
+ const row = arena.splice(y, 1)[0].fill(0);
+ arena.unshift(row);
+ ++y;
+
+ score += rowCount * 10;
+ lines += 1;
+ rowCount *= 2;
+ }
+}
+
+function updateScore() {
+ scoreElement.innerText = score;
+ linesElement.innerText = lines;
+}
+
+function resetGame() {
+ arena.forEach(row => row.fill(0));
+ score = 0;
+ lines = 0;
+ gameOver = false;
+ document.getElementById('game-over').style.display = 'none';
+ updateScore();
+ playerReset();
+ update();
+}
+
+let dropCounter = 0;
+let dropInterval = 1000;
+let lastTime = 0;
+let score = 0;
+let lines = 0;
+let gameOver = false;
+
+function update(time = 0) {
+ if (gameOver) return;
+
+ const deltaTime = time - lastTime;
+ lastTime = time;
+
+ dropCounter += deltaTime;
+ if (dropCounter > dropInterval) {
+ playerDrop();
+ }
+
+ draw();
+ requestAnimationFrame(update);
+}
+
+const arena = createMatrix(12, 20);
+
+const player = {
+ pos: {x: 0, y: 0},
+ matrix: null,
+};
+
+// Controls
+document.addEventListener('keydown', event => {
+ if (gameOver) return;
+
+ if (event.keyCode === 37 || event.keyCode === 65) { // Left or A
+ playerMove(-1);
+ } else if (event.keyCode === 39 || event.keyCode === 68) { // Right or D
+ playerMove(1);
+ } else if (event.keyCode === 40 || event.keyCode === 87) { // Down or W
+ playerDrop();
+ } else if (event.keyCode === 38 || event.keyCode === 81 || event.keyCode === 83) { // Up, Q, or S (Rotate)
+ playerRotate(1);
+ } else if (event.keyCode === 32) { // Space (Hard Drop)
+ while(!collide(arena, player)) {
+ player.pos.y++;
+ }
+ player.pos.y--;
+ merge(arena, player);
+ playerReset();
+ arenaSweep();
+ updateScore();
+ }
+});
+
+// --- Scoreboard / Leaderboard Logic ---
+
+const DEFAULT_NAMES = window.DEFAULT_NAMES || ['Arthur', 'Ford', 'Zaphod', 'Trillian', 'Marvin'];
+
+function setRandomDefaultName() {
+ const input = document.getElementById('player-name');
+ const btn = document.getElementById('submit-score-btn');
+ input.value = DEFAULT_NAMES[Math.floor(Math.random() * DEFAULT_NAMES.length)];
+ btn.textContent = 'SUBMIT SCORE';
+ btn.disabled = false;
+}
+
+async function loadLeaderboard() {
+ try {
+ const res = await fetch('/api/scores');
+ const data = await res.json();
+ const list = document.getElementById('leaderboard-list');
+ list.innerHTML = '';
+ data.scores.forEach((entry, index) => {
+ const div = document.createElement('div');
+ div.className = 'leaderboard-entry';
+ div.innerHTML = `
+ #${index + 1}
+ ${escapeHtml(entry.name)}
+ ${entry.score.toLocaleString()}
+ `;
+ list.appendChild(div);
+ });
+ } catch (err) {
+ console.error('Failed to load leaderboard:', err);
+ }
+}
+
+function escapeHtml(text) {
+ const div = document.createElement('div');
+ div.textContent = text;
+ return div.innerHTML;
+}
+
+async function submitScore() {
+ const nameInput = document.getElementById('player-name');
+ const btn = document.getElementById('submit-score-btn');
+ const scoreForm = document.getElementById('score-form');
+ const scoreConfirm = document.getElementById('score-confirm');
+ const name = nameInput.value.trim();
+
+ if (!name) {
+ alert('Please enter your name!');
+ return;
+ }
+
+ btn.disabled = true;
+ btn.textContent = 'SUBMITTING...';
+
+ try {
+ const res = await fetch('/api/scores', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ name, score })
+ });
+
+ if (res.ok) {
+ // Hide the entire form, show confirmation
+ scoreForm.style.display = 'none';
+ scoreConfirm.style.display = 'block';
+ loadLeaderboard(); // Refresh leaderboard
+ } else {
+ const errData = await res.json().catch(() => ({}));
+ alert('Failed to submit score: ' + (errData.error || 'Unknown error'));
+ btn.disabled = false;
+ btn.textContent = 'SUBMIT SCORE';
+ }
+ } catch (err) {
+ console.error('Submit error:', err);
+ alert('Error submitting score.');
+ btn.disabled = false;
+ btn.textContent = 'SUBMIT SCORE';
+ }
+}
+
+// Bind submit button
+document.getElementById('submit-score-btn').addEventListener('click', submitScore);
+
+// Allow pressing Enter in the name input to submit
+document.getElementById('player-name').addEventListener('keydown', (e) => {
+ if (e.key === 'Enter') submitScore();
+});
+
+// Load leaderboard on page load
+loadLeaderboard();
+
+// --- End Scoreboard Logic ---
+
+playerReset();
+updateScore();
+update();
diff --git a/submissions/week-2/DiegoPICT/templates/game.html b/submissions/week-2/DiegoPICT/templates/game.html
new file mode 100644
index 0000000..26faa3a
--- /dev/null
+++ b/submissions/week-2/DiegoPICT/templates/game.html
@@ -0,0 +1,60 @@
+
+
+
+
+
+ Neon Tetris
+
+
+
+
+
Neon Tetris
+
+
+
+
+
+
+
+
SCORE
+
0
+
+
+
+
LINES
+
0
+
+
+
+ WASD / Arrows to Move
+ Up / Q / W to Rotate
+ Space to Drop
+
+ WASD / Arrows to Move
+ Up / Q / W to Rotate
+ Space to Drop
+
+
+
+
+
+
GAME OVER
+
Final Score: 0
+
+
+
+
Use Arrow Keys or WASD to play
+
+
+
+
diff --git a/submissions/week-2/dgaye96/NOTES.md b/submissions/week-2/dgaye96/NOTES.md
new file mode 100644
index 0000000..125caea
--- /dev/null
+++ b/submissions/week-2/dgaye96/NOTES.md
@@ -0,0 +1,27 @@
+# Week 2 Notes — [dgaye96]
+
+## Setup
+- **IDE used:** VS Code
+- **AI coding extension / tool:** Continue / Open code
+- **Model used:** qwen/qwen3.6-35b-a3b
+- **Any configuration changes from Week 1:** For this week I used LLM Studio as Inference Engines
+
+## Features Added
+1. Son / Effets sonores
+2. Hard drop
+
+
+## Experience
+- **How did working in an IDE differ from chat UI in Week 1:** Code generation was faster on the chat UI than on the IDE for Tetris, but I tested generating React code, and the result was incredible
+- **What the local model did well in this workflow:** The local template handled the creation of a new React project well, but it turned out to be a bit slow when it came to adding features to Tetris
+- **Where it fell short or needed manual correction:** I did not make any manual corrections; the model occasionally made automatic corrections
+- **Estimated time spent with AI assistance vs. manual editing:** AI assistance is better
+
+## Observations for the Assessm
+- **Is IDE-connected local AI a viable daily coding workflow on your hardware? Why / why not:** With more RAM (for example, 64 GB or 128 GB), this can provide a viable day-to-day work environment for development.
+- **Compared to cloud AI coding tools you've used (if any) — what's the practical gap:** This delay corresponds to the time it takes for the local AI model to generate the code; it is faster to correct it in the cloud than to do so locally.
+
+## Validation
+
+- 👍 Validated — Enhanced Tetris runs, at least two new features visible, generated with local model + IDE
+
diff --git a/submissions/week-2/dgaye96/tetris.html b/submissions/week-2/dgaye96/tetris.html
new file mode 100644
index 0000000..ee318d1
--- /dev/null
+++ b/submissions/week-2/dgaye96/tetris.html
@@ -0,0 +1,493 @@
+
+
+
+
+
+Tetris
+
+
+
+
+
+
+
+
Next
+
+
+
+
Score
+
0
+
+
+
Level
+
1
+
+
+
Lines
+
0
+
+
+
+
+ ←→ move ↑ rotate
+ ↓ soft Space hard drop
+
+
+
+
+
+
diff --git a/submissions/week-2/okhaleel/NOTES.md b/submissions/week-2/okhaleel/NOTES.md
new file mode 100644
index 0000000..ee37841
--- /dev/null
+++ b/submissions/week-2/okhaleel/NOTES.md
@@ -0,0 +1,45 @@
+\# Week 2 Notes — OKHALEEL
+
+
+
+\## Setup
+
+\- \*\*IDE used:\*\* VS Code
+
+\- \*\*AI coding extension / tool:\*\* Coding Agents (Zoo Code, Cline, and Continue) connected to LLMs via (LM Studio, Ollama, llama.cpp)
+
+\- \*\*Model used:\*\* Tested both Gemma-4 12B and Qwen-3.6 27B
+
+\- \*\*Any configuration changes from Week 1:\*\* The idea was to use the working code I got from week1 and enhance it with more functions/UI.
+
+
+
+\## Features Added (tried to add, but did not work so far)
+
+* A welcome landing page with Play button
+* Select a player name
+* Option to save the score
+* Show a leaderboard with top scores
+
+
+
+\## Experience
+
+\- \*\*How did working in an IDE differ from chat UI in Week 1:\*\* It is easier to work with, provides better capabilities, and allows user to test and refine.
+
+\- \*\*What the local model did well in this workflow:\*\* When tested with Qwen-27B, it was very slow about 1 tok/s. Gemma-4 12B was better with about 2.4 tok/s but still times out and could not finish the requested updates.
+
+\- \*\*Where it fell short or needed manual correction:\*\* The performance was not accepted as I waited for several hours in some cases, but the generation process stopped suddenly. I was able to fix some errors related to the cnx window, tried a lot of different combinations in settings such as context windows, threads, GPU offloads, etc..
+
+What I noticed is that most of the time-outs happen when the agent started editing the existing html file or creating a new file, so part of my troubleshooting was confirming the access permissions (IDE and agent), for example: added a yaml file called permissions with Read (\*) and Write (\*)
+
+\- \*\*Estimated time spent with AI assistance vs. manual editing:\*\* 90% troubleshooting and trying different options/settings.
+
+
+
+\## Observations for the Assessment
+
+\- \*\*Is IDE-connected local AI a viable daily coding workflow on your hardware? Why / why not:\*\* No, it did not work for me. very very slow, and unstable.
+
+\- \*\*Compared to cloud AI coding tools you've used (if any) — what's the practical gap:\*\* Of course privacy and cost saving are the main advantages for local coding, but it is limited to small/simple tasks. Cloud tools are much faster, mature, and gives more predictable results.
+