Files
2026-04-12 18:58:03 +09:00

294 lines
20 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ⚡ Test Project: Module A — Speed Test
## 1. Project Overview
This assessment is a **Speed Test** designed to quickly and accurately evaluate practical proficiency across web technologies. Competitors must complete a total of 20 independent tasks across four categories — **A (Design)**, **B (Layout)**, **C (Frontend)**, and **D (Backend)** — within the allotted time. Each task is independent and may be attempted in any order.
---
## 2. Tech Stack & Constraints
| Category | Allowed Technologies | Restrictions |
| :--- | :--- | :--- |
| **A. Design** | GIMP | No other image editors (e.g., Photoshop) permitted |
| **B. Layout** | HTML, CSS | JavaScript is not permitted |
| **C. Frontend** | JavaScript (Vanilla) | No external libraries or frameworks permitted |
| **D. Backend** | PHP, MySQL | Database must be connected using PDO |
* All deliverables will be evaluated in a desktop Chrome browser.
* Save each task's deliverable in a subdirectory named after the task ID under `/module_a/`. (e.g., `/module_a/a1/`, `/module_a/b1/`)
* Design tasks must include the GIMP source file (`.xcf`) in the submission directory.
---
## 3. Tasks
### 🎨 A. Design — GIMP Proficiency
> **Provided files**: Files for A1 (`source.png`), A2 (`base.jpg`), and A3 (`photo.jpg`, `mask.png`) are pre-placed in each task's working directory. A4 and A5 have no provided files; competitors must create all assets from scratch.
#### **A1. Layer Compositing and Text Placement** `Easy`
Create an image in GIMP using a layered structure.
* Canvas size: **800×400px**, Resolution: **72dpi**
* **Layer 1**: Fill the background with the solid color `#2C3E50`.
* **Layer 2**: Open the provided image (`source.png`), place it at the **center** of the canvas, and set its opacity to **70%**.
* **Layer 3**: Add the text **"Hello, GIMP"** in white (`#FFFFFF`) at 36pt, and position it at the top-left of the canvas **(x: 20px, y: 20px)**.
* Save the project as a `.xcf` file first. Then flatten all layers (Flatten Image) and export the result as `result.png`.
#### **A2. Selection and Layer Compositing** `Easy`
Apply shape effects to an image using GIMP's selection tools and layers.
* Open the provided image (`base.jpg`) as the background layer.
* **Effect 1**: Add a new layer. Use the Rectangle Select tool to select the region from **(0, 0) to (200, 200)** in the top-left corner, fill it with `#E74C3C`, and set this layer's opacity to **60%**.
* **Effect 2**: Add another new layer. Create an elliptical selection with a diameter of **150px** at the **center** of the image. Go to `Selection → Border`, set the border width to **3px**, and fill the resulting selection with `#FFFFFF`.
* Save the project as a `.xcf` file first. Then flatten all layers (Flatten Image) and export the result as `result.jpg`.
#### **A3. Color Correction and Layer Mask** `Normal`
Apply color correction and a layer mask to the provided image (`photo.jpg`) in GIMP.
* **Color correction**: Use the Hue-Saturation tool to increase Saturation by **+40**.
* **Curves adjustment**: Use the Curves tool to raise the output value of highlights by **+20 or more** and lower the output value of shadows by **-20 or less** to increase contrast.
* **Layer mask**: Add a layer mask to the image layer. Paste the provided mask image (`mask.png`) into the mask layer so that the background outside the subject is removed.
* Save the project as a `.xcf` file first. Then export the result as `result.png`, ensuring the transparent background is preserved (PNG format).
#### **A4. Text Effect and Glow** `Normal`
Apply a glow visual effect to text in GIMP.
* Canvas size: **600×200px**, Background color: `#1A1A2E`
* Add the text **"SPEED TEST"** in white (`#FFFFFF`), Bold, 60pt, centered on the canvas.
* Duplicate the text layer and place the duplicate **below** the original text layer.
* Rasterize the duplicate layer (Layer → Rasterize). In the Layers panel, set the duplicate layer's **Mode** to **`Color`** first. Then set the foreground color to `#4A90D9` and apply `Edit → Fill with Foreground Color` so the blue color is applied.
* Apply **Gaussian Blur** with a radius of **8px** to the duplicate layer to complete the outer glow effect.
* Save the project as a `.xcf` file first, then export the result as `result.png`.
#### **A5. Text Warp and Filter Effects** `Hard`
Rasterize text and apply a combination of Distorts filters in GIMP to create visual distortion effects.
* Canvas size: **800×300px**, Background color: `#0D0D0D`
* Add the text **"DISTORTION"** in white (`#FFFFFF`), Bold, 72pt, centered on the canvas.
* Rasterize the text layer (Layer → Rasterize).
* Apply the following two Distorts filters to the rasterized text layer in order:
* **Ripple**: Amplitude **8**, Wavelength **40**, Orientation: Horizontal
* **Whirl and Pinch**: Whirl angle **20** degrees, Pinch **0**, Radius **1.0**
* Duplicate the distorted text layer. Apply **Gaussian Blur** with a radius of **3px** to the duplicate, then place the duplicate **below** the original layer to create a ghosting effect.
* Save the project as a `.xcf` file first, then export the result as `result.png`.
---
### 📐 B. Layout — HTML / CSS Only
#### **B1. Flexbox Card Layout** `Easy`
Build a card list layout using HTML and CSS only.
* Use **Flexbox** to arrange cards **4 per row**. (Use `flex-wrap: wrap`)
* Each card must contain: an image area (`<div>`, height **160px**, with a background color), a title (`<h3>`), body text (`<p>`), and a button (`<button>`).
* Set the gap between cards to **24px**.
* Create **8** dummy cards. Each card's image area must have a different background color.
#### **B2. Sticky Header and CSS Interaction** `Easy`
Build a header with CSS-only interactions using HTML and CSS only.
* Use **Flexbox** to arrange the header with a logo text on the left, 4 menu links in the center, and 2 buttons on the right.
* Implement a CSS-only interaction where hovering over a menu link reveals a **2px solid underline** with a `transition` effect. (Use `border-bottom` or a `::after` pseudo-element)
* Use `position: sticky; top: 0;` to keep the header fixed at the top while scrolling.
* Place dummy content with a minimum height of **3000px** below the header to enable scrolling.
#### **B3. CSS Grid Two-Column Layout** `Normal`
Build a two-column page layout using CSS Grid with HTML and CSS only.
* Use **CSS Grid** to create a layout with a fixed left sidebar (**250px**) and a right main content area (`1fr`).
* Place a vertical navigation menu (5 items) in the left sidebar. Style the first item to indicate an active state using background color and text color.
* Place a title, body text, and a **3-column card grid** (using CSS Grid, 6 cards) in sequence in the right main area.
* Apply `height: 100vh` and `overflow: hidden` to the layout wrapper. Apply `height: 100vh` and `overflow-y: auto` to both the sidebar and the main area so that each scrolls independently.
#### **B4. CSS Animations and Transitions** `Normal`
Implement various CSS animations and transition effects on a single page using HTML and CSS only.
* **Card hover effect**: Arrange 4 cards in a row using Flexbox. On hover, each card should move up **8px** and have a stronger shadow using a transition. (Use `transform: translateY(-8px)`, `box-shadow`, and `transition`)
* **Loading spinner**: Use `@keyframes` to create a circular loading spinner. The spinner should be **48px** in diameter with a **4px** border. Only the top border (`border-top`) should be colored `#3498DB`; the remaining borders should be `#e0e0e0`. The spinner rotates infinitely.
* **Fade-in text**: On page load, a heading (`<h1>`) should animate from `translateY(20px)` to `translateY(0)` while fading from `opacity: 0` to `opacity: 1` using `@keyframes`. (`animation-duration: 0.8s`, `animation-fill-mode: both`)
#### **B5. CSS Grid and Advanced Selectors** `Hard`
Build a two-column content layout with a CSS-only tab interaction using HTML and CSS only.
* Use **CSS Grid** to create a two-column layout: left column (65%) and right column (35%).
* **Left area**: Place a main image area (`<div>`, height **300px**, with a background color) and a horizontal thumbnail list below it (Flexbox, `overflow-x: auto`). Include **5** thumbnails, each as an **80×80px** `<div>` with a different background color.
* **Right area — upper**: Place a title, subtitle, and body text.
* **Right area — lower**: Implement 3 tabs (Overview / Details / Reviews) with their respective content areas.
* Use `<input type="radio" name="tab">` and the CSS `:checked` selector **without JavaScript** so that only the selected tab's content is shown.
* Hide the `<input type="radio">` elements with `display: none` and style the corresponding `<label>` elements to look like tab buttons.
* At the bottom of the right area, place a Primary button and a Secondary button side by side. Apply a `@keyframes` animation to the Primary button so its background color transitions smoothly on hover.
---
### ⚡ C. Frontend — JavaScript (Vanilla)
#### **C1. localStorage-based Memo App** `Easy`
Build a simple memo app using Vanilla JavaScript and `localStorage`.
* The page must include a text input (`<textarea>`) and a **"Save"** button.
* Clicking **"Save"** adds the memo to a JSON array stored under the `memos` key in `localStorage`. Empty content must not be saved.
* Render the saved memo list below the input area. Each item must include the memo content and a **"Delete"** button.
* Clicking **"Delete"** removes the item from `localStorage` and immediately updates the rendered list.
* The memo list must persist after a page refresh.
#### **C2. DOM Manipulation and Event Handling** `Easy`
Build a dynamic list with item management using Vanilla JavaScript.
* The page must include a text input (`<input type="text">`) and an **"Add"** button.
* Clicking **"Add"** or pressing Enter adds the input value as a new list item. Empty values must not be added. The input field is cleared after adding.
* Each item must include a **"Done"** button and a **"Delete"** button.
* Clicking **"Done"** applies a strikethrough (`text-decoration: line-through`) to the item text. Clicking again toggles it back.
* Clicking **"Delete"** removes the item immediately.
* Display the current **total item count** and **completed item count** at the top of the list in real time.
#### **C3. Dynamic JSON Rendering and Filtering** `Normal`
Build a page that fetches a local JSON file and dynamically renders its content using Vanilla JavaScript and the Fetch API.
* Fetch the provided `posts.json` file at `/module_a/c3/posts.json` using the Fetch API. The file contains an array of objects with the keys `id`, `title`, `body`, and `category`. (20 items total)
* Display a **loading spinner** (CSS animation) while fetching, and remove it when the fetch completes.
* Render all items as cards. Each card must display `id`, `title`, `body`, and `category`.
* Implement a search input that filters cards in real time by `title`. (Case-insensitive; updates immediately on each keystroke)
* If the Fetch request fails, display the error message **"Failed to load data."** on the screen.
> **Provided file**: `posts.json` (pre-placed in the competitor's working directory at `/module_a/c3/`)
#### **C4. Form Validation** `Normal`
Implement real-time form validation using Vanilla JavaScript.
* Build a registration form with the following fields: **Name**, **Email**, **Password**, **Confirm Password**
* Validation rules for each field:
* **Name**: Required, at least 2 characters
* **Email**: Required, must contain both `@` and `.`
* **Password**: Required, at least 8 characters, must contain both letters and numbers
* **Confirm Password**: Required, must match the Password field exactly
* When focus leaves a field (`blur` event), display an error message below that field if the validation rule is not met. Remove the error message immediately once the condition is satisfied.
* The **"Submit"** button must only be enabled when all fields are valid. Clicking it should trigger `alert("Registration complete.")`.
#### **C5. IntersectionObserver and Deferred Rendering** `Hard`
Implement infinite scroll and deferred rendering using `IntersectionObserver`.
* Define an array of 50 dummy items in JavaScript. Each item must have `id`, `title`, and `color`. (`color` is an arbitrary hex color value in `#RRGGBB` format)
* On initial load, render **10** items. Each item consists of a **200px-tall** color `<div>` and its `title` text. The first 10 items should display their `color` value as the background color immediately.
* Place a **sentinel element** (`<div id="sentinel">`) at the bottom of the list. When the sentinel enters the viewport, automatically render the next 10 items.
* While new items are being added, insert a **loading spinner element** directly before the sentinel to display it, and remove it once rendering is complete. (Simulate async behavior using `setTimeout` with 600ms)
* Once all **50 items** have been rendered, stop observing the sentinel (`observer.unobserve`) and display the message **"All items loaded."**
* New items should be added to the DOM with their color `<div>` initially set to `#cccccc` (grey). Use a **separate `IntersectionObserver` instance** to watch each `<div>`, and replace the background color with the real color from the element's `data-color` attribute the moment it enters the viewport.
---
### 🛢️ D. Backend — PHP / MySQL
> **Provided files**: `posts_dump.sql` for D4 and `data_dump.sql` for D5 are pre-placed in each task's working directory.
#### **D1. PDO-based CRUD API** `Easy`
Build a REST API to handle data using PHP and MySQL (PDO).
* Create an `items` table using the structure below. Submit the table creation SQL as `table.sql`.
* `id` (INT, PK, AUTO_INCREMENT), `title` (VARCHAR 100, NOT NULL), `content` (TEXT), `created_at` (TIMESTAMP DEFAULT CURRENT_TIMESTAMP)
* Implement the following 4 endpoints in a single file `api.php`, branching by HTTP method (`$_SERVER['REQUEST_METHOD']`).
* `GET /module_a/d1/api.php` → Return all items as a JSON array
* `POST /module_a/d1/api.php` → Add a new item. Body (JSON): `{"title": "...", "content": "..."}`. Read the request body using `php://input` and parse it with `json_decode()`. On success, return the inserted row as JSON.
* `PUT /module_a/d1/api.php?id={id}` → Update `title` and `content`. Body (JSON): `{"title": "...", "content": "..."}`. Read the request body using `php://input` and parse it with `json_decode()`. On success, return the updated row as JSON.
* `DELETE /module_a/d1/api.php?id={id}` → Delete the item. On success, return `{"message": "deleted"}`.
* For PUT/DELETE requests with a non-existent `id`, return HTTP status **404** and `{"error": "Not found"}`.
* All responses must include a `Content-Type: application/json` header.
#### **D2. File Upload Handling** `Easy`
Implement image file upload functionality using PHP.
* In `upload.php`, implement both a file upload HTML form (GET) and the upload processing logic (POST). Set the form's `enctype` to `multipart/form-data`.
* Upload conditions: only **jpg, jpeg, png, gif** extensions are allowed; file size must be **2MB or less**.
* Save files that pass validation to the `uploads/` directory using the naming format **`{time()}_{original_filename}`**. If the `uploads/` directory does not exist, create it manually.
* On successful upload, display the uploaded image using an `<img>` tag.
* For validation failures, display the appropriate error message:
* Invalid extension: **"File type not allowed."**
* Size exceeded: **"File size exceeds 2MB."**
#### **D3. Session-based Authentication System** `Normal`
Implement user registration, login, and logout using PHP sessions and MySQL.
* `users` table: `id` (INT, PK, AUTO_INCREMENT), `email` (VARCHAR 100, UNIQUE), `password` (VARCHAR 255), `name` (VARCHAR 50), `created_at` (TIMESTAMP DEFAULT CURRENT_TIMESTAMP)
* **`register.php`**: On GET, render an HTML registration form. On POST, check for duplicate emails and save the password hashed with `password_hash()`, then redirect immediately to `login.php` without displaying a success message. If the email is already in use, display the error **"This email is already registered."** above the form.
* **`login.php`**: On GET, render an HTML login form. On POST, verify the password with `password_verify()`. On success, store `user_id`, `name`, and `email` in the session and redirect to `mypage.php`. On failure, display the error **"Incorrect email or password."** above the form.
* **`logout.php`**: On GET, destroy the session with `session_destroy()` and redirect to `login.php`.
* **`mypage.php`**: If `user_id` is not in the session, redirect to `login.php`. If logged in, display the message **"Welcome, {name}!"** and a logout link.
#### **D4. Pagination** `Normal`
Implement server-side pagination using PHP and MySQL (PDO).
* Create the `posts` table yourself, then import the provided SQL dump (`posts_dump.sql`). Table structure: `id`, `title`, `content`, `created_at`
* In `index.php`, display **10 posts per page**.
* The current page is determined by the URL query string `?page={n}`, defaulting to 1. Use `LIMIT` and `OFFSET` in your SQL query to retrieve only the data for the current page. If `page` is less than 1 or exceeds the total number of pages, redirect to page 1.
* Display pagination links at the bottom of the page. **Show all page numbers**, highlight the current page with an active style, and include Previous/Next buttons. Disable the Previous button on the first page and the Next button on the last page.
* Each post item must show the title and registration date. Clicking the title navigates to `view.php?id={id}`, which displays the full content of that post.
#### **D5. Multi-table Aggregate Queries** `Hard`
Implement a statistics API using multi-table JOINs and aggregate queries.
* Create all 3 tables yourself, then import the provided SQL dump (`data_dump.sql`). **Tables must be created in the order `users` → `posts` → `comments`** (to satisfy foreign key dependencies).
* `users` (`id`, `name`, `created_at`)
* `posts` (`id`, `user_id` — references users.id, `title`, `category`, `view_count`, `created_at`)
* `comments` (`id`, `post_id` — references posts.id, `created_at`)
* In a single file `stats.php`, branch on the `type` query string and return the following 3 responses:
* `GET /module_a/d5/stats.php?type=daily` → Return the number of new posts per day for the past 7 days, sorted by date ascending. Response format: `[{"date": "2026-04-06", "count": 5}, ...]`
* `GET /module_a/d5/stats.php?type=category` → Return the total post count and average view count per category, sorted by post count descending. Response format: `[{"category": "tech", "post_count": 12, "avg_views": 340}, ...]`
* `GET /module_a/d5/stats.php?type=top` → Return the top 5 posts by comment count, sorted by comment count descending. Response format: `[{"post_id": 3, "title": "...", "author": "Alice Johnson", "comment_count": 18}, ...]`
* All queries must use PDO **Prepared Statements**.
* For unknown `type` values, return HTTP **400** and `{"error": "Invalid type"}`.
---
## 4. Submission Guidelines
Upload all deliverables to the server directory `/module_a/`. Each task's output must be saved in a subdirectory named after the task ID. (e.g., `/module_a/a1/`, `/module_a/b1/`, `/module_a/c1/`, `/module_a/d1/`)
---
## 5. Marking Scheme — Total 25 Points
| Category | Task | Points |
| :--- | :--- | :---: |
| **A. Design** | A1. Layer Compositing and Text Placement | 0.5 |
| | A2. Selection and Layer Compositing | 0.5 |
| | A3. Color Correction and Layer Mask | 1.5 |
| | A4. Text Effect and Glow | 1.5 |
| | A5. Text Warp and Filter Effects | 2.0 |
| **B. Layout** | B1. Flexbox Card Layout | 0.5 |
| | B2. Sticky Header and CSS Interaction | 0.5 |
| | B3. CSS Grid Two-Column Layout | 1.5 |
| | B4. CSS Animations and Transitions | 1.5 |
| | B5. CSS Grid and Advanced Selectors | 2.0 |
| **C. Frontend** | C1. localStorage-based Memo App | 0.5 |
| | C2. DOM Manipulation and Event Handling | 0.5 |
| | C3. Dynamic JSON Rendering and Filtering | 1.5 |
| | C4. Form Validation | 1.5 |
| | C5. IntersectionObserver and Deferred Rendering | 2.0 |
| **D. Backend** | D1. PDO-based CRUD API | 0.5 |
| | D2. File Upload Handling | 0.5 |
| | D3. Session-based Authentication System | 1.5 |
| | D4. Pagination | 1.5 |
| | D5. Multi-table Aggregate Queries | 3.0 |
| **Total** | | **25** |