T

คู่มือการใช้งาน

ระบบจัดการทัวร์นาเมนต์แบดมินตัน — ครบทุกฟีเจอร์

🌐 thaibadtournaments.com

ผู้เล่น เจ้าของรายการ ชมรม แอดมิน เจ้าของระบบ
เวอร์ชัน 1.0  •  วันที่จัดทำ: 15 พฤษภาคม 2569
คู่มือนี้สร้างจากการสำรวจโค้ดและหน้าจอจริงทั้งระบบ

📑 สารบัญ

  1. 1 ภาพรวมระบบ
    • เว็บนี้คืออะไร • กลุ่มผู้ใช้ 5 ระดับ • Flow การทำงาน • 4 สถานะของรายการแข่ง
  2. 2 สำหรับผู้เล่น / นักกีฬา (15 หัวข้อ)
    • สมัครสมาชิก • Login • ผูก LINE • 2FA • ยืนยันตัวตน • โปรไฟล์ • ปฏิทินทัวร์ • สมัครแข่ง • ชวนคู่ • สลิป • Inbox • Notifications • Photo Search • Achievements • Privacy
  3. 3 สำหรับเจ้าของรายการ / Staff Admin (22 หัวข้อ)
    • Admin Dashboard • สร้างทัวร์ • Payment Mode • SlipOK • Bracket • Schedule Planner • Live Score • Group/KO • OBS • TTS • Broadcast • Identity Verify • Users • Analytics • Errors • Shuttlecocks • Export
  4. 4 สำหรับชมรม / สมาคม (6 หัวข้อ)
    • สร้างชมรม • Banner Designer • สมาชิก • Association Tournament • Bulk Import • Age Categories
  5. 5 ระบบ LINE Bot
    • คำสั่งทั้งหมด • Flow ผูกบัญชี • Reminder อัตโนมัติ • Broadcast
  6. 6 สำหรับเจ้าของระบบ (System Owner)
    • Cron Setup • SMTP • LINE Config • SlipOK Config • Gemini TTS • Migrations
  7. 7 ฟีเจอร์ Photo Face Search
    • 🚧 อยู่ระหว่าง setup Proxmox — ออกแบบ UI พร้อมแล้ว
  8. A ภาคผนวก
    • FAQ • 4 สถานะรายการแข่ง • คีย์ลัด • ติดต่อ Support
01

ภาพรวมระบบ

รู้จักโครงสร้าง กลุ่มผู้ใช้ และวงจรการทำงานของระบบ

📖 อ่านก่อนใช้งานทุกบทบาท

1.1 เว็บนี้คืออะไร?

ThaibadTournaments.com คือแพลตฟอร์มจัดการการแข่งขันแบดมินตันแบบครบวงจร ตั้งแต่ผู้เล่นสมัครเข้าแข่ง ไปจนถึงการแสดงผลคะแนนสดผ่าน OBS

หน้าแรกของเว็บ

รูปที่ 1.1 — หน้าแรกของเว็บ thaibadtournaments.com

🎯 เป้าหมายหลัก

🧩 ฟีเจอร์เด่น

🏆 Tournament Engine

รองรับ Round-robin + Knockout (Single/Double elim) อัตโนมัติ advance ทีมชนะ

📡 Live Scoring

ป้อนคะแนนสด → อัปเดต scoreboard + OBS overlay ใน 1 วินาที

💳 Payment + SlipOK

3 โหมด: manual, QR, SlipOK API ตรวจสลิปอัตโนมัติ

📱 LINE Bot

"แมตของฉัน", "แมตที่เท่าไร" + reminder อัตโนมัติ 30 นาที / 1 ชม.

🔊 TTS เรียกคิว

Gemini AI อ่านชื่อสนาม + ผู้เล่น มีการ cache เสียง

📸 Photo Face Search

ค้นหารูปด้วย selfie (อยู่ระหว่าง setup AI)

1.2 กลุ่มผู้ใช้ 5 ระดับ (Roles)

ระบบมีการแบ่งสิทธิ์ผู้ใช้ออกเป็น 5 ระดับ ดังตาราง:

Roleชื่อในระบบสิทธิ์หลักตัวอย่างผู้ใช้
System Owner system_owner ตั้งค่าระบบ, จัดการ migration, ดู error log, จัดการทุกอย่าง เจ้าของเว็บ
Staff Admin staff_admin สร้างทัวร์, ป้อนคะแนน, ตรวจสลิป, จัดการ user, broadcast LINE เจ้าหน้าที่จัดแข่ง
Client Owner client_owner เป็นเจ้าของชมรม, สร้างทัวร์ในชมรม, จัดการสมาชิก เจ้าของชมรม
Contributor contributor ช่วยป้อนคะแนน/ตรวจสลิปในทัวร์ที่ได้รับสิทธิ์เฉพาะ กรรมการชั่วคราว
User user สมัครแข่ง, ดูตาราง, ดูคะแนน, รับ notification นักกีฬาทั่วไป
💡 หมายเหตุเรื่อง Match Permissions

นอกจาก global role แล้ว ระบบยังมี per-tournament permission — เจ้าของรายการสามารถมอบสิทธิ์ scorer, verifier, viewer ให้บางคนเฉพาะทัวร์ของตัวเองได้

1.3 4 สถานะของรายการแข่ง (Tournament Status)

รายการแข่งทุกรายการในระบบจะอยู่ในหนึ่งใน 4 สถานะนี้ ส่งผลต่อสิทธิ์การสมัครและการแสดงผล

สถานะหมายความว่าผู้เล่นทำอะไรได้ผู้จัดทำอะไรได้
เปิดรับสมัคร รายการประกาศแล้ว เปิดให้ลงทะเบียน สมัคร, ชวนคู่, ชำระเงิน, ยกเลิก ดูผู้สมัคร, อนุมัติสลิป, จัดสาย
ปิดรับสมัคร หมดเวลาสมัครแล้ว รอเตรียมการแข่ง ดูรายชื่อ, ดูสาย จัดสาย, พิมพ์ scoresheet, plan ตาราง
กำลังแข่งขัน วันแข่งจริง — ใช้งาน live scoring ดูคิว, ดูคะแนนสด, รับ reminder LINE ป้อนคะแนน, advance ผู้ชนะ, OBS overlay
แข่งขันเสร็จสิ้น จบการแข่งขัน — ดูผลย้อนหลังได้ ดูผล, ดูสถิติ, ดูรูปภาพ แก้ผล (ถ้าผิด), upload รูป

📸 ตัวอย่างจริงในระบบทั้ง 4 สถานะ

เปิดรับสมัคร

เปิดรับสมัคร — รายการ "สนามกลางโอเพ่น #1"

ปิดรับสมัคร

ปิดรับสมัคร — รายการ "Test"

กำลังแข่งขัน

กำลังแข่งขัน — VENSON Kamphaengphet 2026

แข่งขันเสร็จสิ้น

แข่งขันเสร็จสิ้น — Rotary Championship 2026

⚠️ การเปลี่ยนสถานะ

สถานะเปลี่ยนได้เฉพาะ Admin / เจ้าของรายการ ผ่านหน้า edit_match.php ระบบไม่เปลี่ยนอัตโนมัติตามวันที่ — ผู้จัดต้องเปลี่ยนเอง

1.4 Flow การทำงานของระบบ

👥 มุมมองนักกีฬา (User)

User Journey
[1] สมัครสมาชิก → [2] ผูก LINE → [3] ตั้งค่าโปรไฟล์ + ยืนยันตัวตน
                                        ↓
[4] ดูปฏิทินทัวร์ → [5] สมัครรายการ → [6] ชวนคู่ → [7] ชำระเงิน
                                                          ↓
[8] รอ reminder LINE → [9] เช็คอินวันแข่ง → [10] ดูคิว/คะแนนสด
                                                          ↓
                                            [11] รับรางวัล + ดูสถิติย้อนหลัง

🏆 มุมมองเจ้าของรายการ (Admin)

Admin Journey
[1] สร้างรายการ → [2] กำหนด event/รุ่นอายุ → [3] ตั้งค่า Payment mode
        ↓
[4] เปิดรับสมัคร → [5] อนุมัติสลิป → [6] ปิดรับสมัคร
        ↓
[7] จัดสาย (Bracket) → [8] Schedule Planner → [9] พิมพ์ Scoresheet
        ↓
[10] เปลี่ยนสถานะ "กำลังแข่งขัน" → [11] ป้อนคะแนนสด
        ↓
[12] Auto-advance ทีมชนะ → [13] Broadcast LINE → [14] OBS overlay
        ↓
[15] เปลี่ยนสถานะ "เสร็จสิ้น" → [16] อัปโหลดรูป

🔗 ระบบที่ทำงานเบื้องหลัง (Cron + Webhook)

1.5 ทำความรู้จักหน้าตาเว็บ

🏠 หน้าแรก (Homepage)

หน้าแรก

รูปที่ 1.5.1 — หน้าแรกแสดง: รายการเด่น, ข่าวสาร, ปฏิทินใกล้เคียง

📅 ปฏิทินการแข่งขัน (calendar.php)

ปฏิทิน

รูปที่ 1.5.2 — ดูทุกรายการในมุมมองปฏิทินรายเดือน + รายการที่เปิดรับสมัคร

สี dot บนปฏิทินบอกสถานะ:

02

สำหรับผู้เล่น / นักกีฬา

วิธีใช้งานทุกฟีเจอร์สำหรับ User ทั่วไป

👤 Role: user

2.1 สมัครสมาชิกใหม่

การสมัครสมาชิกใช้เวลา ~2 นาที ทำได้ 3 ช่องทาง:

หน้าสมัครสมาชิก

รูปที่ 2.1 — หน้า signup.php

ขั้นตอน (สมัครด้วยฟอร์ม)

  1. เข้า thaibadtournaments.com/badminton/signup.php
  2. กรอก username (a-z, 0-9, _ — ไม่มีช่องว่าง)
  3. กรอก email (ระบบเช็ค MX DNS — ต้องใช้งานได้จริง)
  4. กรอก password + ยืนยัน (อย่างน้อย 8 ตัว)
  5. กรอก ชื่อจริง-นามสกุล ภาษาไทย
  6. ยอมรับ Privacy Policy → กด "สมัครสมาชิก"
⚠️ ตรวจ duplicate

ระบบจะเช็ค check_username.php, check_email.php, check_name_duplicate.php แบบ realtime — ถ้า username/email/ชื่อ ซ้ำ จะเตือนทันทีก่อน submit

💡 Tip — ทำไมต้องใช้ชื่อจริง?

ระบบใช้ชื่อจริงในการแมตช์ผู้เล่นกับการสมัครแข่งและ ranking — ใช้ชื่อเล่นไม่ได้

2.2 เข้าสู่ระบบ (Login)

หน้า login

รูปที่ 2.2 — หน้า login.php — มี 3 ช่องทาง

  1. ใส่ username หรือ email (ระบบรับทั้งคู่)
  2. ใส่ password → กด "ลงชื่อเข้าใช้"
  3. หากมี 2FA เปิดอยู่ ระบบจะถามรหัส OTP 6 หลัก

🔐 ระบบความปลอดภัย

🔑 ลืมรหัสผ่าน

forgot password
  1. กด "ลืมรหัสผ่าน?"
  2. ใส่ email ที่ลงทะเบียนไว้
  3. เปิด email → กดลิงก์ reset (อายุ 1 ชม.)
  4. ตั้ง password ใหม่

2.3 ผูกบัญชี LINE

การผูก LINE สำคัญมาก เพราะระบบจะส่ง reminder ก่อนแข่ง 30 นาที + 1 ชั่วโมง ผ่าน LINE

หน้าผูก LINE

รูปที่ 2.3 — หน้า link_line.php แสดง QR + PIN 6 หลัก

วิธีผูก

  1. Login เข้าระบบ → ไปที่ โปรไฟล์ → "ผูก LINE"
  2. ระบบสร้าง PIN 6 หลัก (อายุ 15 นาที)
  3. เพิ่มเพื่อน LINE Bot: @thaibadtournaments (สแกน QR)
  4. พิมพ์ ลงทะเบียน 123456 ในแชท (แทน 123456 ด้วย PIN ของคุณ)
  5. Bot ตอบกลับ "เชื่อมต่อสำเร็จ" → จบ
🔒 ความปลอดภัย

PIN ใช้ได้ครั้งเดียวเท่านั้น, expire ใน 15 นาที — ถ้าไม่ใช้ทัน ต้องสร้างใหม่ ระบบจะเช็คว่า LINE UID ไม่ได้ผูกกับ user อื่นก่อน

ยกเลิกการผูก

ไปที่ โปรไฟล์ → กดปุ่ม "ยกเลิกการผูก LINE" — ระบบจะลบ link และหยุดส่ง notification ทันที

2.4 ตั้งค่า 2FA (Two-Factor Authentication)

เปิด 2FA เพื่อความปลอดภัยขั้นสูง — ต้องใช้ Google Authenticator หรือ app TOTP อื่น

วิธีเปิด 2FA

  1. ไปที่ โปรไฟล์แก้ไขข้อมูล → tab "ความปลอดภัย"
  2. กด "เปิดใช้ 2FA"
  3. สแกน QR code ด้วย Google Authenticator (หรือ Authy, 1Password)
  4. กรอกรหัส 6 หลักจาก app → ยืนยัน
  5. ระบบให้ backup codes 10 รหัส — บันทึกไว้ในที่ปลอดภัย
🚨 ระวัง — Backup Codes

Backup codes แต่ละรหัสใช้ได้ ครั้งเดียว — ใช้เมื่อมือถือหาย/Authenticator app เปลี่ยนเครื่อง ห้ามแชร์ ห้าม screenshot บน cloud

เวลา login ด้วย 2FA

  1. ใส่ username + password ปกติ
  2. ระบบพาไปหน้า verify_2fa.php
  3. เปิด Authenticator → กรอกรหัส 6 หลัก → ผ่าน

2.5 ยืนยันตัวตน (Identity Verification)

ทัวร์บางรายการ (โดยเฉพาะ Association tournament รุ่นอายุ) บังคับให้ยืนยันตัวตนก่อนสมัคร เพื่อยืนยันอายุจริง

ขั้นตอน

  1. ไปที่ โปรไฟล์ → "ยืนยันตัวตน"
  2. อัปโหลดรูปบัตรประชาชน (ปิดเลข 4 ตัวท้ายได้)
  3. กรอกข้อมูล: ชื่อ-นามสกุล, วันเกิด, เพศ (ต้องตรงกับบัตร)
  4. กด "ส่งคำขอ" → รอแอดมินตรวจ (ปกติ 1-2 วันทำการ)
🔒 Privacy-First

เมื่อแอดมินอนุมัติแล้ว ระบบจะลบรูปบัตรประชาชนทันที — เก็บแค่ flag "verified" + วันเกิด + เพศ ไม่มีการเก็บภาพถาวร

หลังยืนยันแล้ว

2.6 ดูและแก้ไขโปรไฟล์

หน้าโปรไฟล์

รูปที่ 2.6 — หน้าโปรไฟล์ profile.php

ส่วนประกอบ

แก้ไขข้อมูล

edit profile

รูปที่ 2.6.2 — edit_profile.php

แก้ไขได้ทันที (ไม่ต้อง OTP):

ต้องใช้ OTP ผ่าน email ก่อนเปลี่ยน:

💡 ทำไมต้อง OTP?

ข้อมูลพวกนี้ส่งผลต่อ identity + การสมัครรุ่นอายุ — ระบบบังคับให้ยืนยันผ่าน OTP เพื่อป้องกัน account takeover

2.7 ดูปฏิทินการแข่งขัน

calendar

รูปที่ 2.7 — calendar.php — แสดงรายการแข่งทุกสถานะ

วิธีกรอง

วิธีอ่านสีบนปฏิทิน

เปิดรับสมัครสีเขียว — สมัครได้ตอนนี้
ปิดรับสมัครสีแดง — หมดเวลาสมัครแล้ว
กำลังแข่งขันสีเหลือง — แข่งวันนี้/สัปดาห์นี้
เสร็จสิ้นสีเทา — จบแล้ว ดูผลย้อนหลัง

คลิกที่รายการเพื่อเข้าสู่หน้า match_detail.php?id=...

2.8 หน้ารายละเอียดรายการแข่ง (Match Detail Tabs)

หน้ารายการแข่ง match_detail.php?id=N มี 9 tabs ที่จะแสดง/ซ่อนตามสถานะของรายการ

tab info

รูปที่ 2.8 — Tab "รายละเอียดการแข่งขัน" (default)

Tabไอคอนเนื้อหาเห็นเมื่อ
รายละเอียดℹ️วันแข่ง, สถานที่, โปสเตอร์, Google Mapเสมอ
กติกา📜กฎการแข่ง + รูปประกอบเปิดโดยแอดมิน
รายชื่อผู้สมัคร📋ทีมที่สมัครแล้ว + สถานะชำระเงินเปิดโดยแอดมิน
ตารางแข่งขันคิว + สนาม + เวลา (อัปเดตสด)หลังจัดสาย
รอบแบ่งกลุ่ม📊ตารางคะแนนกลุ่ม (W/D/L)มี group stage
รอบน็อกเอาต์🌳สายแข่ง (bracket tree)มี knockout
ผลการแข่งขัน🏆ผู้ชนะ + เหรียญหลังจบ
จำนวนลูกแบด🏸track ลูกแบดมินตันที่ใช้เปิดโดยแอดมิน
รูปภาพ📸gallery รูปจากการแข่งเปิดโดยแอดมิน

📡 Tab "การแข่งสด" (Live)

เมื่อรายการอยู่สถานะ กำลังแข่งขัน และเปิด YouTube Live URL — จะมีปุ่ม "🔴 ดูการแข่งสด" แยกพิเศษ ฝัง YouTube embed

2.9 สมัครเข้าแข่ง

กดได้เมื่อรายการอยู่สถานะ เปิดรับสมัคร เท่านั้น

ขั้นตอน

  1. เข้าหน้า match_detail.php?id=N
  2. กดปุ่ม "สมัครเข้าแข่งขัน" (สีเขียว ขวามือ)
  3. เลือก event ที่ต้องการ (เช่น ชายคู่, หญิงคู่, คู่ผสม)
  4. เลือก รุ่นอายุ (ถ้ามี — บังคับยืนยันตัวตนก่อน)
  5. กรอก ชื่อทีม (ค้นหาจากชื่อชมรมอัตโนมัติ)
  6. ส่วน คู่ที่ 2: 3 ทางเลือก
    • 📨 ชวนผ่าน UID — กรอก UID ของคู่ → ระบบส่ง invite ใน Inbox + LINE
    • 🔍 ค้นหาด้วยชื่อ — autocomplete จาก search_users_by_name
    • ✍️ ใส่ชื่อ guest — สำหรับผู้ที่ไม่มีบัญชีในระบบ
  7. กด "ส่งใบสมัคร"
⚠️ ค่าธรรมเนียม

หลังส่งใบสมัคร สถานะจะเป็น "รอชำระเงิน" ต้องอัปโหลดสลิปภายในเวลาที่กำหนด (ส่วนใหญ่ 24-48 ชม.) ไม่งั้นใบสมัครจะถูกยกเลิกอัตโนมัติ

2.10 ตอบรับการเชิญจากคู่

เมื่อมีคนชวนคุณ — คุณจะได้รับการแจ้งเตือน 2 ช่องทาง:

inbox

รูปที่ 2.10 — Inbox แสดง invite จากคู่

ขั้นตอนตอบรับ

  1. เปิด Inbox → คลิกที่ข้อความ "🎾 [ชื่อ] ชวนคุณลงแข่ง [ทัวร์]"
  2. ระบบพาไป respond_invite.php?token=...
  3. ตรวจข้อมูล: รายการ, event, คู่ของคุณ
  4. กด "ยอมรับ" หรือ "ปฏิเสธ"
  5. หากยอมรับ — ใบสมัครเข้าสถานะ "รอชำระเงิน" ทันที (คนชวนต้องชำระเอง หรือคุยกันเอง)
💡 Token Security

Token ของ invite ใช้ครั้งเดียว, ผูกกับ user_id ของคุณ — คนอื่นเปิดลิงก์ไม่ได้

2.11 ชำระเงิน + อัปโหลดสลิป

ระบบรองรับ 3 โหมดการชำระ:

โหมดวิธีการการตรวจ
manualไม่มีระบบ online — โอนแล้วแจ้งแอดมินเองแอดมิน manual
manual_qrสแกน QR code → อัปโหลดสลิปแอดมิน manual
slipokสแกน QR → อัปโหลดสลิป → SlipOK API ตรวจอัตโนมัติอัตโนมัติ

ขั้นตอนอัปโหลดสลิป

  1. เข้าหน้า match_detail.php → tab "รายชื่อผู้สมัคร" → หาแถวของคุณ
  2. กด "อัปโหลดสลิป"
  3. เลือกรูปสลิป (JPG/PNG, ขนาด < 5 MB)
  4. กด "ส่ง" → ระบบตรวจสลิป
    • SlipOK mode — ตรวจอัตโนมัติใน 5-10 วินาที → สถานะ "ผ่านชำระแล้ว"
    • Manual mode — รอแอดมินตรวจ (1-24 ชม.)
⚠️ SlipOK เช็คอะไรบ้าง

API ตรวจ: ยอดเงิน, ชื่อผู้รับโอน, เลข trans_ref, และ unique check ไม่ให้ใช้สลิปเดียวกันซ้ำ

2.12 Inbox — กล่องข้อความ

inbox

ประเภทข้อความที่จะเข้า Inbox

เปิดข้อความ → ระบบ mark เป็น "read" อัตโนมัติ

2.13 ตั้งค่าการแจ้งเตือน

เปิด/ปิดการแจ้งเตือนแต่ละประเภทได้ใน notification_settings.php

ช่องทาง

ประเภทที่ตั้งค่าได้

Flagเมื่อไร
notify_match_reminderก่อนแข่ง 30 นาที + 1 ชั่วโมง
notify_court_changeแอดมินเปลี่ยนสนาม/คิว
notify_morning_broadcastสรุปตารางวันแข่ง 06:00
notify_partner_inviteมีคนชวนเป็นคู่
notify_result_postedผลแข่งของคุณถูก post
notify_payment_statusสลิปได้รับอนุมัติ/ปฏิเสธ

ตั้งค่าได้ ต่อรายการแข่ง (per-tournament) ไม่ใช่ global เท่านั้น

2.14 ข่าวสาร (News)

news

รูปที่ 2.14 — หน้าข่าวสาร news.php

ข่าวสารโพสต์โดยแอดมิน — รวม:

2.15 ค้นหารูปภาพด้วยใบหน้า (Photo Face Search)

🚧 ฟีเจอร์อยู่ระหว่างพัฒนา

ระบบ AI Face Recognition กำลังติดตั้งบน Proxmox VM (GPU) — รายละเอียดเทคนิคอ่านที่ส่วนที่ 7

การใช้งานที่วางแผนไว้

  1. เข้าหน้า photo_search.php
  2. อัปโหลด selfie (รูปหน้าตัวเอง 1 รูป)
  3. เลือกรายการที่ต้องการค้นหารูป
  4. ระบบส่ง embedding ไปยัง AI → match กับรูปทั้งหมดในรายการ
  5. แสดงผล: รูปที่มีใบหน้าใกล้เคียง พร้อม similarity score
  6. ดาวน์โหลดรูปที่ต้องการ
03

เจ้าของรายการ / Staff Admin

วิธีจัดการทัวร์นาเมนต์ตั้งแต่ต้นจนจบ

🏆 Role: staff_admin หรือ tournament owner

3.1 Admin Dashboard

admin dashboard

รูปที่ 3.1 — หน้า admin.php — ศูนย์รวมการจัดการทั้งหมด

เมนูหลักใน Dashboard

3.2 สร้างรายการแข่งใหม่

ทำได้จาก Admin Dashboard → กดปุ่ม "+ สร้างรายการ"

ฟิลด์ที่ต้องกรอก

กลุ่มฟิลด์หมายเหตุ
ข้อมูลพื้นฐานtitleชื่อรายการ
start_date / end_dateวันแข่ง
locationสถานที่ + map_url (Google Maps)
provinceจังหวัด (ใช้ filter)
การแข่งmatch_modeweb ทั่วไป / association สมาคม (มีรุ่นอายุ)
available_eventsJSON list — ชายคู่, หญิงคู่, คู่ผสม, เดี่ยว ฯลฯ
available_age_categoriesสำหรับ association mode
การชำระเงินpayment_modemanual / manual_qr / slipok
payment_qr_imageรูป QR (สำหรับ manual_qr)
payment_amountยอดที่ต้องชำระ
slipok_branch_id / api_key(สำหรับ slipok)
Tab visibilitytab_result_enabledเปิด tab "ผลการแข่งขัน"
tab_shuttlecocks_enabledเปิด tab "จำนวนลูกแบด"
tab_photos_enabledเปิด tab "รูปภาพ"
tab_rules_enabledเปิด tab "กติกา"
Livelive_enabledเปิดปุ่ม "ดูสด"
youtube_live_urlURL embed
Notificationnotify_match_reminderเปิด LINE reminder 30/60 นาที
notify_court_changeเปิดแจ้งเปลี่ยนสนาม
notify_morning_broadcastเปิด morning broadcast

3.3 แก้ไขรายการแข่ง

edit match

รูปที่ 3.3 — edit_match.php — มี multi-section + sensitive changes

การเปลี่ยน "สถานะ"

เปลี่ยนผ่าน dropdown — มี 4 ค่า:

⚠️ Sensitive Changes

การเปลี่ยน payment_mode, slipok_api_key, อายุของรายการ ต้องผ่าน OTP confirmation ผ่าน apply_sensitive_changes.php

3.4 ตั้งค่าระบบชำระเงิน (Payment Modes)

โหมด 1: Manual

โหมด 2: Manual QR

โหมด 3: SlipOK (อัตโนมัติ)

verify slips
  1. สมัคร SlipOK API ที่ slipok.com → ได้ branch_id + api_key
  2. กรอกใน edit_match.php ที่ฟิลด์ slipok_branch_id + slipok_api_key
  3. ผู้เล่นอัปโหลดสลิป → SlipOK ตรวจ: ยอดเงิน, ชื่อผู้รับ, trans_ref, duplicate check
  4. ผ่าน → match_registrations.status='ผ่านชำระแล้ว', slip_auto_verified=1
  5. ไม่ผ่าน → ตกมาให้แอดมินตรวจด้วยมือ
💡 ความถูกต้องสูง

SlipOK ใช้ OCR + database ของธนาคารตรวจ trans_ref — แม่นยำเกือบ 100% และเร็ว ~5 วินาที

3.5 ตรวจสลิป Manual

หน้า admin_verify_slips.php — แสดงสลิปที่รอตรวจทั้งหมด

ขั้นตอน

  1. ดูรูปสลิป (กดขยายได้)
  2. เทียบกับ: ชื่อบัญชีรับโอน, ยอดเงิน, วันที่
  3. กด "✓ อนุมัติ" → สถานะ "ผ่านชำระแล้ว"
  4. หรือกด "✗ ปฏิเสธ" → ใส่เหตุผล (เช่น "ยอดไม่ตรง", "สลิปซ้ำ")
  5. ระบบส่ง notification ไปยังผู้เล่น + คู่ผ่าน Inbox + LINE
🚨 ระวังสลิปปลอม

ตรวจ ชื่อผู้รับโอน ทุกครั้ง! สลิปปลอมมักเปลี่ยนเฉพาะชื่อผู้โอน — ระบบ SlipOK ป้องกันได้ดีกว่า manual

3.6 ตั้งค่าสายแข่ง (Bracket Config)

หลังปิดรับสมัคร → ต้องจัดสายการแข่งก่อน

รูปแบบที่รองรับ

รูปแบบคำอธิบายใช้กับ
Round-robin onlyแบ่งกลุ่ม แต่ละคู่แข่งทุกคู่ในกลุ่มผู้เล่นน้อย, ลีก
Single Eliminationแพ้คัดออก รอบเดียวทัวร์ทั่วไป
Double Eliminationมี loser bracketมืออาชีพ
Group + KOแบ่งกลุ่มก่อน → ทีมต้น ๆ ไป knockoutทัวร์ใหญ่
manage group

รูปที่ 3.6 — admin_manage_group.php — จัดกลุ่ม + คะแนน

3.7 Schedule Planner — วางตารางแข่ง

schedule planner

รูปที่ 3.7 — admin_schedule_planner.php — auto schedule

ฟีเจอร์

Input parameters

3.8 พิมพ์ใบลงคะแนน (Scoresheet)

print scoresheet

รูปที่ 3.8 — admin_print_scoresheet.php — A4 Landscape

รูปแบบที่พิมพ์ได้

หน้า A4 Landscape — ทดสอบและปรับ margin เพื่อให้พิมพ์ตรงทุก browser (Chrome, Safari, Firefox)

3.9 ป้อนคะแนนสด (Live Scoring)

live match

รูปที่ 3.9 — admin_live_match.php

วิธีป้อนคะแนน

  1. เปิด admin_live_match.php?id=N
  2. เลือกคู่ที่กำลังแข่งจากตาราง
  3. กรอกคะแนนใน input field — รองรับหลายรูปแบบ:
    • 21 15 21 10 → auto-format เป็น 21-15, 21-10
    • 21-15 21-10 → คงรูปแบบ
    • 21-19 18-21 21-15 → 3 เซ็ต
  4. กด "บันทึก" — ระบบ:
    • อัปเดต group_standings auto (W/D/L, set diff, point diff)
    • เรียก autoAdvanceKnockout() ถ้าเป็นแมตช์น็อกเอาต์ → ส่งทีมชนะไปรอบถัดไป
    • Broadcast ผ่าน match_order_api.php ให้ scoreboard + OBS อัปเดต
💡 Real-time Co-work

หากกรรมการหลายคนป้อนพร้อมกัน — ระบบใช้ editing_presence table แสดงว่าใครกำลังแก้ field ไหน (TTL 5 วินาที)

3.10 จัดการรอบน็อกเอาต์ (Knockout)

manage knockout

รูปที่ 3.10 — admin_manage_knockout.php

โครงสร้าง

ตาราง knockout_matches ใช้ symbolic reference:

เมื่อ admin ป้อนคะแนนแมตช์ที่ 1 → ระบบเรียก autoAdvanceKnockout() recursively walk tree → แทนที่ W1 ในแมตช์ลูก ด้วยชื่อทีมจริง

3.11 จัดการลำดับการแข่ง (Order of Play)

manage order

รูปที่ 3.11 — admin_manage_order.php

ทำได้

⚠️ ถ้าเปลี่ยนสนาม/เวลา

หาก notify_court_change เปิดอยู่ — ระบบจะส่ง LINE notification ไปยังผู้เล่นทั้งคู่ทันที

3.12 Live Scoreboard (Kiosk Display)

หน้าจอแสดงผลขนาดใหญ่ — สำหรับ TV/Projector ในงานแข่ง

💡 ใช้งาน

เปิด admin_scoreboard.php?id=N บน TV → เต็มจอ (F11) → อัปเดต auto ทุก 1 วินาที

3.13 OBS Overlay — สำหรับ Live Streaming

ตั้งค่า OBS

  1. เปิด OBS Studio
  2. เพิ่ม Source: Browser Source
  3. URL: https://thaibadtournaments.com/badminton/admin_obs_overlay.php?id=N&court=1
  4. Width: 1920, Height: 1080
  5. เลือก "Custom CSS" → ปรับสี/ขนาดตามต้องการ
  6. กด "OK" → overlay จะแสดงทับวิดีโอแบบโปร่งใส
💡 พารามิเตอร์ที่ปรับได้
  • ?court=1 — แสดงเฉพาะคอร์ทที่ 1
  • ?theme=dark — ใช้ธีมเข้ม
  • ?style=compact — ขนาดเล็ก (สำหรับมุมจอ)

อ่านเพิ่มเติม: ไฟล์ OBS overlay.md ใน root

3.14 TTS เรียกคิว (Court Call)

ระบบเรียกชื่อนักกีฬาผ่าน Text-to-Speech

3 เครื่องมือ TTS

เครื่องมือคุณภาพความเร็วราคา
Gemini AI (default)⭐⭐⭐⭐⭐ ดีที่สุด2-3 วินาที100 RPD ฟรี
Google Translate TTS⭐⭐⭐1 วินาทีฟรี ไม่จำกัด
Browser SpeechSynthesis⭐⭐ทันทีฟรี

การเรียกใช้

  1. เปิด tts_court_call.php?id=N บนเครื่องที่มีลำโพง/เครื่องเสียง
  2. เลือกคิวที่ต้องการเรียก
  3. กด "เรียก" — ระบบจะอ่าน "สนาม X เชิญทีม Y และ Z"

TTS Cache

tts cache

ระบบ cache เสียงด้วย SHA256(text+voice).wav ใน /uploads/tts_cache/

3.15 LINE Broadcast

line broadcast

รูปที่ 3.15 — admin_line_broadcast.php

การส่งข้อความหมู่

  1. เลือก กลุ่มเป้าหมาย:
    • ทั้งหมด
    • ตามจังหวัด
    • ตามรายการแข่งที่สมัครไว้
    • ตามรุ่นอายุ/เพศ
  2. เลือก รูปแบบ: Plain text หรือ Flex Message
  3. เขียนข้อความ → Preview ก่อนส่ง
  4. กด "ส่ง" → ระบบ multicast batch 500 UIDs/ครั้ง
⚠️ LINE Quota

LINE Messaging API จำกัด push quota ต่อเดือน — ตรวจสอบที่ LINE Developer Console ก่อนส่งหมู่ทั้งหมด

3.16 Morning Broadcast (สรุปตารางวันแข่ง)

ส่งสรุปตารางการแข่งของผู้เล่นแต่ละคนตอน 06:00 ของวันแข่ง

วิธีตั้ง

  1. เปิด admin_morning_broadcast.php
  2. เลือกรายการ + วันที่
  3. กด "ดู Preview" — ระบบรวบรวม matches ของผู้เล่นทุกคน, group ตาม user
  4. กด "ส่งทันที" หรือ "ตั้งเวลาส่ง"

แต่ละผู้เล่นจะได้ 1 ข้อความเดียว สรุปทุกแมตช์ของตัวเอง (ไม่ซ้ำแม้สมัครหลายรุ่น)

การ Automate

ตั้ง cron job ใน server ให้รัน admin_morning_broadcast.php?auto=1&date=TODAY ตอน 06:00 ทุกวัน

3.17 ตรวจสอบการยืนยันตัวตน

verify identity

รูปที่ 3.17 — admin_verify_identity.php

ขั้นตอน

  1. ดูรูปบัตรประชาชนของผู้สมัคร (กดขยายได้)
  2. เปรียบเทียบกับข้อมูลที่กรอก: ชื่อ, วันเกิด, เพศ
  3. กด "✓ อนุมัติ" → ระบบ:
    • ตั้ง users.identity_verified = 1
    • ลบรูปบัตรประชาชนทันที (privacy-first)
    • ส่ง notification ผ่าน Inbox + LINE
  4. หรือกด "✗ ปฏิเสธ" → ใส่เหตุผล (เช่น "รูปไม่ชัด", "ข้อมูลไม่ตรง")

3.18 จัดการผู้ใช้

manage users

รูปที่ 3.18 — manage_users.php

การจัดการ

3.19 Visitor Analytics

visitor logs

รูปที่ 3.19 — admin_visitor_logs.php

ข้อมูลที่เก็บ

Tableเก็บอะไร
visitor_sessions1 session = 1 user open browser, IP, device, browser, referrer
visitor_pageviewsหน้าที่เปิด + duration (จาก heartbeat ทุก 30 วินาที)

Metrics

3.20 Error Log Viewer

error log

รูปที่ 3.20 — admin_errors.php

การทำงาน

การใช้งานหน้านี้

3.21 Player Stats / Head-to-Head

player stats

รูปที่ 3.21 — admin_player_stats.php

ดูได้

3.22 จัดการลูกแบดมินตัน + Export

Shuttlecocks Tracker

shuttlecocks

รูปที่ 3.22 — admin_shuttlecocks.php — บันทึกลูกที่ใช้

Export Registrations

เข้า export_registrations.php?id=N → ดาวน์โหลด CSV/Excel ของผู้สมัครทั้งหมด

จังหวัดในปฏิทิน

calendar province

admin_calendar_province.php — เพิ่ม/แก้ไขจังหวัดให้ตัวกรอง

04

สำหรับชมรม / สมาคม

การสร้างและจัดการชมรม + Association Tournament

🏛️ Role: client_owner

4.1 สร้างชมรมใหม่

club create

รูปที่ 4.1 — club_create.php

ฟิลด์ที่ต้องกรอก

เมื่อสร้างเสร็จ — คุณเป็น club_member role=owner โดยอัตโนมัติ

4.2 ออกแบบ Banner ชมรม

Banner ปรากฏใน profile ชมรม, list ชมรม, และในรายการแข่งของชมรม

รูปแบบที่รองรับ (เก็บใน club_banner_designs)

Background typeคำอธิบาย
Gradient2 สี + ทิศทาง (linear-gradient)
Solidสีเดียว
Imageอัปโหลดรูปเป็น bg
PatternSVG pattern (dots, lines, diagonal)

ปรับแต่งข้อความ

4.3 จัดการสมาชิกชมรม

club manage

รูปที่ 4.3 — club_manage.php?id=N

การเชิญสมาชิก

  1. แชร์ลิงก์ของชมรม (เช่น club_view.php?id=N) ให้สมาชิก
  2. สมาชิกกด "สมัครเข้าร่วม" → สถานะ pending
  3. เจ้าของชมรม approve/reject ในหน้า club_manage.php

Roles ในชมรม

💡 Auto-link ทีม

เมื่อสมาชิกของชมรมสมัครแข่ง — ระบบใช้ find_club_by_name() (case-insensitive) เพื่อ auto-link ทีมกับชมรมโดยอัตโนมัติ

4.4 หน้าโปรไฟล์ชมรม (Club View)

club view

รูปที่ 4.4 — club_view.php — ใครก็เห็นได้

ส่วนประกอบ

4.5 Association Tournament Mode

โหมดพิเศษสำหรับทัวร์ระดับสมาคม — มีรุ่นอายุ + draw system แบบ BWF

ความต่างจาก Web Mode

FeatureWeb ModeAssociation Mode
รุ่นอายุ✅ บังคับยืนยันตัวตน
การจัด Drawกลุ่ม/น็อกเอาต์Draw system + Seeding
Bulk import✅ CSV upload
หน้า detailmatch_detail.phpmatch_detail_association.php

Tabs ใน Association Mode

4.6 Bulk Import นักกีฬา (CSV)

สำหรับสมาคมที่ต้องลงทะเบียนนักกีฬาจำนวนมากจากระบบสมาคมเดิม

CSV Template

Columnความหมายตัวอย่าง
full_nameชื่อจริง-นามสกุลสมชาย ใจดี
dobวันเกิด YYYY-MM-DD2010-05-15
genderM/FM
id_numberเลขบัตรประชาชน1234567890123
club_nameชื่อชมรม (optional)โรงเรียน ABC
eventรายการที่สมัครชายเดี่ยว U13
partner_nameชื่อคู่ (สำหรับคู่)สมศักดิ์ ใจกล้า

ขั้นตอน

  1. เข้า assoc_bulk_import.php?id=N
  2. ดาวน์โหลด template CSV
  3. กรอกข้อมูล → save เป็น UTF-8 BOM (สำคัญ — รักษาภาษาไทย)
  4. อัปโหลด → ระบบ preview 10 แถวแรก → confirm
  5. ระบบสร้าง guest users + match_registrations
⚠️ Encoding

Excel default save เป็น ANSI/Windows-874 — ภาษาไทยจะเพี้ยน! ใช้ "Save As → CSV UTF-8" หรือ Google Sheets export CSV

4B

มุมมอง Client Owner ในหน้ารายการ

เห็นอะไร ทำอะไรได้ — เวลาเข้าหน้ารายการของตัวเอง

👨‍💼 Client Owner ที่ได้รับมอบสิทธิ์ในรายการแข่ง

4B.1 Client Owner คือใคร?

Client Owner คือผู้ใช้ที่ได้รับ "สิทธิ์เจ้าของรายการ" เฉพาะรายการแข่งใดรายการหนึ่ง (ไม่ใช่ทั้งเว็บ)

ตัวอย่างสถานการณ์

💡 ต่างจาก Staff Admin ตรงไหน?

Staff Admin = สิทธิ์ทั่วทั้งระบบ ทำได้ทุกรายการ
Client Owner = สิทธิ์เฉพาะรายการที่ได้รับมอบหมาย รายการอื่นเป็น user ปกติ

วิธีรู้ว่าคุณเป็น Client Owner ของรายการไหน

เปิดหน้ารายการ — ถ้าเห็น แท็กสีฟ้าเขียนว่า:

👨‍💼 You are viewing as: Client Owner

แท็กนี้ขึ้นใต้ชื่อรายการ บอกชัดว่าคุณกำลังดูในฐานะเจ้าของรายการ

4B.2 เมื่อเปิด "หน้ารายละเอียดรายการ" จะเห็นอะไร?

เริ่มจากบนลงล่าง:

match detail admin view

รูปที่ 4B.2 — หน้ารายการที่ Client Owner เห็น (พร้อมปุ่มจัดการพิเศษ)

ส่วนที่ "เพิ่มขึ้น" จากที่ user เห็น

ตำแหน่งสิ่งที่เห็นกดแล้วไป
มุมขวาบน🔴 ปุ่ม "ระบบบันทึกคะแนน" (เฉพาะตอนรายการ "กำลังแข่งขัน")หน้าป้อนคะแนนสด
มุมขวาบน✏️ ปุ่ม "แก้ไขข้อมูล" (ทุกสถานะ)หน้าแก้ไขรายการ
ใต้ชื่อรายการ🏷️ แท็กสีฟ้า "Client Owner"
แต่ละ tabปุ่มจัดการเพิ่มเติม (รายละเอียดด้านหน้า 4B.3 - 4B.8)

ส่วนที่เห็น "เหมือนเดิม" กับ user

4B.3 Tab "รายชื่อผู้สมัคร" — สิ่งที่ Client Owner ทำได้

นี่คือ tab ที่ Client Owner ใช้บ่อยที่สุด เพราะรวมงาน ดูผู้สมัคร + อนุมัติสลิป + ปรับสถานะ

ปุ่มและฟีเจอร์ที่เห็น (ที่ user ไม่เห็น)

➕ ปุ่ม "เพิ่มรายชื่อทีละคน"

คลิก → กล่องสีขาวเปิดขึ้นมา ใส่ข้อมูลทีม (รุ่น, ชื่อทีม, ผู้เล่นคนที่ 1, ผู้เล่นคนที่ 2, เบอร์) → กด "บันทึก"

ใช้เมื่อ: มีคนแจ้งสมัครผ่าน LINE/โทร แต่ไม่สมัครเองในเว็บ — Client Owner กรอกแทน

🔍 ปุ่ม "ตรวจสอบสลิปการชำระเงิน"

ขึ้นเมื่อรายการตั้งค่า payment เป็นแบบ Manual QR และมีสลิปรอตรวจ — ปุ่มแสดงจำนวนสลิปที่รอ (เช่น "🔍 ตรวจสอบสลิป (3)")

คลิก → ไปยังหน้า "ตรวจสอบสลิป" รายชื่อทีมที่ยังรอตรวจ

📊 ตารางผู้สมัคร — คอลัมน์เพิ่ม

นอกจากคอลัมน์ที่ user เห็น (ทีม, ผู้เล่น, รุ่น, สถานะ) — Client Owner เห็นเพิ่ม:

  • 📞 เบอร์โทรศัพท์ ของทีม
  • 📄 สลิปโอนเงิน — ปุ่ม "ดูสลิป" / "Upload"
  • 🖼️ รูปผู้เล่น (ถ้ามี) — กดดูภาพได้
  • 🔧 สถานะแบบ dropdown เลือกเปลี่ยนได้ทันที (รอชำระ, ผ่านชำระแล้ว, สำรอง, ยกเลิก)

✏️ ปุ่ม "แก้ไข" / "ลบ" ในแต่ละแถว

แก้ไขชื่อทีม, ผู้เล่น, เบอร์, รุ่น หรือลบใบสมัครได้

4B.4 Tab "ตารางแข่งขัน" — สิ่งที่ Client Owner ทำได้

ปุ่ม/ฟีเจอร์เพิ่มจาก user

🗂️ ปุ่ม "วางตารางแข่ง" (Schedule Planner)

คลิกแล้วเปิดหน้าใหม่ — ใช้สร้างตาราง: เลือกจำนวนคอร์ท, ช่วงเวลา, ระยะเวลา/แมตช์ → ระบบสร้างให้อัตโนมัติ + drag-drop ปรับเองได้

⚙️ ปุ่ม "จัดการคิวด้วยมือ"

เปิดตารางคิวให้แก้: เปลี่ยน สนาม, เวลา, เลขคิว, ทีม, คะแนน

ระวัง: ถ้าเปลี่ยนสนาม/เวลา → ระบบจะส่ง LINE แจ้งทีมทั้งคู่ทันที (ถ้าตั้ง "แจ้งเตือนเปลี่ยนสนาม" ไว้)

🔴 ปุ่ม "บันทึกคะแนน" ในแต่ละแถวคิว

ขึ้นเมื่อรายการอยู่สถานะ กำลังแข่งขัน — กดเพื่อป้อนคะแนนของคู่นั้นแบบเร็ว

🖨️ ปุ่ม "พิมพ์ใบลงคะแนน"

เปิดหน้าใหม่ — รูปแบบ A4 ใส่ลายเซ็นกรรมการ — เลือกรูปแบบ Full referee หรือ Compact 2 แมตช์/หน้า

4B.5 Tab "รอบแบ่งกลุ่ม" + "รอบน็อกเอาต์"

Tab "รอบแบ่งกลุ่ม"

📊 ปุ่ม "อัปโหลดตารางคะแนนแบบกลุ่ม"

เปิดหน้า "จัดการกลุ่ม" — ใส่ผู้เล่นลงในกลุ่ม, ป้อนคะแนน W/D/L, ระบบคำนวณ point diff + tiebreaker อัตโนมัติ

Tab "รอบน็อกเอาต์"

🌳 ปุ่ม "ตั้งค่าสายแข่ง"

เปิดหน้า Bracket Config — เลือกรูปแบบ Single/Double Elimination, กำหนด seed, generate bracket อัตโนมัติ

🏆 ปุ่ม "จัดการสายแข่ง"

เปิดหน้า "จัดการน็อกเอาต์" — แก้ไขทีมในแต่ละ slot, ป้อนคะแนน, ระบบ auto-advance ทีมชนะไปรอบถัดไปทั้งสายอัตโนมัติ

4B.6 Tab อื่น ๆ — สิ่งที่ Client Owner ทำได้

Tab "กติกา"

📜 ปุ่ม "แก้ไขกติกา" + "อัปโหลดรูปกติกา"

แก้ไขกฎการแข่ง (มี rich text editor) + อัปโหลดรูปภาพประกอบกติกาได้ — ผู้สมัครทุกคนเห็นทันทีที่อัปเดต

Tab "รูปภาพ"

📤 ปุ่ม "อัปโหลดรูปการแข่ง"

เลือกหลายไฟล์พร้อมกัน (multi-upload) → ระบบ resize อัตโนมัติ → ขึ้นในแกลเลอรี

🗑️ ปุ่ม "ลบรูป" ในแต่ละรูป

ลบรูปออกจากแกลเลอรีได้ (เฉพาะรูปของรายการนี้)

Tab "จำนวนลูกแบด"

🏸 ปุ่ม "บันทึกจำนวนลูกที่ใช้"

กรอกจำนวนลูกที่ทีมใช้ต่อแมตช์ + ราคา/ลูก → ระบบคำนวณค่าลูกที่ทีมต้องจ่ายเพิ่ม

Tab "ผลการแข่งขัน"

Client Owner ไม่ มีปุ่มแก้ผล (ปุ่มนี้สำหรับ Staff Admin/System Owner เท่านั้น) — เห็นผลแบบ read-only หลังจบรายการ

4B.7 ตารางสรุป — Client Owner ทำอะไรได้ ทำอะไรไม่ได้

✅ Client Owner ทำได้

หมวดการกระทำ
รายการแข่งแก้ไขข้อมูลรายการ (ชื่อ, วันแข่ง, สถานที่, โปสเตอร์)
เปลี่ยนสถานะรายการ (เปิด/ปิด/กำลังแข่ง/เสร็จสิ้น)
เปิด/ปิด tab visibility (กติกา, ลูกแบด, รูปภาพ, ผลแข่ง)
เปลี่ยน YouTube Live URL
ผู้สมัครเพิ่มรายชื่อทีละทีม
แก้ไข/ลบใบสมัคร
เปลี่ยนสถานะการชำระเงิน
ดูเบอร์โทร, รูปผู้เล่น, สลิปโอนเงิน
การแข่งวางตารางแข่ง (Schedule Planner)
ป้อนคะแนนสด (Live Score)
Bracketตั้งค่าสายแข่ง (Group/KO)
จัดการกลุ่ม + จัดการน็อกเอาต์
กติกาแก้ไขกฎ + อัปโหลดรูปประกอบ
รูปภาพอัปโหลด/ลบรูปการแข่ง
ลูกแบดบันทึกจำนวนลูกที่ใช้
พิมพ์พิมพ์ scoresheet A4

4B.8 ❌ Client Owner ทำไม่ได้ (ต้องใช้ Staff Admin / System Owner)

การกระทำทำไม
Import CSV ผู้สมัครจำนวนมากเครื่องมือสำหรับสมาคม ต้อง full admin
Export ผู้สมัครเป็น CSVมีข้อมูลส่วนตัว — จำกัดเฉพาะ full admin
แก้ไขผลการแข่งย้อนหลังการแก้ผลหลังจบรายการต้องผ่าน full admin
เปลี่ยนรูปแบบการชำระเงิน (manual ↔ slipok)เป็น sensitive change ต้องผ่าน OTP จาก full admin
เปลี่ยนรหัสบัญชี SlipOKเป็น secret ของระบบ
ลบรายการแข่งทั้งรายการทำได้เฉพาะ System Owner
Broadcast LINE ระดับระบบการส่งหมู่ทั้งระบบสงวนสำหรับ Staff Admin
ตรวจสอบตัวตนผู้ใช้ (Identity)ตรวจบัตรประชาชน — Staff Admin เท่านั้น
ดู Visitor Logs / Error Logsเครื่องมือ admin ของระบบ
จัดการผู้ใช้ทั้งระบบเปลี่ยน role / ลบบัญชี — System Owner
⚠️ เห็นปุ่มที่ไม่มีสิทธิ์?

ถ้ารายการมีลักษณะ "association mode" (สมาคม + รุ่นอายุ) Client Owner อาจเห็นปุ่ม Import/Export บางตัวขึ้นอยู่กับการตั้งค่า — ถ้ากดแล้วโดน "Forbidden" หมายความว่าต้องส่งคำขอผ่าน Staff Admin

4B.9 วงจรการทำงานทั่วไปของ Client Owner

ลำดับการใช้งานทั่วไปจากเปิดสมัคร → จบรายการ:

📌 ก่อนเปิดรับสมัคร

  1. เข้าหน้ารายการ → กด "แก้ไขข้อมูล"
  2. ตั้งวันแข่ง, สถานที่, อัปโหลดโปสเตอร์, ใส่ Google Map
  3. เลือก event ที่เปิด (ชายคู่, หญิงคู่ ฯลฯ)
  4. ตั้งค่า payment_mode + แสกน QR code + ค่าธรรมเนียม
  5. เปิด/ปิด tab visibility ตามต้องการ
  6. กลับมาที่หน้ารายการ → เปลี่ยนสถานะเป็น เปิดรับสมัคร

📌 ระหว่างเปิดรับสมัคร

  1. ดูที่ Tab "รายชื่อผู้สมัคร" — เห็นใครสมัครมาบ้าง
  2. กด "ตรวจสอบสลิป" — อนุมัติสลิปที่อัปโหลดมา
  3. เพิ่มทีมที่แจ้งทางอื่น (LINE/โทร) ด้วยปุ่ม "เพิ่มทีละคน"

📌 ก่อนวันแข่ง

  1. เปลี่ยนสถานะเป็น ปิดรับสมัคร
  2. ไปที่ Tab "รอบแบ่งกลุ่ม" + "รอบน็อกเอาต์" → ตั้ง bracket
  3. ไปที่ Tab "ตารางแข่งขัน" → กด "วางตารางแข่ง"
  4. พิมพ์ scoresheet + ตารางคิว

📌 วันแข่ง

  1. เปลี่ยนสถานะเป็น กำลังแข่งขัน
  2. กดปุ่ม "ระบบบันทึกคะแนน" → เปิดหน้าป้อนคะแนนสด
  3. ป้อนคะแนนแต่ละแมตช์ — ระบบ auto-advance ผู้ชนะ
  4. ถ้ามีการเปลี่ยนสนาม/เวลา → ระบบส่ง LINE แจ้งผู้เล่นอัตโนมัติ

📌 หลังจบรายการ

  1. เปลี่ยนสถานะเป็น แข่งขันเสร็จสิ้น
  2. อัปโหลดรูปการแข่งที่ Tab "รูปภาพ"
  3. ตรวจสอบจำนวนลูกที่ใช้ใน Tab "ลูกแบด"
4C

มุมมอง Contributor ในหน้ารายการ

เห็นอะไร ทำอะไรได้ — ผู้ช่วยกรรมการประจำรายการ

👷 Contributor ที่ได้รับมอบสิทธิ์ในรายการแข่ง

4C.1 Contributor คือใคร?

Contributor = "ผู้ช่วยจัดการรายการ" ที่เจ้าของรายการมอบสิทธิ์ให้ — เน้นช่วย ป้อนคะแนน + ดูข้อมูลผู้สมัคร ในรายการนั้น โดยไม่ได้สิทธิ์เรื่องเงินและสถานะรายการ

ตัวอย่างผู้ใช้ Contributor

วิธีรู้ว่าคุณเป็น Contributor

เปิดหน้ารายการ — ถ้าเห็น แท็กสีม่วง:

👷 You are viewing as: Contributor
💡 ต่างกับ Client Owner ตรงไหน?

Client Owner = "เจ้าของรายการ" จัดการได้เกือบทุกอย่าง
Contributor = "ผู้ช่วย" จัดการได้แค่บางส่วน — โดยเฉพาะ เรื่องเงินและสถานะรายการแตะไม่ได้

4C.2 เมื่อเปิด "หน้ารายละเอียดรายการ" จะเห็นอะไร?

ส่วนที่เห็นเพิ่มจาก user ทั่วไป

ตำแหน่งสิ่งที่เห็นกดแล้วไป
มุมขวาบน🔴 ปุ่ม "ระบบบันทึกคะแนน" (เฉพาะตอนรายการ "กำลังแข่งขัน")หน้าป้อนคะแนนสด
ใต้ชื่อรายการ🏷️ แท็กสีม่วง "Contributor"
แต่ละ tabปุ่มเพิ่มบางอย่าง (รายละเอียดหน้าถัดไป)

⚠️ ส่วนที่ Contributor "ไม่เห็น" (ที่ Client Owner เห็น)

4C.3 Tab "รายชื่อผู้สมัคร" — มุมมอง Contributor

✅ Contributor เห็นและทำได้

➕ ปุ่ม "เพิ่มรายชื่อทีละคน"

เพิ่มทีมใหม่ลงทะเบียนได้ — กรณีมีทีมแจ้งหน้างาน หรือเจ้าของรายการขอให้ช่วยกรอกแทน

📋 ตารางผู้สมัคร — เห็นคอลัมน์เพิ่ม

  • 📞 เบอร์โทรศัพท์ ของทีม
  • 📄 ปุ่ม "ดูสลิป" — กดดูภาพสลิปที่ทีมอัปโหลดได้ (แต่เปลี่ยนสถานะไม่ได้)
  • 🖼️ รูปผู้เล่น ดูเต็มได้

✏️ ปุ่ม "แก้ไข" ในแต่ละแถว

แก้ไขชื่อทีม, ชื่อผู้เล่น, เบอร์โทรศัพท์, รุ่น ได้ — แต่เปลี่ยนสถานะการชำระเงินไม่ได้

❌ Contributor ทำไม่ได้

⚠️ เหตุผลเชิงระบบ

การเงินและสถานะรายการเป็น "ความรับผิดชอบของเจ้าของรายการ" — Contributor ออกแบบมาให้ช่วยเรื่องการแข่งจริง ไม่ใช่เรื่องเงิน

4C.4 Tab "ตารางแข่งขัน" + "รอบแบ่งกลุ่ม" + "น็อกเอาต์"

Tab "ตารางแข่งขัน"

🔴 ปุ่ม "บันทึกคะแนน" ในแต่ละแถวคิว

ขึ้นเมื่อรายการ กำลังแข่งขัน — งานหลักของ Contributor: ป้อนคะแนนของแมตช์ที่กำลังเล่น

⚙️ ปุ่ม "จัดการคิว"

เปลี่ยนสนาม/เวลา/เลขคิว/คะแนนของแมตช์ใดก็ได้ — ใช้เมื่อต้องสลับคิวกระทันหัน

🖨️ ปุ่ม "พิมพ์ใบลงคะแนน"

พิมพ์ scoresheet เพื่อแจกกรรมการแต่ละสนาม

Tab "รอบแบ่งกลุ่ม"

📊 ปุ่ม "อัปโหลดตารางคะแนนแบบกลุ่ม (Admin)"

เปิดหน้าจัดการกลุ่ม — ป้อนคะแนนแต่ละแมตช์ของกลุ่ม ระบบคำนวณตารางคะแนนให้

Tab "รอบน็อกเอาต์"

Contributor เห็น bracket tree เต็มและสามารถ ป้อนคะแนนแต่ละแมตช์ได้ — แต่ "ตั้งค่าสายแข่ง" (Bracket Config) เป็นปุ่มของ Client Owner เท่านั้น

4C.5 Tab อื่น ๆ — มุมมอง Contributor

Tab "กติกา"

📜 ปุ่ม "แก้ไขกติกา" + "อัปโหลดรูป"

แก้ไขกติกาและอัปโหลดรูปประกอบได้ — เหมือน Client Owner

Tab "รูปภาพ"

📤 ปุ่ม "อัปโหลดรูปการแข่ง"

อัปโหลดรูปได้ — งานที่ช่างภาพรายการมักทำ

🗑️ ปุ่ม "ลบรูป"

ลบรูปได้

Tab "จำนวนลูกแบด"

🏸 ปุ่ม "บันทึกจำนวนลูก"

กรอกจำนวนลูกที่ทีมใช้ต่อแมตช์

Tab "ผลการแข่งขัน"

Contributor ไม่ มีปุ่มแก้ผลย้อนหลัง (เป็นของ full admin เท่านั้น) — เห็นผลแบบ read-only หลังจบรายการ

4C.6 ตารางสรุป — Contributor ทำอะไรได้ ทำไม่ได้

✅ Contributor ทำได้

หมวดการกระทำ
ผู้สมัครเพิ่มทีมใหม่ทีละคน
แก้ไขข้อมูลทีม (ชื่อ, ผู้เล่น, เบอร์, รุ่น)
ดูเบอร์โทร, รูปผู้เล่น, สลิป
การแข่งป้อนคะแนนสดของแต่ละแมตช์
จัดการคิวด้วยมือ (เปลี่ยนสนาม/เวลา/ลำดับ)
พิมพ์ scoresheet
กลุ่มป้อนคะแนนรอบแบ่งกลุ่ม
น็อกเอาต์ป้อนคะแนนรอบน็อกเอาต์ (auto-advance ผู้ชนะ)
กติกาแก้ไข + อัปโหลดรูปประกอบ
รูปภาพอัปโหลด/ลบรูปการแข่ง
ลูกแบดบันทึกจำนวนลูกที่ใช้

❌ Contributor ทำไม่ได้

การกระทำต้องไปหาใคร
เปลี่ยน สถานะการชำระเงิน ของทีมClient Owner / Staff Admin
อนุมัติ/ปฏิเสธ สลิปClient Owner / Staff Admin
แก้ไข ข้อมูลรายการ (ชื่อ, วัน, สถานที่, payment mode)Client Owner / Staff Admin
เปลี่ยน สถานะรายการ (เปิด/ปิด/แข่ง/เสร็จสิ้น)Client Owner / Staff Admin
ตั้งค่าสายแข่ง (Bracket Config)Client Owner / Staff Admin
Import CSVStaff Admin
Export ผู้สมัคร CSVStaff Admin
แก้ผลย้อนหลังStaff Admin / System Owner
ลบรายการแข่งSystem Owner

4C.7 วงจรการทำงานของ Contributor ในวันแข่ง

Contributor มักทำงานช่วงวันแข่งเป็นหลัก — flow ทั่วไป:

📌 ก่อนวันแข่ง (1-2 วัน)

  1. เข้าหน้ารายการที่ได้รับมอบหมาย → ตรวจ tab "ตารางแข่งขัน"
  2. พิมพ์ scoresheet จากปุ่ม "พิมพ์ใบลงคะแนน" — แจกกรรมการแต่ละสนาม
  3. ดู tab "รายชื่อผู้สมัคร" — ทำความคุ้นเคยกับชื่อทีม

📌 วันแข่ง — งานหน้างาน

  1. มีทีมมาแจ้งสมัครหน้างาน → ใช้ปุ่ม "เพิ่มทีละคน" ใน tab "รายชื่อผู้สมัคร"
    • (แจ้งเจ้าของรายการให้ตั้งสถานะการชำระเงินให้ — Contributor ทำเองไม่ได้)
  2. ระหว่างแข่ง — เปิด "ระบบบันทึกคะแนน":
    • เลือกคู่ที่กำลังแข่ง
    • กรอกคะแนน (รับได้ทั้ง "21 15 21 10" หรือ "21-15 21-10")
    • กดบันทึก → ระบบคำนวณตารางคะแนน + advance ผู้ชนะอัตโนมัติ
  3. ถ้าต้องสลับคิวกระทันหัน → ใช้ "จัดการคิว" ใน tab ตารางแข่ง
  4. ถ่ายรูปการแข่ง → อัปโหลดผ่าน tab "รูปภาพ"
  5. นับลูกที่ใช้ → บันทึกใน tab "จำนวนลูกแบด"

📌 หลังจบรายการ

Contributor ไม่ต้องทำอะไรเพิ่ม — Client Owner / Staff Admin จะเป็นคนเปลี่ยนสถานะรายการเป็น แข่งขันเสร็จสิ้น

💡 สรุปสั้น

Contributor = "มือป้อนคะแนน + ผู้ช่วยหน้างาน"
ทำทุกอย่างที่ไม่เกี่ยวกับ "เงิน" และ "สถานะรายการ"

4C.8 ตารางเปรียบเทียบ 3 บทบาทในหน้ารายการ

การกระทำ User
(ผู้สมัคร)
Contributor
(ผู้ช่วย)
Client Owner
(เจ้าของรายการ)
ดูข้อมูลรายการ + กติกา
สมัครเข้าแข่ง
ดูตารางแข่ง + ผล
ดูเบอร์โทรของทีมอื่น
ดูสลิปโอนเงินของทีมอื่น
เพิ่มทีมเข้าแข่ง
แก้ไขข้อมูลทีม❌ (ของตัวเองได้)
ป้อนคะแนนสด
จัดการคิว/สนาม/เวลา
พิมพ์ scoresheet
อัปโหลด/ลบรูปการแข่ง
แก้ไขกติกา
บันทึกจำนวนลูก
เปลี่ยนสถานะการชำระเงิน
อนุมัติ/ปฏิเสธสลิป
แก้ไขข้อมูลรายการ
เปลี่ยนสถานะรายการ
ตั้งค่าสายแข่ง (Bracket)
วางตารางแข่ง (Schedule)
05

ระบบ LINE Bot

คำสั่ง + Flow ผูกบัญชี + Reminder อัตโนมัติ

📱 สำหรับทุก Role

5.1 ภาพรวม LINE Bot

Bot LINE Official Account ทำงานควบคู่กับเว็บ สื่อสารกับผู้เล่นผ่าน LINE ทุกขั้นตอน

ฟีเจอร์หลัก

🔗 ผูกบัญชี

PIN 6 หลัก เชื่อม LINE UID กับ user account

📅 ดูตารางตัวเอง

พิมพ์ "แมตของฉัน" → ดูทุก tournament ที่สมัคร

📍 ดูคิว

พิมพ์ "แมตที่เท่าไร" → ดูคิวที่กำลังแข่ง

⏰ Reminder

แจ้งก่อนแข่ง 30 นาที + 1 ชั่วโมง อัตโนมัติ

📢 Broadcast

รับประกาศจากแอดมิน + morning broadcast

💰 Payment

แจ้งสลิปอนุมัติ/ปฏิเสธ + LINE Flex Message

เพิ่มเพื่อน

สแกน QR code ในหน้า profile.php หรือเสิร์ช @thaibadtournaments ใน LINE

5.2 คำสั่งทั้งหมด

คำสั่งผลลัพธ์ต้อง login?
ลงทะเบียน [PIN]ผูก LINE กับบัญชีในเว็บมี PIN จากเว็บ
สถานะแสดงว่าผูกบัญชีไหน + UID
แมตของฉันlist ทุก tournament ที่สมัคร + status
แมตที่เท่าไรดูคิวที่กำลังแข่ง + แมตช์ถัดไป (ถ้าแข่งวันนี้)
ตรวจสอบการแข่งขันMulti-step: เลือก tournament → เลือก event → ดูแมตช์
ยกเลิกcancel state machine
help / เมนูแสดงคำสั่งทั้งหมด

การ Match แบบ Fuzzy

Bot รองรับการพิมพ์ที่ไม่เป๊ะ:

5.3 Flow ผูกบัญชี (Account Linking)

Sequence Diagram
User                Web                 LINE Bot           DB
 │                   │                     │                │
 │── เข้า profile ──>│                     │                │
 │                   │── สร้าง PIN ────────────────────────>│
 │                   │<── PIN "123456" ──────────────────── │
 │<── PIN + QR ──────│                     │                │
 │                                         │                │
 │── สแกน QR + Add Friend ────────────────>│                │
 │                                         │── ลงทะเบียน ───>│ (check PIN)
 │                                         │<── valid ──────│
 │<── "ผูกบัญชีสำเร็จ!" ─────────────────── │── update user ─>│
                                                            (line_uid)

ข้อกำหนด

5.4 Reminder อัตโนมัติ

ระบบ cron_notify_matches.php รันทุก 2-5 นาที

Logic

  1. หา tournaments ที่อยู่สถานะ กำลังแข่งขัน วันนี้
  2. คำนวณ current_leading match_no + จำนวนสนาม N
  3. ส่ง reminder 1 ชม.: match_no ใน range [current_leading, current_leading + 2N]
  4. ส่ง reminder 30 นาที: match_no ใน range [current_leading, current_leading + N]
  5. Mark flag notify_1h_sent, notify_30m_sent เพื่อไม่ส่งซ้ำ

ตัวอย่างข้อความ

🏸 แจ้งเตือนการแข่ง
รายการ: VENSON Kamphaengphet 2026
🎾 ทีม: สมชาย / สมศักดิ์
🆚 vs: สมหญิง / สมศรี
🏟 สนาม: 2
⏰ เวลา: 14:30 (อีก 30 นาที)
📍 คิวที่: 18

กรุณามาที่สนามก่อนเวลา 15 นาที
💡 ปิด reminder

ผู้เล่นสามารถปิด notify_match_reminder ใน notification_settings.php ต่อรายการได้

5.5 Morning Broadcast (สรุปวันแข่ง)

ส่งสรุปตารางของผู้เล่นแต่ละคนตอน 06:00 ของวันแข่ง — 1 ข้อความ/คน

ตัวอย่างข้อความ

🌅 สวัสดียามเช้า สมชาย!
วันนี้คุณมีแข่ง 3 แมตช์

📍 รายการ: VENSON Kamphaengphet 2026
1️⃣ 09:00 ⚡ สนาม 2 ⚡ คิว 5
   ชายคู่ U35 — vs สมหมาย/สมศักดิ์

2️⃣ 11:30 ⚡ สนาม 1 ⚡ คิว 12
   คู่ผสม — vs ทีมเหลือง

3️⃣ 14:00 ⚡ สนาม 3 ⚡ คิว 18
   ชายเดี่ยว — vs ทีมแดง

ขอให้โชคดี! 🍀

ส่งผ่าน Flex Message ของ LINE — UI สวยงาม คลิกแต่ละ match เพื่อเข้าหน้า match_detail ได้

06

สำหรับ System Owner

การตั้งค่าระบบ + Cron + APIs + Migrations

⚙️ Role: system_owner

6.1 ภาพรวมหน้าที่ของ System Owner

ไฟล์สำคัญที่ควรรู้

ไฟล์หน้าที่
app_config.phpconfig public (อยู่ใน webroot)
app_secret.phpsecrets — นอก webroot
db.phpเชื่อมต่อ MySQL
smtp_config.phpSMTP server credentials
line_config.phpLINE Bot channel access token
lib/bootstrap.phpโหลด wide ทุก session

6.2 ตั้งค่า SMTP (Email)

ระบบใช้ PHPMailer ส่ง email สำหรับ: OTP, reset password, error alerts, broadcast

ตั้งค่าใน smtp_config.php

<?php
return [
  'host' => 'smtp.gmail.com',
  'port' => 587,
  'username' => '[email protected]',
  'password' => 'xxxx xxxx xxxx xxxx', // App password
  'encryption' => 'tls',
  'from_email' => '[email protected]',
  'from_name' => 'ThaibadTournaments',
];
⚠️ Gmail App Password

หากใช้ Gmail ต้อง enable 2FA ก่อน → สร้าง App Password ที่ myaccount.google.com/apppasswords

ทดสอบ

เปิด test_error_monitor.php → จะส่ง test email ไป admin email

6.3 ตั้งค่า LINE Bot

อ่านเอกสาร: Line_Admin_Setup.md, Line_Noti.md, Line_User_Guide.md

ขั้นตอน

  1. สร้าง LINE Official Account ที่ developers.line.biz
  2. เปิด Messaging API
  3. คัดลอก: Channel Access Token + Channel Secret
  4. กรอกใน line_config.php:
    return [
      'channel_access_token' => 'xxxxx...',
      'channel_secret' => 'xxxxx...',
      'liff_id' => 'xxxxx-xxxxx',
    ];
  5. ตั้ง Webhook URL: https://thaibadtournaments.com/badminton/line_webhook.php
  6. เปิด "Use webhook" + ปิด "Auto-reply messages"
  7. เพิ่มเพื่อนเอง → ทดสอบ "สถานะ"

LIFF (LINE Front-end Framework)

สำหรับ login ผ่าน LINE ในเว็บ — สร้าง LIFF app type=Full → URL ชี้ไปที่ auth_line.php

6.4 ตั้ง Cron Jobs

ระบบมี 2 cron jobs หลักที่ต้องตั้งใน server

1. Match Reminder (ทุก 2-5 นาที)

*/3 * * * * curl -s -H "X-Cron-Secret: YOUR_SECRET" \
  https://thaibadtournaments.com/badminton/cron_notify_matches.php \
  >> /var/log/thaibad_cron.log 2>&1

2. Morning Broadcast (06:00 ทุกวัน)

0 6 * * * curl -s -H "X-Cron-Secret: YOUR_SECRET" \
  "https://thaibadtournaments.com/badminton/admin_morning_broadcast.php?auto=1&date=TODAY"

3. Cleanup เก่า (รายสัปดาห์)

0 3 * * 0 php /path/to/cleanup_old_logs.php
🔒 X-Cron-Secret

ตั้ง CRON_SECRET ใน app_secret.php → ใช้เป็น header X-Cron-Secret เพื่อกัน cron URL ถูกเรียกจากภายนอก

6.5 ตั้งค่า SlipOK API

สำหรับการตรวจสลิปอัตโนมัติ

ขั้นตอน

  1. สมัครที่ slipok.com → เลือกแพ็กเกจ
  2. เพิ่มสาขา (Branch) → ได้ branch_id
  3. สร้าง api_key
  4. ตั้งบัญชีรับโอนของแต่ละ tournament ใน edit_match.php → ฟิลด์:
    • slipok_branch_id
    • slipok_api_key
    • payment_account_name — ต้องตรงกับใน SlipOK

API Call

lib/slipok.php ส่ง POST ไปยัง https://api.slipok.com/api/line/apikey/{branch_id} พร้อมรูปสลิป

Response Codes

6.6 ตั้งค่า Gemini TTS API

ขั้นตอน

  1. ไปที่ ai.google.dev → สร้าง API Key
  2. เก็บใน app_secret.php:
    'GEMINI_API_KEY' => 'AIzaSy...',
  3. Default model: gemini-2.5-flash-preview-tts + voice Kore (Thai)

Quota

การจัดการ Cache

ระบบเก็บไฟล์เสียงใน /uploads/tts_cache/SHA256(text+voice).wav

6.7 Database Migrations

เมื่ออัปเดตระบบ — รัน migration scripts ใน root ของ project

17 Migration Scripts

Scriptเพิ่มอะไร
migrate_2fa_tables.php2FA + backup codes
migrate_payment_system.phppayment_mode, slipok, slip status
migrate_clubs.phpclubs, members, banner_designs
migrate_lockout.phpfailed_login_attempts, lockout_until
migrate_add_gender.phpusers.gender (M/F)
migrate_age_categories.phpavailable_age_categories JSON
migrate_identity_verification.phpidentity_verified + id_card_image
migrate_errors_log.phperrors_log table
migrate_line_chat_states.phpstate machine ของ webhook
migrate_line_link_pins.phpPIN 6 หลักผูก LINE
migrate_notify_flags.phpnotify_* flags ต่อ tournament
migrate_calendar_province.phpfilter จังหวัด
migrate_calendar_map_url.phpGoogle Maps URL
migrate_match_tab_visibility.phptab_*_enabled flags
migrate_match_permissions_role.phpper-tournament role
migrate_tts_cache.phptts_quota_daily + cache table
migrate_cleanup_legacy_roles.phpcleanup เก่า ๆ
⚠️ Backup ก่อนรัน Migration

ใช้ mysqldump backup ก่อนรันทุกครั้ง — ไม่มี rollback automatic

6.8 ระบบ Real-time Co-work

อ่านเอกสาร Real_time_Co_work.md

Editing Presence

ตาราง editing_presence:

API ที่เกี่ยวข้อง

Polling Strategy

Frontend poll ทุก 2 วินาที — ไม่ใช้ WebSocket (เพื่อง่ายในการ host บน shared hosting)

07

Photo Face Search

ค้นหารูปการแข่งด้วยใบหน้าตัวเอง (AI Face Recognition)

🚧 อยู่ระหว่างพัฒนา • UI พร้อม • Backend รอ Proxmox

7.1 ภาพรวมและสถานะ

🚧 สถานะ: อยู่ระหว่างพัฒนา

UI ของฟีเจอร์นี้ออกแบบและ deploy แล้ว — ผู้ใช้สามารถเข้าหน้า photo_search.php?id=N ดูแกลเลอรีรูปได้ แต่ปุ่ม "อัปโหลด selfie" ยังถูกปิดอยู่จนกว่า Face API Server บน Proxmox จะติดตั้งเสร็จ

เป้าหมาย

ผู้เล่นต้องการดูรูปของตัวเองในรายการแข่ง — แทนที่จะต้อง scroll หารูปทั้งหมด ระบบจะให้ อัปโหลด selfie 1 รูป → AI หารูปที่มีใบหน้าใกล้เคียงให้ทั้งหมด

เทคโนโลยีที่จะใช้

Componentเทคโนโลยี
Face DetectionInsightFace (RetinaFace + ArcFace)
Embedding512-dim vector ต่อใบหน้า
SimilarityCosine similarity (threshold ~0.5)
BackendPython Flask API บน Ubuntu 22.04
HardwareNVIDIA RTX 3060 (Proxmox passthrough)

7.2 UI Design (เลียนแบบจากโค้ดจริง)

หน้าจอที่ออกแบบไว้ตาม photo_search.php:

Mockup — photo_search.php?id=N
← กลับหน้ารูปภาพ 🔍 ค้นหารูปด้วยใบหน้า VENSON Kamphaengphet 2026 — รูปทั้งหมด 142 รูป 🚧 ระบบค้นหาด้วยใบหน้ากำลังอยู่ระหว่างพัฒนา ดูแกลเลอรีด้านล่างไปก่อนได้ 📷 อัปโหลดเซลฟี่เพื่อค้นหารูปของคุณ รองรับ JPG, PNG, WEBP · ขนาดไม่เกิน 10 MB 📸 แกลเลอรี (142 รูป)

รูปที่ 7.2 — UI ปัจจุบัน (Backend ปิด) สร้างจากการอ่านโค้ด photo_search.php

7.3 Flow ที่วางไว้

ฝั่ง User

  1. เข้าหน้า match_detail.php?id=N → tab "รูปภาพ"
  2. กดปุ่ม "🔍 ค้นหารูปของฉัน" → ไป photo_search.php
  3. กดกล่อง "อัปโหลดเซลฟี่"
  4. เลือก/ถ่ายรูป selfie (camera permission)
  5. กด "ค้นหา" → loading 3-10 วินาที
  6. แสดงผลลัพธ์:
    • 🎯 รูปที่มีใบหน้าตรง (similarity > 0.65) — top match
    • 📷 รูปอื่นที่คล้าย (0.50 - 0.65)
    • ปุ่ม "ดาวน์โหลดทั้งหมด" (ZIP)

ฝั่ง Server

Architecture
Browser              VM1 (PHP)              VM2 (Face API)         GPU
  │                     │                         │                  │
  ├── POST selfie ─────>│                         │                  │
  │                     ├── proxy w/ tournament ─>│                  │
  │                     │                         ├── detect face ──>│
  │                     │                         │<── embedding ────│ RTX 3060
  │                     │                         │   (512-d vector) │
  │                     │                         │                  │
  │                     │                         ├── compare with ─>│
  │                     │                         │   all photo emb. │
  │                     │                         │<── ranked list ──│
  │                     │<── JSON results ────────│                  │
  │<── HTML render ─────│                         │                  │

API Spec ที่วางไว้

POST http://192.168.1.102:5000/api/face/search
Content-Type: multipart/form-data

selfie: <file>
tournament_id: 3
threshold: 0.5

Response:
{
  "status": "ok",
  "matches": [
    {"photo_id": 142, "filename": "img001.jpg", "similarity": 0.87},
    {"photo_id": 156, "filename": "img089.jpg", "similarity": 0.74},
    ...
  ],
  "processing_time_ms": 2340
}

7.4 Setup ของ Proxmox (ที่กำลังจัดทำ)

อ่านเอกสารเต็มที่ Proxmox_Setup.md

Hardware

ส่วนรายละเอียด
CPUAMD Ryzen 9 5900X (12C/24T)
RAM48 GB
GPU #1NVIDIA RTX 3060 (passthrough → VM2)
GPU #2Quadro P1000 (host)

VM Layout

VMหน้าที่vCPURAMDiskIP
VM1Web (Apache+PHP+MySQL+LINE)46 GB50 GB192.168.1.101
VM2Face Detection API816 GB80 GB192.168.1.102

Setup สรุป VM2

  1. ติดตั้ง Ubuntu 22.04 LTS
  2. ติดตั้ง NVIDIA driver + CUDA 12
  3. ติดตั้ง Python 3.10 + virtualenv
  4. pip install insightface flask onnxruntime-gpu opencv-python
  5. เขียน Flask API endpoint /api/face/search
  6. เปิด firewall port 5000 (เฉพาะ LAN)
  7. ทดสอบเรียกจาก VM1 → match กับรูปทดสอบ

7.5 ข้อพิจารณา Privacy + Performance

🔒 Privacy

⚡ Performance Target

🚦 Rate Limiting

🚨 จริยธรรม

ระบบ search ได้เฉพาะ รูปของรายการที่ผู้ใช้สมัครเข้าแข่งเท่านั้น — ไม่ใช่รูปทั้งระบบ และไม่อนุญาตให้ admin export embeddings ออกนอก server

A

ภาคผนวก

FAQ, 4 สถานะรายการ, คีย์ลัด, ติดต่อ Support

📖 Reference สำหรับทุก Role

A.1 คำถามที่พบบ่อย (FAQ)

🔑 บัญชี + ลงทะเบียน

Q: ลืม username/email — ทำยังไง?
A: ติดต่อแอดมินผ่าน LINE Bot พิมพ์ "สถานะ" — ระบบจะตอบ UID และอีเมลที่ผูกไว้

Q: ผูก LINE ไม่ได้ — PIN expire — ทำใหม่ยังไง?
A: เข้าหน้าโปรไฟล์ → กด "สร้าง PIN ใหม่" → PIN ใหม่อายุ 15 นาที

Q: เปลี่ยนชื่อในระบบได้ไหม?
A: ได้ แต่ต้องผ่าน OTP email และต้องตรงกับบัตรประชาชน (ถ้า verified แล้ว)

🏆 การสมัครแข่ง

Q: สมัครแล้วยกเลิกได้ไหม?
A: ยกเลิกได้ตราบเท่าที่รายการยังเป็น เปิดรับสมัคร หากชำระเงินแล้ว — แอดมินจะคืนตามนโยบายแต่ละรายการ

Q: คู่ที่ชวนปฏิเสธ — ใบสมัครยังอยู่ไหม?
A: ใบสมัครจะเข้าสถานะ "รอคู่" — คุณเปลี่ยนคู่ได้ภายในเวลาที่กำหนด

Q: สมัครชื่อ guest (ไม่มีบัญชี) ได้ไหม?
A: ได้ — แต่ guest จะไม่ได้รับ LINE reminder อัตโนมัติ ต้องดูตารางในเว็บเอง

💰 ชำระเงิน

Q: SlipOK ตรวจสลิปไม่ผ่าน เพราะอะไร?
A: เหตุผลที่พบบ่อย: (1) ชื่อผู้รับโอนไม่ตรง (2) ยอดไม่ตรง (3) สลิปซ้ำ (4) สลิปอ่านไม่ออก (เบลอ/มืด)

Q: โอนเงินแล้วลืมอัปโหลดสลิป?
A: กลับเข้าหน้ารายการ → tab "รายชื่อผู้สมัคร" → หาแถวของคุณ → "อัปโหลดสลิป" — ยังทำได้จนกว่ารายการจะ ปิดรับสมัคร

A.1 FAQ (ต่อ)

📱 LINE Bot

Q: Bot ไม่ตอบกลับ — เพราะอะไร?
A: เช็ค 4 จุด: (1) เพิ่ม Bot เป็นเพื่อนแล้วยัง (2) ผูกบัญชีหรือยัง (3) คำสั่งถูกต้องไหม (4) Webhook ของระบบทำงานปกติไหม (System Owner ตรวจที่ admin_errors.php)

Q: ทำไมไม่ได้รับ reminder?
A: ตรวจ 3 อย่าง: (1) ผูก LINE แล้ว (2) เปิด notify_match_reminder ในตั้งค่า (3) ตอนแข่งรายการอยู่สถานะ กำลังแข่งขัน

🏟 วันแข่ง

Q: หาคิวตัวเองไม่เจอ — ทำยังไง?
A: 3 ทาง: (1) พิมพ์ "แมตที่เท่าไร" ใน LINE Bot (2) ดูที่ tab "ตารางแข่งขัน" ในหน้ารายการ (3) ฟัง TTS Court Call

Q: คะแนนผิด/ผลแข่งผิด — แก้ยังไง?
A: แจ้งแอดมิน — แอดมินมีสิทธิ์แก้คะแนนได้ตลอดเวลา (รวมถึงหลังจบรายการ)

📸 รูปภาพ

Q: Face Search ใช้ได้เมื่อไร?
A: รออัปเดต — กำลัง setup Proxmox VM2 + RTX 3060 ดู ส่วนที่ 7

Q: ลบรูปของฉันออกได้ไหม?
A: ติดต่อแอดมินของรายการ — มีสิทธิ์ลบเฉพาะคนนั้น

A.2 ตารางอ้างอิง 4 สถานะรายการแข่ง

Action เปิดรับสมัคร ปิดรับสมัคร กำลังแข่งขัน เสร็จสิ้น
ดูรายการ
สมัครเข้าแข่ง
อัปโหลดสลิป⚠️ (ภายในกำหนด)
ยกเลิกการสมัคร
ดูรายชื่อผู้สมัคร
ดูสายแข่ง
ดูตารางการแข่ง
ดูคะแนนสด
รับ LINE reminder
ดูผลย้อนหลัง⚠️ (บางส่วน)
ดูรูปภาพ
Admin: จัดสาย⚠️⚠️
Admin: ป้อนคะแนน⚠️
Admin: อนุมัติสลิป⚠️
Admin: Broadcast LINE⚠️

✅ = ทำได้   ❌ = ทำไม่ได้   ⚠️ = ทำได้แต่มีเงื่อนไข

A.3 คีย์ลัด (Keyboard Shortcuts)

ทั่วไป

Ctrl + Pพิมพ์/บันทึก PDF
F11Fullscreen (สำหรับ scoreboard kiosk)
Escปิด lightbox/modal

หน้าป้อนคะแนน (admin_live_match.php)

Tabไปช่องถัดไป
Enterบันทึก + ไปแมตช์ถัดไป
Escยกเลิกการแก้ไข

LINE Bot Commands (สรุป)

ลงทะเบียน [PIN]ผูกบัญชี
สถานะเช็คการเชื่อมต่อ
แมตของฉันตารางแข่งทั้งหมด
แมตที่เท่าไรคิวปัจจุบัน
ตรวจสอบการแข่งขันmulti-step lookup
ยกเลิกcancel state
เมนูแสดง help

A.4 ปัญหาที่พบบ่อย + วิธีแก้

"บัญชีถูกล็อก"

ใส่ password ผิด 5 ครั้ง → ล็อก 15 นาที — รอครบเวลาแล้วลองใหม่ หรือใช้ "ลืมรหัสผ่าน" reset

"CSRF token mismatch"

session expired — refresh หน้า + login ใหม่

SlipOK "ชื่อผู้รับไม่ตรง"

ตรวจ payment_account_name ใน edit_match.php ให้ตรงกับชื่อบัญชีที่ระบุใน SlipOK dashboard

LINE Webhook ไม่ทำงาน

  1. Console: developers.line.biz → ตรวจ webhook URL
  2. กด "Verify" → ต้องได้ 200 OK
  3. เช็ค admin_errors.php ดู error
  4. เช็ค HMAC signature secret ใน line_config.php

TTS เสียงไม่ออก

  1. เช็ค Gemini API quota ที่ ai.google.dev
  2. ลอง fallback Google Translate TTS
  3. เช็คสิทธิ์ folder /uploads/tts_cache/ ต้อง writable

Score ไม่ advance ไปรอบถัดไป

เช็ค bracket_config: ทีม seed ทุกที่ต้องมีค่า team1_cond / team2_cond ที่ map ได้ — ดูรายละเอียดใน admin_live_match_helpers.php

A.5 ติดต่อ Support

📧 Email

[email protected]
(System Owner)

📱 LINE

@thaibadtournaments
(Official Account)

🌐 Website

thaibadtournaments.com

🐛 รายงาน Bug

ส่ง screenshot + URL
ไปที่ email ด้านบน

ก่อนแจ้งปัญหา กรุณาเตรียม


📕 จบคู่มือ ThaibadTournaments.com v1.0
จัดทำ 15 พฤษภาคม 2569 จากการอ่านโค้ดและ Screenshot จริงทั้งระบบ