Back to Projects

GitHub Repository

uzex-time

No description provided.

Stars: 2Language: HTMLUpdated: 9/1/2026

README

# uzex-time

Server vaqti sinxronizatori va **bosish vaqtini oldindan hisoblab beruvchi**
signal tizimi. Kim qo'lda bid qo'yadi - shu odam uchun.

## ⚠️ Eng muhim g'oya

Soat aniqligi muammo emas edi. Soat **±5 ms** aniqlikda ishlaydi, lekin oxirgi
sinovda bid **1-2 sekund** kech tushdi. Farq 200-400 barobar - demak xato
soatda emas, **signal va serverga yozilish orasidagi yo'lda**.

Bu yo'l quyidagilardan iborat:

| Bosqich | Odatda | Nazorat qilinadimi |
|---|---|---|
| Signalni eshitish → bosish | 200-300 ms (±100 ms tarqoqlik) | **Ha - sanoq bilan** |
| Auktsion sahifasi → so'rov | 5-50 ms | Qisman |
| LAN | 1-5 ms | Yo'q (kichik) |
| **Server navbati (yuzlab bid bir vaqtda)** | **100 ms - bir necha sekund** | **Qisman - zaxira bilan** |

Eski versiyada signal `59.750s` da chalinardi, ya'ni target'dan **250 ms
oldin**. Odamning reaksiyasi ham ~250 ms. Natijada bosish aynan `10:00:00.000`
ga - ya'ni **muddat tugagan lahzaga** tushardi, navbat esa uni yana 1-2 sekund
orqaga surardi. Bu versiya shu xatoni tuzatadi.

## 🎯 Yechim: reaksiya emas, oldindan his qilish

1. **Sanoq (3-2-1).** Signal endi bitta zarba emas. Undan oldin har sekundda
   qisqa "tik" chalinadi va ekranda chiziq to'ladi. Ovozga *reaksiya qilish*
   ~250 ms va ±100 ms tarqoqlik beradi; ritmni *oldindan his qilib* bosish
   tarqoqlikni bir necha o'n ms gacha tushiradi. Bu tayyorlangan musiqachi
   bilan cho'chib ketgan odam orasidagi farq.

2. **Oldinga surish (lead).** Signal endi target'da emas, `target - lead` da
   chalinadi:

   * **Reaksiya (ms)** - shaxsiy kechikishingiz. Taxmin qilinmaydi, **mashq
     rejimida o'lchanadi**.
   * **Navbat zaxirasi (ms)** - server navbati uchun. Bu **kuzatilgan** son
     bo'lishi kerak: bid qo'yib, auktsion ro'yxatida serverning o'zi qo'ygan
     vaqtni ko'ring va farqni yozing.

3. **Soat hech qachon siljitilmaydi.** Faqat signal oldinga suriladi, shuning
   uchun ekrandagi vaqt haqiqiy bo'lib qoladi va auktsion ekrani bilan
   solishtirsa bo'ladi.

## 🧪 Mashq (kalibrovka)

Sanoq davomida oxirgi zarbaga mos ravishda **PROBEL** bosing (yoki panel'dagi
tugmani). Har urinish uchun belgili xato yoziladi:

* **O'rtacha** - sizning doimiy kechikishingiz. `O'lchovni qo'llash` tugmasi
  uni to'g'ridan-to'g'ri "Reaksiya" maydoniga qo'yadi.
* **Tarqoqlik** - ishonchlilik. Agar ± 100 ms bo'lsa, siz hali reaksiya
  qilyapsiz; ± 30 ms atrofida bo'lsa, ritmni his qilyapsiz. **Tarqoqlik
  tushmaguncha mashq qiling** - o'rtachani tuzatib bo'ladi, tarqoqlikni yo'q.

Sozlamalar `localStorage` da saqlanadi: joyida sahifani qayta ochsangiz,
shoshilinch ravishda qaytadan o'lchash shart emas.

## 🔌 LAN (internetsiz) rejimi

Eng katta yashirin xavf: **auktsion serverining soati** - bid o'z vaqtida
tushdimi yoki yo'qmi, shuni faqat **o'sha** soat hal qiladi. `time.uzex.uz`
bilan mukammal sinxron bo'lib, ayni paytda noto'g'ri soatga qarab turgan
bo'lishingiz mumkin.

Shuning uchun manba sozlanadigan qilindi:

```bash
TIME_UPSTREAM=http://10.0.0.5/ node server.js            # bash
$env:TIME_UPSTREAM='http://10.0.0.5/'; node server.js    # PowerShell
```

Manba **istalgan HTTP server** bo'lishi mumkin. Agar javob tanasi epoch-ms son
bo'lmasa, `Date` sarlavhasiga o'tiladi - uni har qanday server yuboradi.

`Date` faqat sekund aniqligida, shuning uchun mijoz **qirra (edge) qidirish**
rejimiga o'tadi: tez-tez so'rov yuborib, sekund **almashgan lahzani** ikki
o'lchov orasiga qisib oladi. Shu yo'l bilan sekundlik sarlavhadan LAN'da
**±30 ms** aniqlik chiqadi (sinovda: mahalliy soatga nisbatan 11 ms xato).

## 📋 Joyidagi tartib

1. Noutbukni **simli** ulang (Wi-Fi 5-50 ms tebranish qo'shadi).
2. `TIME_UPSTREAM` ni auktsion serveriga qaratib `node server.js` ni ishga
   tushiring; holat qatorida qaysi manbaga qulflanganini tekshiring.
3. **Target** ni bosish tushishi kerak bo'lgan lahzaga qo'ying.
4. Bir necha daqiqa **mashq qiling**, keyin `O'lchovni qo'llash`.
5. **Navbat zaxirasi** ni o'tgan auktsionlardagi kuzatuvingizdan kiriting.
   Ma'lumot bo'lmasa, birinchi marta ehtiyotkorlik bilan katta oling: kech
   tushgan bid umuman hisobga olinmaydi, erta tushgani esa hisobga olinadi.
6. Sanoqni kuting, `HOZIR BOSING` da bosing.
7. **Har safar yozib boring**: qachon bosdingiz va server qaysi vaqtni qo'ydi.
   Farq - keyingi safar uchun navbat zaxirasi.

## 🖥️ Lokal ishga tushirish

```bash
npm run dev        # yoki: node server.js
# -> http://localhost:3000
```

`server.js` statik sahifani va Vercel'dagi bilan **bir xil** `/api/time`
funksiyasini yuritadi.

> `index.html` ni fayl sifatida ochish tavsiya etilmaydi: proksi (`/api/time`)
> shart, chunki manba CORS sarlavhalarini bermaydi.

## ⚙️ Aniqlik haqida

Proksi o'zining ichki vaqtini qaytaradi (`innerRtt`, `postFetchMs`,
`handlerMs`), brauzer esa buni umumiy kechikishdan ayiradi - shunda faqat sof
tarmoq vaqti simmetrik deb hisoblanadi:

```
netRtt       = clientRtt - handlerMs
serverAtRecv = serverTimestamp + innerRtt/2 + postFetchMs + netRtt/2
```

Boshqa xossalar: har 2 sekundda avtomatik sinxronizatsiya (`:10` va `:40`),
30 sekundlik oynada NTP uslubidagi mediana + og'irlikli o'rtacha, soat
**hech qachon orqaga sakramaydi** (slew), sinxron bo'lmaganda signal
**butunlay o'chiriladi**.

**Muhim:** target lahzasida endi "zaxira" signal chalinmaydi. Lead sozlangan
holda bunday signal aynan **allaqachon kech bo'lgan** lahzada "bos" deb
turgan bo'lardi - ya'ni tuzatilayotgan xatoning o'zi. Ovoz rejalashtirilmasa,
dastur signal bermay, buni yozib ko'rsatadi.

## 📦 Vercel

Konfiguratsiya nol-sozlamali. `TIME_UPSTREAM` ni Vercel env o'zgaruvchisi
sifatida ham berish mumkin, lekin joyidagi LAN uchun lokal `server.js`
ishonchliroq - internetga bog'liq emas.