# ⚡ Sinov loyihasi: Modul A — Tezlik testi (Speed Test)

## 1. Loyiha haqida qisqacha ma'lumot

Ushbu baholash veb-texnologiyalar bo'yicha amaliy ko'nikmalarni tez va aniq baholash uchun mo'ljallangan **Tezlik testi** (Speed Test) hisoblanadi. Ishtirokchilar to'rtta toifa — **A (Dizayn)**, **B (Layout)**, **C (Frontend)** va **D (Backend)** bo'yicha jami 20 ta mustaqil topshiriqni belgilangan vaqt ichida bajarishlari kerak. Har bir topshiriq mustaqil bo'lib, ularni istalgan tartibda bajarish mumkin.

---

## 2. Texnologiyalar to'plami (Tech Stack) va cheklovlar

| Toifa | Ruxsat berilgan texnologiyalar | Cheklovlar |
| :--- | :--- | :--- |
| **A. Dizayn** | GIMP | Boshqa grafik tahrirlovchilardan (masalan, Photoshop) foydalanish taqiqlanadi |
| **B. Layout** | HTML, CSS | JavaScript-dan foydalanish taqiqlanadi |
| **C. Frontend** | JavaScript (Vanilla) | Tashqi kutubxonalar yoki freymvorklardan foydalanish taqiqlanadi |
| **D. Backend** | PHP, MySQL | Ma'lumotlar bazasiga ulanish uchun faqat PDO ishlatilishi kerak |

* Barcha natijalar Chrome brauzerining desktop versiyasida tekshiriladi.
* Har bir topshiriq natijasini `/module_a/` papkasi ostidagi topshiriq ID-si bilan nomlangan quyi papkaga saqlang (masalan, `/module_a/a1/`, `/module_a/b1/`).
* Dizayn topshiriqlari uchun GIMP manba fayli (`.xcf`) topshiriladigan papkada bo'lishi shart.

---

## 3. Topshiriqlar

### 🎨 A. Dizayn — GIMP mahorati

> **Taqdim etilgan fayllar**: A1 (`source.png`), A2 (`base.jpg`) va A3 (`photo.jpg`, `mask.png`) uchun fayllar har bir topshiriqning ishchi katalogiga joylashtirilgan. A4 va A5 uchun fayllar taqdim etilmagan; ishtirokchilar barcha elementlarni noldan yaratishlari kerak.

#### **A1. Qatlamlarni birlashtirish va matn joylashtirish** `Oson`

GIMP-da qatlamli tuzilmadan foydalangan holda rasm yarating.

* Kanvas o'lchami: **800×400px**, Ruxsat: **72dpi**
* **1-qatlam**: Fonni `#2C3E50` rangli foni bilan to'ldiring.
* **2-qatlam**: Taqdim etilgan rasmni (`source.png`) oching, uni kanvasning **markaziga** joylashtiring va shaffofligini (opacity) **70%** ga o'rnating.
* **3-qatlam**: **"Hello, GIMP"** matnini oq rangda (`#FFFFFF`), 36pt o'lchamda qo'shing va uni kanvasning yuqori chap burchagiga **(x: 20px, y: 20px)** joylashtiring.
* Loyihani avval `.xcf` formatida saqlang. Keyin barcha qatlamlarni birlashtiring (Flatten Image) va natijani `result.png` sifatida eksport qiling.

#### **A2. Tanlash va qatlamlarni birlashtirish** `Oson`

GIMP-ning tanlash vositalari va qatlamlaridan foydalanib, rasmga shakl effektlarini qo'llang.

* Taqdim etilgan rasmni (`base.jpg`) fon qatlami sifatida oching.
* **1-effekt**: Yangi qatlam qo'shing. "Rectangle Select" (To'rtburchak tanlash) vositasi yordamida yuqori chap burchakdagi **(0, 0) dan (200, 200)** gacha bo'lgan maydonni tanlang, uni `#E74C3C` rang bilan to'ldiring va ushbu qatlamning shaffofligini **60%** ga o'rnating.
* **2-effekt**: Yana bitta yangi qatlam qo'shing. Rasmning **markazida** diametri **150px** bo'lgan elliptik tanlov yarating. `Selection → Border` menyusiga kiring, chegara kengligini **3px** qilib belgilang va hosil bo'lgan tanlovni `#FFFFFF` rangi bilan to'ldiring.
* Loyihani avval `.xcf` formatida saqlang. Keyin barcha qatlamlarni birlashtiring (Flatten Image) va natijani `result.jpg` sifatida eksport qiling.

#### **A3. Rangni to'g'rilash va qatlam maskasi (Layer Mask)** `O'rtacha`

Taqdim etilgan rasmga (`photo.jpg`) rangni to'g'rilash va qatlam maskasini qo'llang.

* **Rangni to'g'rilash**: "Hue-Saturation" vositasidan foydalanib, to'yinganlikni (Saturation) **+40** ga oshiring.
* **Egri chiziqlar (Curves)**: "Curves" vositasidan foydalanib, kontrastni oshirish uchun yorug'lik qiymatini (highlights) **+20 yoki undan ko'proqqa** oshiring va soya qiymatini (shadows) **-20 yoki undan kamroqqa** tushiring.
* **Qatlam maskasi**: Rasm qatlamiga qatlam maskasini qo'shing. Taqdim etilgan maska tasvirini (`mask.png`) qatlam maskasiga joylashtiring, shunda asosiy obyektdan tashqaridagi fon olib tashlanadi.
* Loyihani avval `.xcf` formatida saqlang. Keyin natijani `result.png` sifatida eksport qiling va shaffof fon saqlanib qolganiga ishonch hosil qiling.

#### **A4. Matn effekti va porlash (Glow)** `O'rtacha`

GIMP-da matnga porlash effektini qo'llang.

* Kanvas o'lchami: **600×200px**, Fon rangi: `#1A1A2E`
* **"SPEED TEST"** matnini oq rangda (`#FFFFFF`), qalin (Bold), 60pt o'lchamda kanvas markaziga qo'shing.
* Matn qatlamini nusxalang va nusxasini asl matn qatlamining **ostiga** joylashtiring.
* Nusxalangan qatlamni rasterlang (Layer → Rasterize). Qatlamlar panelida ushbu qatlamning rejimini (Mode) **`Color`** ga o'rnating. Keyin asosiy rangni (foreground) `#4A90D9` ga o'rnating va `Edit → Fill with Foreground Color` orqali ko'k rangni qo'llang.
* Tashqi porlash effektini yakunlash uchun nusxalangan qatlamga **8px** radiusli **Gaussian Blur** filtrini qo'llang.
* Loyihani avval `.xcf` formatida saqlang, so'ngra natijani `result.png` sifatida eksport qiling.

#### **A5. Matnni buzish (Warp) va filtr effektlari** `Qiyin`

Matnni rasterlang va vizual buzilish effektlarini yaratish uchun GIMP-ning "Distorts" filtrlarini qo'llang.

* Kanvas o'lchami: **800×300px**, Fon rangi: `#0D0D0D`
* **"DISTORTION"** matnini oq rangda (`#FFFFFF`), qalin (Bold), 72pt o'lchamda kanvas markaziga qo'shing.
* Matn qatlamini rasterlang (Layer → Rasterize).
* Rasterlangan matn qatlamiga quyidagi ikkita "Distorts" filtrini tartib bilan qo'llang:
  * **Ripple**: Amplituda **8**, To'lqin uzunligi (Wavelength) **40**, Yo'nalish: Horizontal
  * **Whirl and Pinch**: Whirl burchagi **20** daraja, Pinch **0**, Radius **1.0**
* Buzilgan matn qatlamini nusxalang. Nusxaga **3px** radiusli **Gaussian Blur** filtrini qo'llang va "ghosting" (arvohsimon) effektini yaratish uchun uni asl qatlamning **ostiga** joylashtiring.
* Loyihani avval `.xcf` formatida saqlang, so'ngra natijani `result.png` sifatida eksport qiling.

---

### 📐 B. Layout — Faqat HTML / CSS

#### **B1. Flexbox Card Layout** `Oson`

Faqat HTML va CSS yordamida kartalar ro'yxatini yarating.

* Kartalarni har bir qatorda **4 tadan** joylashtirish uchun **Flexbox** dan foydalaning. (`flex-wrap: wrap` ishlating)
* Har bir karta quyidagilarni o'z ichiga olishi kerak: rasm maydoni (`<div>`, balandligi **160px**, fon rangi bilan), sarlavha (`<h3>`), asosiy matn (`<p>`) va tugma (`<button>`).
* Kartalar orasidagi masofani (gap) **24px** qilib belgilang.
* **8 ta** namunaviy (dummy) karta yarating. Har bir kartaning rasm maydoni har xil fon rangiga ega bo'lishi kerak.

#### **B2. Sticky Header va CSS interaksiyasi** `Oson`

Faqat HTML va CSS yordamida CSS interaksiyalariga ega sarlavha (header) yarating.

* Sarlavhani joylashtirish uchun **Flexbox** dan foydalaning: chapda logotip matni, markazda 4 ta menyu havolasi va o'ngda 2 ta tugma.
* Menyu havolasi ustiga kursor olib borilganda (hover), `transition` effekti bilan **2px qalinlikdagi chiziq** paydo bo'ladigan interaksiyani amalga oshiring. (`border-bottom` yoki `::after` psevdo-elementidan foydalaning)
* Sarlavhani skroll paytida yuqorida qotib turishi uchun `position: sticky; top: 0;` dan foydalaning.
* Skroll qilish imkoniyati bo'lishi uchun sarlavha ostiga kamida **3000px** balandlikdagi namunaviy kontent joylashtiring.

#### **B3. CSS Grid Ikki ustunli maket** `O'rtacha`

Faqat HTML va CSS yordamida CSS Grid orqali ikki ustunli sahifa maketini yarating.

* Chap tomonda mahkamlangan sidebar (**250px**) va o'ng tomonda asosiy kontent maydoni (`1fr`) yaratish uchun **CSS Grid** dan foydalaning.
* Chap sidebarga vertikal navigatsiya menyusini (5 ta element) joylashtiring. Birinchi elementni faol holatda ekanligini ko'rsatish uchun fon rangi va matn rangini o'zgartiring.
* O'ngdagi asosiy maydonda tartib bilan sarlavha, matn va **3 ustunli karta setkasi** (CSS Grid yordamida, 6 ta karta) joylashtiring.
* Umumiy o'rovchi elementga (wrapper) `height: 100vh` va `overflow: hidden` qo'llang. Sidebar va asosiy maydonning har biri alohida skroll bo'lishi uchun ikkalasiga ham `height: 100vh` va `overflow-y: auto` xususiyatlarini bering.

#### **B4. CSS Animatsiyalar va Transitionlar** `O'rtacha`

Faqat HTML va CSS yordamida bitta sahifada turli xil CSS animatsiyalari va transition effektlarini amalga oshiring.

* **Karta hover effekti**: Flexbox yordamida qatorga 4 ta karta joylashtiring. Kursor ustiga kelganda, har bir karta **8px** yuqoriga ko'tarilishi va kuchliroq soyaga ega bo'lishi kerak. (`transform: translateY(-8px)`, `box-shadow` va `transition` ishlating)
* **Yuklanish indikatori (Loading spinner)**: `@keyframes` yordamida aylana shaklidagi spinner yarating. Spinner diametri **48px**, chegarasi (border) **4px** bo'lsin. Faqat yuqori chegara (`border-top`) `#3498DB` rangda bo'lishi kerak, qolganlari esa `#e0e0e0`. Spinner cheksiz aylanadi.
* **Matnning paydo bo'lishi (Fade-in)**: Sahifa yuklanganda sarlavha (`<h1>`) `@keyframes` yordamida `translateY(20px)` dan `translateY(0)` holatiga o'tishi va `opacity: 0` dan `opacity: 1` ga o'zgarishi kerak. (`animation-duration: 0.8s`, `animation-fill-mode: both`)

#### **B5. CSS Grid va kengaytirilgan selektorlar** `Qiyin`

Faqat HTML va CSS yordamida ikki ustunli kontent maketini va faqat CSS-da ishlaydigan tab (sahifa) interaksiyasini yarating.

* **CSS Grid** yordamida ikki ustunli maket yarating: chap ustun (65%) va o'ng ustun (35%).
* **Chap maydon**: Asosiy rasm maydonini (`<div>`, balandligi **300px**, fon rangi bilan) va uning ostida gorizontal rasmchalar (thumbnail) ro'yxatini joylashtiring (Flexbox, `overflow-x: auto`). 5 ta rasmcha bo'lsin, har biri **80×80px** o'lchamdagi va turli fon rangli `<div>` bo'lsin.
* **O'ng maydon — yuqori**: Sarlavha, kichik sarlavha va matn joylashtiring.
* **O'ng maydon — quyi**: 3 ta tab (Umumiy ko'rinish / Tafsilotlar / Sharhlar) va ularga tegishli kontent maydonlarini yarating.
  * Faqat tanlangan tab kontentini ko'rsatish uchun **JavaScript-siz** `<input type="radio" name="tab">` va CSS `:checked` selektoridan foydalaning.
  * `<input type="radio">` elementlarini `display: none` bilan yashiring va mos keladigan `<label>` elementlarini tab tugmalari kabi dizayn qiling.
* O'ng maydonning eng pastida yonma-yon "Asosiy" va "Yordamchi" tugmalarni joylashtiring. Asosiy tugma ustiga kursor olib kelganda uning fon rangi silliq o'zgarishi uchun `@keyframes` animatsiyasini qo'llang.

---

### ⚡ C. Frontend — JavaScript (Vanilla)

#### **C1. localStorage asosidagi eslatmalar ilovasi** `Oson`

Vanilla JavaScript va `localStorage` yordamida oddiy eslatma (memo) ilovasini yarating.

* Sahifada matn kiritish maydoni (`<textarea>`) va **"Saqlash"** tugmasi bo'lishi kerak.
* "Saqlash" tugmasi bosilganda, eslatma `localStorage`-dagi `memos` kaliti ostida JSON massiviga qo'shiladi. Bo'sh matnni saqlash mumkin emas.
* Saqlangan eslatmalar ro'yxatini kiritish maydoni ostida ko'rsating. Har bir elementda matn va **"O'chirish"** tugmasi bo'lishi kerak.
* "O'chirish" tugmasi bosilganda, element `localStorage`-dan o'chirilishi va ro'yxat darhol yangilanishi kerak.
* Sahifa qayta yuklanganda ham eslatmalar ro'yxati saqlanib qolishi kerak.

#### **C2. DOM manipulyatsiyasi va hodisalarni boshqarish** `Oson`

Vanilla JavaScript yordamida elementlarni boshqarish imkoniyatiga ega dinamik ro'yxat yarating.

* Sahifada matn kiritish maydoni (`<input type="text">`) va **"Qo'shish"** tugmasi bo'lishi kerak.
* "Qo'shish" tugmasi bosilganda yoki Enter tugmasi bosilganda kiritilgan qiymat yangi ro'yxat elementi sifatida qo'shiladi. Bo'sh qiymat qo'shilmasligi kerak. Qo'shilgandan keyin kiritish maydoni tozalanadi.
* Har bir elementda **"Bajarildi"** va **"O'chirish"** tugmalari bo'lishi kerak.
  * "Bajarildi" tugmasi bosilganda matn ustidan chiziladi (`text-decoration: line-through`). Qayta bosilganda asl holatiga qaytadi.
  * "O'chirish" tugmasi bosilganda element darhol o'chiriladi.
* Ro'yxatning yuqorisida real vaqt rejimida **jami elementlar soni** va **bajarilganlar sonini** ko'rsating.

#### **C3. Dinamik JSON rendering va filtrlash** `O'rtacha`

Vanilla JavaScript va Fetch API yordamida mahalliy JSON faylini yuklaydigan va uning mazmunini dinamik ravishda ko'rsatadigan sahifa yarating.

* `/module_a/c3/posts.json` manzilidagi `posts.json` faylini Fetch API orqali yuklang. Fayl `id`, `title`, `body` va `category` kalitlariga ega bo'lgan obyektlar massivini o'z ichiga oladi (jami 20 ta element).
* Ma'lumot yuklanayotgan vaqtda **yuklanish indikatorini** (CSS animatsiyasi) ko'rsating va yuklash tugagach uni olib tashlang.
* Barcha elementlarni kartalar ko'rinishida ko'rsating. Har bir kartada `id`, `title`, `body` va `category` bo'lishi kerak.
* Qidiruv maydonini yarating, u `title` bo'yicha kartalarni real vaqt rejimida filtrlaydi (katta-kichik harfni farqlamaydi; har bir tugma bosilganda yangilanadi).
* Agar Fetch so'rovi muvaffaqiyatsiz tugasa, ekranda **"Failed to load data."** xatosini ko'rsating.

> **Taqdim etilgan fayl**: `posts.json` (ishtirokchining `/module_a/c3/` ishchi katalogiga joylashtirilgan)

#### **C4. Formani tekshirish (Validation)** `O'rtacha`

Vanilla JavaScript yordamida real vaqt rejimida formani tekshirishni amalga oshiring.

* Quyidagi maydonlarga ega ro'yxatdan o'tish formasini yarating: **Ism**, **Email**, **Parol**, **Parolni tasdiqlash**.
* Har bir maydon uchun tekshirish qoidalari:
  * **Ism**: Majburiy, kamida 2 ta belgi.
  * **Email**: Majburiy, `@` va `.` belgilarini o'z ichiga olishi kerak.
  * **Parol**: Majburiy, kamida 8 ta belgi, harflar va raqamlarni o'z ichiga olishi kerak.
  * **Parolni tasdiqlash**: Majburiy, Parol maydoni bilan to'liq mos kelishi kerak.
* Fokus maydondan chiqqanda (`blur` hodisasi), agar qoida buzilgan bo'lsa, o'sha maydon ostida xato xabarini ko'rsating. Shart bajarilishi bilan xato xabarini darhol olib tashlang.
* **"Yuborish"** tugmasi faqat barcha maydonlar to'g'ri to'ldirilganda faollashishi kerak. Tugma bosilganda `alert("Registration complete.")` xabari chiqishi kerak.

#### **C5. IntersectionObserver va kechiktirilgan rendering** `Qiyin`

`IntersectionObserver` yordamida cheksiz skroll va kechiktirilgan renderingni amalga oshiring.

* JavaScript-da 50 ta namunaviy elementdan iborat massiv yarating. Har bir element `id`, `title` va `color` ga ega bo'lishi kerak (`color` - ixtiyoriy `#RRGGBB` formatidagi rang).
* Dastlabki yuklanishda **10 ta** elementni ko'rsating. Har bir element **200px** balandlikdagi rangli `<div>` va uning `title` matnidan iborat bo'lsin. Birinchi 10 ta element o'zining rangini darhol fon sifatida ko'rsatishi kerak.
* Ro'yxatning oxiriga **kuzatuvchi element** (`<div id="sentinel">`) joylashtiring. Ushbu element ko'rinish maydoniga (viewport) kirganda, keyingi 10 ta element avtomatik ravishda qo'shilishi kerak.
* Yangi elementlar qo'shilayotganda kuzatuvchi elementdan oldin yuklanish indikatorini ko'rsating va rendering tugagach uni olib tashlang (`setTimeout` yordamida 600ms kechikishni simulyatsiya qiling).
* Barcha **50 ta element** yuklab bo'lingandan so'ng, kuzatuvchini to'xtating (`observer.unobserve`) va **"All items loaded."** xabarini ko'rsating.
* Yangi elementlar DOM-ga qo'shilganda ularning rangli `<div>`lari dastlab kulrang (`#cccccc`) bo'lishi kerak. Har bir `<div>`ni kuzatish uchun **alohida `IntersectionObserver` nusxasidan** foydalaning va element ekranda ko'rinishi bilan kulrangni elementning `data-color` atributidagi haqiqiy rangga almashtiring.

---

### 🛢️ D. Backend — PHP / MySQL

> **Taqdim etilgan fayllar**: D4 uchun `posts_dump.sql` va D5 uchun `data_dump.sql` har bir topshiriqning ishchi katalogiga joylashtirilgan.

#### **D1. PDO asosidagi CRUD API** `Oson`

PHP va MySQL (PDO) yordamida ma'lumotlarni boshqarish uchun REST API yarating.

* Quyidagi tuzilmada `items` jadvalini yarating. Jadvalni yaratish SQL kodini `table.sql` sifatida topshiring.
  * `id` (INT, PK, AUTO_INCREMENT), `title` (VARCHAR 100, NOT NULL), `content` (TEXT), `created_at` (TIMESTAMP DEFAULT CURRENT_TIMESTAMP)
* Bitta `api.php` faylida HTTP metodlari (`$_SERVER['REQUEST_METHOD']`) bo'yicha ajratilgan 4 ta endpointni amalga oshiring:
  * `GET /module_a/d1/api.php` → Barcha elementlarni JSON massivi sifatida qaytaradi.
  * `POST /module_a/d1/api.php` → Yangi element qo'shadi. Body (JSON): `{"title": "...", "content": "..."}`. So'rov tanasini `php://input` orqali o'qing va `json_decode()` bilan tahlil qiling. Muvaffaqiyatli bo'lsa, qo'shilgan qatorni JSON sifatida qaytaring.
  * `PUT /module_a/d1/api.php?id={id}` → `title` va `content`ni yangilaydi. Body (JSON): `{"title": "...", "content": "..."}`. Muvaffaqiyatli bo'lsa, yangilangan qatorni JSON sifatida qaytaring.
  * `DELETE /module_a/d1/api.php?id={id}` → Elementni o'chiradi. Muvaffaqiyatli bo'lsa, `{"message": "deleted"}` qaytaring.
* Mavjud bo'lmagan `id` uchun PUT/DELETE so'rovlari yuborilsa, **404** HTTP statusi va `{"error": "Not found"}` qaytaring.
* Barcha javoblarda `Content-Type: application/json` sarlavhasi (header) bo'lishi shart.

#### **D2. Fayl yuklashni boshqarish** `Oson`

PHP yordamida rasm fayllarini yuklash funksiyasini amalga oshiring.

* `upload.php` faylida fayl yuklash HTML formasini (GET) va yuklashni qayta ishlash mantiqini (POST) amalga oshiring. Formaning `enctype` atributini `multipart/form-data` qilib belgilang.
* Yuklash shartlari: faqat **jpg, jpeg, png, gif** kengaytmalariga ruxsat beriladi; fayl o'lchami **2MB yoki undan kam** bo'lishi kerak.
* Tekshiruvdan o'tgan fayllarni `uploads/` papkasiga **`{time()}_{asl_fayl_nomi}`** formatida saqlang. Agar `uploads/` papkasi mavjud bo'lmasa, uni kod orqali yarating.
* Muvaffaqiyatli yuklangandan so'ng, yuklangan rasmni `<img>` tegi orqali ko'rsating.
* Tekshiruv xatolari uchun tegishli xabarlarni chiqaring:
  * Noto'g'ri kengaytma: **"File type not allowed."**
  * O'lcham oshib ketgan: **"File size exceeds 2MB."**

#### **D3. Sessiya asosidagi autentifikatsiya tizimi** `O'rtacha`

PHP sessiyalari va MySQL yordamida foydalanuvchilarni ro'yxatdan o'tkazish, tizimga kirish va chiqishni amalga oshiring.

* `users` jadvali: `id` (INT, PK, AUTO_INCREMENT), `email` (VARCHAR 100, UNIQUE), `password` (VARCHAR 255), `name` (VARCHAR 50), `created_at` (TIMESTAMP DEFAULT CURRENT_TIMESTAMP)
* **`register.php`**: GET so'rovida ro'yxatdan o'tish formasini chiqaring. POST so'rovida email takrorlanmaganini tekshiring, parolni `password_hash()` bilan shifrlab saqlang va hech qanday xabarsiz darhol `login.php` ga yo'naltiring. Agar email band bo'lsa, forma ustida **"This email is already registered."** xatosini ko'rsating.
* **`login.php`**: GET so'rovida kirish formasini chiqaring. POST so'rovida parolni `password_verify()` bilan tekshiring. Muvaffaqiyatli bo'lsa, sessiyada `user_id`, `name` va `email`ni saqlang va `mypage.php` ga yo'naltiring. Xato bo'lsa, **"Incorrect email or password."** xabarini ko'rsating.
* **`logout.php`**: `session_destroy()` orqali sessiyani yakunlang va `login.php` ga yo'naltiring.
* **`mypage.php`**: Agar sessiyada `user_id` bo'lmasa, `login.php` ga yo'naltiring. Tizimga kirgan bo'lsa, **"Welcome, {name}!"** xabari va chiqish (logout) havolasini ko'rsating.

#### **D4. Sahifalash (Pagination)** `O'rtacha`

PHP va MySQL (PDO) yordamida server tomonida sahifalashni amalga oshiring.

* `posts` jadvalini yarating va taqdim etilgan SQL dump (`posts_dump.sql`) faylini import qiling. Jadval tuzilishi: `id`, `title`, `content`, `created_at`.
* `index.php` sahifasida **har bir sahifada 10 ta post** ko'rsating.
* Joriy sahifa URL-dagi `?page={n}` so'rovi orqali aniqlanadi (standart: 1). SQL so'rovida faqat kerakli ma'lumotlarni olish uchun `LIMIT` va `OFFSET` dan foydalaning. Agar `page` 1 dan kichik yoki jami sahifalar sonidan ko'p bo'lsa, 1-sahifaga yo'naltiring.
* Sahifaning pastki qismida sahifalash havolalarini ko'rsating. **Barcha sahifa raqamlarini ko'rsating**, joriy sahifani "active" uslubi bilan belgilang va "Oldingi/Keyingi" tugmalarini qo'shing. Birinchi sahifada "Oldingi", oxirgi sahifada esa "Keyingi" tugmalarini faolsizlantiring (disable).
* Har bir post elementida sarlavha va yaratilgan sana ko'rsatilishi kerak. Sarlavha bosilganda `view.php?id={id}` sahifasiga o'tib, postning to'liq matni ko'rsatiladi.

#### **D5. Bir nechta jadvalli agregat so'rovlar** `Qiyin`

Bir nechta jadvallarni birlashtirish (JOIN) va agregat so'rovlar yordamida statistika API-sini yarating.

* Barcha 3 ta jadvalni yarating va `data_dump.sql` faylini import qiling. **Jadvallar `users` → `posts` → `comments` tartibida yaratilishi kerak** (tashqi kalit bog'liqliklari uchun).
  * `users` (`id`, `name`, `created_at`)
  * `posts` (`id`, `user_id`, `title`, `category`, `view_count`, `created_at`)
  * `comments` (`id`, `post_id`, `created_at`)
* Bitta `stats.php` faylida `type` query stringiga qarab quyidagi 3 xil javobni qaytaring:
  * `GET /module_a/d5/stats.php?type=daily` → Oxirgi 7 kundagi har bir kun uchun yangi postlar sonini sana bo'yicha o'sish tartibida qaytaring. Format: `[{"date": "2026-04-06", "count": 5}, ...]`
  * `GET /module_a/d5/stats.php?type=category` → Har bir kategoriya bo'yicha jami postlar soni va o'rtacha ko'rishlar sonini, postlar soni kamayish tartibida qaytaring. Format: `[{"category": "tech", "post_count": 12, "avg_views": 340}, ...]`
  * `GET /module_a/d5/stats.php?type=top` → Izohlar soni bo'yicha eng yuqori 5 ta postni, izohlar soni kamayish tartibida qaytaring. Format: `[{"post_id": 3, "title": "...", "author": "Alice Johnson", "comment_count": 18}, ...]`
* Barcha so'rovlarda PDO **Prepared Statements** ishlatilishi shart.
* Noma'lum `type` qiymatlari uchun **400** HTTP statusi va `{"error": "Invalid type"}` qaytaring.

---

## 4. Topshirish bo'yicha ko'rsatmalar

Barcha natijalarni serverdagi `/module_a/` katalogiga yuklang. Har bir topshiriq o'zining ID-si bilan nomlangan quyi papkada bo'lishi kerak (masalan, `/module_a/a1/`, `/module_a/b1/`, `/module_a/c1/`, `/module_a/d1/`).

---

## 5. Baholash sxemasi — Jami 25 ball

| Toifa | Topshiriq | Ballar |
| :--- | :--- | :---: |
| **A. Dizayn** | 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 |
| **Jami** | | **25** |