ระบบจัดการทัวร์นาเมนต์แบดมินตัน — ครบทุกฟีเจอร์
🌐 thaibadtournaments.com
รู้จักโครงสร้าง กลุ่มผู้ใช้ และวงจรการทำงานของระบบ
ThaibadTournaments.com คือแพลตฟอร์มจัดการการแข่งขันแบดมินตันแบบครบวงจร ตั้งแต่ผู้เล่นสมัครเข้าแข่ง ไปจนถึงการแสดงผลคะแนนสดผ่าน OBS

รูปที่ 1.1 — หน้าแรกของเว็บ thaibadtournaments.com
รองรับ Round-robin + Knockout (Single/Double elim) อัตโนมัติ advance ทีมชนะ
ป้อนคะแนนสด → อัปเดต scoreboard + OBS overlay ใน 1 วินาที
3 โหมด: manual, QR, SlipOK API ตรวจสลิปอัตโนมัติ
"แมตของฉัน", "แมตที่เท่าไร" + reminder อัตโนมัติ 30 นาที / 1 ชม.
Gemini AI อ่านชื่อสนาม + ผู้เล่น มีการ cache เสียง
ค้นหารูปด้วย selfie (อยู่ระหว่าง setup AI)
ระบบมีการแบ่งสิทธิ์ผู้ใช้ออกเป็น 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 | นักกีฬาทั่วไป |
นอกจาก global role แล้ว ระบบยังมี per-tournament permission — เจ้าของรายการสามารถมอบสิทธิ์ scorer, verifier, viewer ให้บางคนเฉพาะทัวร์ของตัวเองได้
รายการแข่งทุกรายการในระบบจะอยู่ในหนึ่งใน 4 สถานะนี้ ส่งผลต่อสิทธิ์การสมัครและการแสดงผล
| สถานะ | หมายความว่า | ผู้เล่นทำอะไรได้ | ผู้จัดทำอะไรได้ |
|---|---|---|---|
| เปิดรับสมัคร | รายการประกาศแล้ว เปิดให้ลงทะเบียน | สมัคร, ชวนคู่, ชำระเงิน, ยกเลิก | ดูผู้สมัคร, อนุมัติสลิป, จัดสาย |
| ปิดรับสมัคร | หมดเวลาสมัครแล้ว รอเตรียมการแข่ง | ดูรายชื่อ, ดูสาย | จัดสาย, พิมพ์ scoresheet, plan ตาราง |
| กำลังแข่งขัน | วันแข่งจริง — ใช้งาน live scoring | ดูคิว, ดูคะแนนสด, รับ reminder LINE | ป้อนคะแนน, advance ผู้ชนะ, OBS overlay |
| แข่งขันเสร็จสิ้น | จบการแข่งขัน — ดูผลย้อนหลังได้ | ดูผล, ดูสถิติ, ดูรูปภาพ | แก้ผล (ถ้าผิด), upload รูป |

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

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

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

แข่งขันเสร็จสิ้น — Rotary Championship 2026
สถานะเปลี่ยนได้เฉพาะ Admin / เจ้าของรายการ ผ่านหน้า edit_match.php ระบบไม่เปลี่ยนอัตโนมัติตามวันที่ — ผู้จัดต้องเปลี่ยนเอง
[1] สมัครสมาชิก → [2] ผูก LINE → [3] ตั้งค่าโปรไฟล์ + ยืนยันตัวตน
↓
[4] ดูปฏิทินทัวร์ → [5] สมัครรายการ → [6] ชวนคู่ → [7] ชำระเงิน
↓
[8] รอ reminder LINE → [9] เช็คอินวันแข่ง → [10] ดูคิว/คะแนนสด
↓
[11] รับรางวัล + ดูสถิติย้อนหลัง
[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] อัปโหลดรูป

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

รูปที่ 1.5.2 — ดูทุกรายการในมุมมองปฏิทินรายเดือน + รายการที่เปิดรับสมัคร
สี dot บนปฏิทินบอกสถานะ:
วิธีใช้งานทุกฟีเจอร์สำหรับ User ทั่วไป
การสมัครสมาชิกใช้เวลา ~2 นาที ทำได้ 3 ช่องทาง:

รูปที่ 2.1 — หน้า signup.php
thaibadtournaments.com/badminton/signup.phpระบบจะเช็ค check_username.php, check_email.php, check_name_duplicate.php แบบ realtime — ถ้า username/email/ชื่อ ซ้ำ จะเตือนทันทีก่อน submit
ระบบใช้ชื่อจริงในการแมตช์ผู้เล่นกับการสมัครแข่งและ ranking — ใช้ชื่อเล่นไม่ได้

รูปที่ 2.2 — หน้า login.php — มี 3 ช่องทาง
_csrf token
การผูก LINE สำคัญมาก เพราะระบบจะส่ง reminder ก่อนแข่ง 30 นาที + 1 ชั่วโมง ผ่าน LINE

รูปที่ 2.3 — หน้า link_line.php แสดง QR + PIN 6 หลัก
@thaibadtournaments (สแกน QR)ลงทะเบียน 123456 ในแชท (แทน 123456 ด้วย PIN ของคุณ)PIN ใช้ได้ครั้งเดียวเท่านั้น, expire ใน 15 นาที — ถ้าไม่ใช้ทัน ต้องสร้างใหม่ ระบบจะเช็คว่า LINE UID ไม่ได้ผูกกับ user อื่นก่อน
ไปที่ โปรไฟล์ → กดปุ่ม "ยกเลิกการผูก LINE" — ระบบจะลบ link และหยุดส่ง notification ทันที
เปิด 2FA เพื่อความปลอดภัยขั้นสูง — ต้องใช้ Google Authenticator หรือ app TOTP อื่น
Backup codes แต่ละรหัสใช้ได้ ครั้งเดียว — ใช้เมื่อมือถือหาย/Authenticator app เปลี่ยนเครื่อง ห้ามแชร์ ห้าม screenshot บน cloud
verify_2fa.phpทัวร์บางรายการ (โดยเฉพาะ Association tournament รุ่นอายุ) บังคับให้ยืนยันตัวตนก่อนสมัคร เพื่อยืนยันอายุจริง
เมื่อแอดมินอนุมัติแล้ว ระบบจะลบรูปบัตรประชาชนทันที — เก็บแค่ flag "verified" + วันเกิด + เพศ ไม่มีการเก็บภาพถาวร

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

รูปที่ 2.6.2 — edit_profile.php
แก้ไขได้ทันที (ไม่ต้อง OTP):
ต้องใช้ OTP ผ่าน email ก่อนเปลี่ยน:
ข้อมูลพวกนี้ส่งผลต่อ identity + การสมัครรุ่นอายุ — ระบบบังคับให้ยืนยันผ่าน OTP เพื่อป้องกัน account takeover

รูปที่ 2.7 — calendar.php — แสดงรายการแข่งทุกสถานะ
| เปิดรับสมัคร | สีเขียว — สมัครได้ตอนนี้ |
| ปิดรับสมัคร | สีแดง — หมดเวลาสมัครแล้ว |
| กำลังแข่งขัน | สีเหลือง — แข่งวันนี้/สัปดาห์นี้ |
| เสร็จสิ้น | สีเทา — จบแล้ว ดูผลย้อนหลัง |
คลิกที่รายการเพื่อเข้าสู่หน้า match_detail.php?id=...
หน้ารายการแข่ง match_detail.php?id=N มี 9 tabs ที่จะแสดง/ซ่อนตามสถานะของรายการ

รูปที่ 2.8 — Tab "รายละเอียดการแข่งขัน" (default)
| Tab | ไอคอน | เนื้อหา | เห็นเมื่อ |
|---|---|---|---|
| รายละเอียด | ℹ️ | วันแข่ง, สถานที่, โปสเตอร์, Google Map | เสมอ |
| กติกา | 📜 | กฎการแข่ง + รูปประกอบ | เปิดโดยแอดมิน |
| รายชื่อผู้สมัคร | 📋 | ทีมที่สมัครแล้ว + สถานะชำระเงิน | เปิดโดยแอดมิน |
| ตารางแข่งขัน | ⏰ | คิว + สนาม + เวลา (อัปเดตสด) | หลังจัดสาย |
| รอบแบ่งกลุ่ม | 📊 | ตารางคะแนนกลุ่ม (W/D/L) | มี group stage |
| รอบน็อกเอาต์ | 🌳 | สายแข่ง (bracket tree) | มี knockout |
| ผลการแข่งขัน | 🏆 | ผู้ชนะ + เหรียญ | หลังจบ |
| จำนวนลูกแบด | 🏸 | track ลูกแบดมินตันที่ใช้ | เปิดโดยแอดมิน |
| รูปภาพ | 📸 | gallery รูปจากการแข่ง | เปิดโดยแอดมิน |
เมื่อรายการอยู่สถานะ กำลังแข่งขัน และเปิด YouTube Live URL — จะมีปุ่ม "🔴 ดูการแข่งสด" แยกพิเศษ ฝัง YouTube embed
กดได้เมื่อรายการอยู่สถานะ เปิดรับสมัคร เท่านั้น
match_detail.php?id=Nหลังส่งใบสมัคร สถานะจะเป็น "รอชำระเงิน" ต้องอัปโหลดสลิปภายในเวลาที่กำหนด (ส่วนใหญ่ 24-48 ชม.) ไม่งั้นใบสมัครจะถูกยกเลิกอัตโนมัติ
เมื่อมีคนชวนคุณ — คุณจะได้รับการแจ้งเตือน 2 ช่องทาง:

รูปที่ 2.10 — Inbox แสดง invite จากคู่
respond_invite.php?token=...Token ของ invite ใช้ครั้งเดียว, ผูกกับ user_id ของคุณ — คนอื่นเปิดลิงก์ไม่ได้
ระบบรองรับ 3 โหมดการชำระ:
| โหมด | วิธีการ | การตรวจ |
|---|---|---|
| manual | ไม่มีระบบ online — โอนแล้วแจ้งแอดมินเอง | แอดมิน manual |
| manual_qr | สแกน QR code → อัปโหลดสลิป | แอดมิน manual |
| slipok | สแกน QR → อัปโหลดสลิป → SlipOK API ตรวจอัตโนมัติ | อัตโนมัติ |
match_detail.php → tab "รายชื่อผู้สมัคร" → หาแถวของคุณAPI ตรวจ: ยอดเงิน, ชื่อผู้รับโอน, เลข trans_ref, และ unique check ไม่ให้ใช้สลิปเดียวกันซ้ำ

เปิดข้อความ → ระบบ mark เป็น "read" อัตโนมัติ
เปิด/ปิดการแจ้งเตือนแต่ละประเภทได้ใน 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.php
ข่าวสารโพสต์โดยแอดมิน — รวม:
ระบบ AI Face Recognition กำลังติดตั้งบน Proxmox VM (GPU) — รายละเอียดเทคนิคอ่านที่ส่วนที่ 7
photo_search.phpวิธีจัดการทัวร์นาเมนต์ตั้งแต่ต้นจนจบ

รูปที่ 3.1 — หน้า admin.php — ศูนย์รวมการจัดการทั้งหมด
ทำได้จาก Admin Dashboard → กดปุ่ม "+ สร้างรายการ"
| กลุ่ม | ฟิลด์ | หมายเหตุ |
|---|---|---|
| ข้อมูลพื้นฐาน | title | ชื่อรายการ |
| start_date / end_date | วันแข่ง | |
| location | สถานที่ + map_url (Google Maps) | |
| province | จังหวัด (ใช้ filter) | |
| การแข่ง | match_mode | web ทั่วไป / association สมาคม (มีรุ่นอายุ) |
| available_events | JSON list — ชายคู่, หญิงคู่, คู่ผสม, เดี่ยว ฯลฯ | |
| available_age_categories | สำหรับ association mode | |
| การชำระเงิน | payment_mode | manual / manual_qr / slipok |
| payment_qr_image | รูป QR (สำหรับ manual_qr) | |
| payment_amount | ยอดที่ต้องชำระ | |
| slipok_branch_id / api_key | (สำหรับ slipok) | |
| Tab visibility | tab_result_enabled | เปิด tab "ผลการแข่งขัน" |
| tab_shuttlecocks_enabled | เปิด tab "จำนวนลูกแบด" | |
| tab_photos_enabled | เปิด tab "รูปภาพ" | |
| tab_rules_enabled | เปิด tab "กติกา" | |
| Live | live_enabled | เปิดปุ่ม "ดูสด" |
| youtube_live_url | URL embed | |
| Notification | notify_match_reminder | เปิด LINE reminder 30/60 นาที |
| notify_court_change | เปิดแจ้งเปลี่ยนสนาม | |
| notify_morning_broadcast | เปิด morning broadcast |

รูปที่ 3.3 — edit_match.php — มี multi-section + sensitive changes
เปลี่ยนผ่าน dropdown — มี 4 ค่า:
การเปลี่ยน payment_mode, slipok_api_key, อายุของรายการ ต้องผ่าน OTP confirmation ผ่าน apply_sensitive_changes.php
admin_verify_slips.php → กด "ผ่าน" ด้วยมือ
slipok.com → ได้ branch_id + api_keyedit_match.php ที่ฟิลด์ slipok_branch_id + slipok_api_keymatch_registrations.status='ผ่านชำระแล้ว', slip_auto_verified=1SlipOK ใช้ OCR + database ของธนาคารตรวจ trans_ref — แม่นยำเกือบ 100% และเร็ว ~5 วินาที
หน้า admin_verify_slips.php — แสดงสลิปที่รอตรวจทั้งหมด
ตรวจ ชื่อผู้รับโอน ทุกครั้ง! สลิปปลอมมักเปลี่ยนเฉพาะชื่อผู้โอน — ระบบ SlipOK ป้องกันได้ดีกว่า manual
หลังปิดรับสมัคร → ต้องจัดสายการแข่งก่อน
| รูปแบบ | คำอธิบาย | ใช้กับ |
|---|---|---|
| Round-robin only | แบ่งกลุ่ม แต่ละคู่แข่งทุกคู่ในกลุ่ม | ผู้เล่นน้อย, ลีก |
| Single Elimination | แพ้คัดออก รอบเดียว | ทัวร์ทั่วไป |
| Double Elimination | มี loser bracket | มืออาชีพ |
| Group + KO | แบ่งกลุ่มก่อน → ทีมต้น ๆ ไป knockout | ทัวร์ใหญ่ |

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

รูปที่ 3.7 — admin_schedule_planner.php — auto schedule
order_of_play
รูปที่ 3.8 — admin_print_scoresheet.php — A4 Landscape
หน้า A4 Landscape — ทดสอบและปรับ margin เพื่อให้พิมพ์ตรงทุก browser (Chrome, Safari, Firefox)

รูปที่ 3.9 — admin_live_match.php
admin_live_match.php?id=N21 15 21 10 → auto-format เป็น 21-15, 21-1021-15 21-10 → คงรูปแบบ21-19 18-21 21-15 → 3 เซ็ตgroup_standings auto (W/D/L, set diff, point diff)autoAdvanceKnockout() ถ้าเป็นแมตช์น็อกเอาต์ → ส่งทีมชนะไปรอบถัดไปmatch_order_api.php ให้ scoreboard + OBS อัปเดตหากกรรมการหลายคนป้อนพร้อมกัน — ระบบใช้ editing_presence table แสดงว่าใครกำลังแก้ field ไหน (TTL 5 วินาที)

รูปที่ 3.10 — admin_manage_knockout.php
ตาราง knockout_matches ใช้ symbolic reference:
W1 = ผู้ชนะแมตช์ 1, L1 = ผู้แพ้แมตช์ 1WIN[3] = ผู้ชนะลำดับ 3, LOSE[5] = ผู้แพ้ลำดับ 5เมื่อ admin ป้อนคะแนนแมตช์ที่ 1 → ระบบเรียก autoAdvanceKnockout() recursively walk tree → แทนที่ W1 ในแมตช์ลูก ด้วยชื่อทีมจริง

รูปที่ 3.11 — admin_manage_order.php
match_order_api.phpหาก notify_court_change เปิดอยู่ — ระบบจะส่ง LINE notification ไปยังผู้เล่นทั้งคู่ทันที
หน้าจอแสดงผลขนาดใหญ่ — สำหรับ TV/Projector ในงานแข่ง
admin_scoreboard.php — แสดงคิวปัจจุบัน + คะแนนสดadmin_live_board.php — bracket viewer + standingsเปิด admin_scoreboard.php?id=N บน TV → เต็มจอ (F11) → อัปเดต auto ทุก 1 วินาที
https://thaibadtournaments.com/badminton/admin_obs_overlay.php?id=N&court=1?court=1 — แสดงเฉพาะคอร์ทที่ 1?theme=dark — ใช้ธีมเข้ม?style=compact — ขนาดเล็ก (สำหรับมุมจอ)อ่านเพิ่มเติม: ไฟล์ OBS overlay.md ใน root
ระบบเรียกชื่อนักกีฬาผ่าน Text-to-Speech
| เครื่องมือ | คุณภาพ | ความเร็ว | ราคา |
|---|---|---|---|
| Gemini AI (default) | ⭐⭐⭐⭐⭐ ดีที่สุด | 2-3 วินาที | 100 RPD ฟรี |
| Google Translate TTS | ⭐⭐⭐ | 1 วินาที | ฟรี ไม่จำกัด |
| Browser SpeechSynthesis | ⭐⭐ | ทันที | ฟรี |
tts_court_call.php?id=N บนเครื่องที่มีลำโพง/เครื่องเสียง
ระบบ cache เสียงด้วย SHA256(text+voice).wav ใน /uploads/tts_cache/
admin_tts_cache.php
รูปที่ 3.15 — admin_line_broadcast.php
LINE Messaging API จำกัด push quota ต่อเดือน — ตรวจสอบที่ LINE Developer Console ก่อนส่งหมู่ทั้งหมด
ส่งสรุปตารางการแข่งของผู้เล่นแต่ละคนตอน 06:00 ของวันแข่ง
admin_morning_broadcast.phpแต่ละผู้เล่นจะได้ 1 ข้อความเดียว สรุปทุกแมตช์ของตัวเอง (ไม่ซ้ำแม้สมัครหลายรุ่น)
ตั้ง cron job ใน server ให้รัน admin_morning_broadcast.php?auto=1&date=TODAY ตอน 06:00 ทุกวัน

รูปที่ 3.17 — admin_verify_identity.php
users.identity_verified = 1
รูปที่ 3.18 — manage_users.php

รูปที่ 3.19 — admin_visitor_logs.php
| Table | เก็บอะไร |
|---|---|
visitor_sessions | 1 session = 1 user open browser, IP, device, browser, referrer |
visitor_pageviews | หน้าที่เปิด + duration (จาก heartbeat ทุก 30 วินาที) |

รูปที่ 3.20 — admin_errors.php
lib/error_monitor.php จับ PHP errors + uncaught exceptionserrors_log table + /uploads/logs/errors.jsonl
รูปที่ 3.21 — admin_player_stats.php

รูปที่ 3.22 — admin_shuttlecocks.php — บันทึกลูกที่ใช้
เข้า export_registrations.php?id=N → ดาวน์โหลด CSV/Excel ของผู้สมัครทั้งหมด

admin_calendar_province.php — เพิ่ม/แก้ไขจังหวัดให้ตัวกรอง
การสร้างและจัดการชมรม + Association Tournament

รูปที่ 4.1 — club_create.php
เมื่อสร้างเสร็จ — คุณเป็น club_member role=owner โดยอัตโนมัติ
Banner ปรากฏใน profile ชมรม, list ชมรม, และในรายการแข่งของชมรม
club_banner_designs)| Background type | คำอธิบาย |
|---|---|
| Gradient | 2 สี + ทิศทาง (linear-gradient) |
| Solid | สีเดียว |
| Image | อัปโหลดรูปเป็น bg |
| Pattern | SVG pattern (dots, lines, diagonal) |

รูปที่ 4.3 — club_manage.php?id=N
club_view.php?id=N) ให้สมาชิกpendingclub_manage.phpowner — สิทธิ์ทุกอย่าง (เปลี่ยน owner ได้ครั้งเดียว)admin — จัดการสมาชิก + สร้างทัวร์ในชมรมmember — สมาชิกทั่วไป — ใช้ชื่อชมรมเวลาสมัครแข่งได้เมื่อสมาชิกของชมรมสมัครแข่ง — ระบบใช้ find_club_by_name() (case-insensitive) เพื่อ auto-link ทีมกับชมรมโดยอัตโนมัติ

รูปที่ 4.4 — club_view.php — ใครก็เห็นได้
โหมดพิเศษสำหรับทัวร์ระดับสมาคม — มีรุ่นอายุ + draw system แบบ BWF
| Feature | Web Mode | Association Mode |
|---|---|---|
| รุ่นอายุ | ❌ | ✅ บังคับยืนยันตัวตน |
| การจัด Draw | กลุ่ม/น็อกเอาต์ | Draw system + Seeding |
| Bulk import | ❌ | ✅ CSV upload |
| หน้า detail | match_detail.php | match_detail_association.php |
สำหรับสมาคมที่ต้องลงทะเบียนนักกีฬาจำนวนมากจากระบบสมาคมเดิม
| Column | ความหมาย | ตัวอย่าง |
|---|---|---|
| full_name | ชื่อจริง-นามสกุล | สมชาย ใจดี |
| dob | วันเกิด YYYY-MM-DD | 2010-05-15 |
| gender | M/F | M |
| id_number | เลขบัตรประชาชน | 1234567890123 |
| club_name | ชื่อชมรม (optional) | โรงเรียน ABC |
| event | รายการที่สมัคร | ชายเดี่ยว U13 |
| partner_name | ชื่อคู่ (สำหรับคู่) | สมศักดิ์ ใจกล้า |
assoc_bulk_import.php?id=NExcel default save เป็น ANSI/Windows-874 — ภาษาไทยจะเพี้ยน! ใช้ "Save As → CSV UTF-8" หรือ Google Sheets export CSV
เห็นอะไร ทำอะไรได้ — เวลาเข้าหน้ารายการของตัวเอง
Client Owner คือผู้ใช้ที่ได้รับ "สิทธิ์เจ้าของรายการ" เฉพาะรายการแข่งใดรายการหนึ่ง (ไม่ใช่ทั้งเว็บ)
Staff Admin = สิทธิ์ทั่วทั้งระบบ ทำได้ทุกรายการ
Client Owner = สิทธิ์เฉพาะรายการที่ได้รับมอบหมาย รายการอื่นเป็น user ปกติ
เปิดหน้ารายการ — ถ้าเห็น แท็กสีฟ้าเขียนว่า:
แท็กนี้ขึ้นใต้ชื่อรายการ บอกชัดว่าคุณกำลังดูในฐานะเจ้าของรายการ
เริ่มจากบนลงล่าง:

รูปที่ 4B.2 — หน้ารายการที่ Client Owner เห็น (พร้อมปุ่มจัดการพิเศษ)
| ตำแหน่ง | สิ่งที่เห็น | กดแล้วไป |
|---|---|---|
| มุมขวาบน | 🔴 ปุ่ม "ระบบบันทึกคะแนน" (เฉพาะตอนรายการ "กำลังแข่งขัน") | หน้าป้อนคะแนนสด |
| มุมขวาบน | ✏️ ปุ่ม "แก้ไขข้อมูล" (ทุกสถานะ) | หน้าแก้ไขรายการ |
| ใต้ชื่อรายการ | 🏷️ แท็กสีฟ้า "Client Owner" | — |
| แต่ละ tab | ปุ่มจัดการเพิ่มเติม (รายละเอียดด้านหน้า 4B.3 - 4B.8) | — |
นี่คือ tab ที่ Client Owner ใช้บ่อยที่สุด เพราะรวมงาน ดูผู้สมัคร + อนุมัติสลิป + ปรับสถานะ
คลิก → กล่องสีขาวเปิดขึ้นมา ใส่ข้อมูลทีม (รุ่น, ชื่อทีม, ผู้เล่นคนที่ 1, ผู้เล่นคนที่ 2, เบอร์) → กด "บันทึก"
ใช้เมื่อ: มีคนแจ้งสมัครผ่าน LINE/โทร แต่ไม่สมัครเองในเว็บ — Client Owner กรอกแทน
ขึ้นเมื่อรายการตั้งค่า payment เป็นแบบ Manual QR และมีสลิปรอตรวจ — ปุ่มแสดงจำนวนสลิปที่รอ (เช่น "🔍 ตรวจสอบสลิป (3)")
คลิก → ไปยังหน้า "ตรวจสอบสลิป" รายชื่อทีมที่ยังรอตรวจ
นอกจากคอลัมน์ที่ user เห็น (ทีม, ผู้เล่น, รุ่น, สถานะ) — Client Owner เห็นเพิ่ม:
แก้ไขชื่อทีม, ผู้เล่น, เบอร์, รุ่น หรือลบใบสมัครได้
คลิกแล้วเปิดหน้าใหม่ — ใช้สร้างตาราง: เลือกจำนวนคอร์ท, ช่วงเวลา, ระยะเวลา/แมตช์ → ระบบสร้างให้อัตโนมัติ + drag-drop ปรับเองได้
เปิดตารางคิวให้แก้: เปลี่ยน สนาม, เวลา, เลขคิว, ทีม, คะแนน
ระวัง: ถ้าเปลี่ยนสนาม/เวลา → ระบบจะส่ง LINE แจ้งทีมทั้งคู่ทันที (ถ้าตั้ง "แจ้งเตือนเปลี่ยนสนาม" ไว้)
ขึ้นเมื่อรายการอยู่สถานะ กำลังแข่งขัน — กดเพื่อป้อนคะแนนของคู่นั้นแบบเร็ว
เปิดหน้าใหม่ — รูปแบบ A4 ใส่ลายเซ็นกรรมการ — เลือกรูปแบบ Full referee หรือ Compact 2 แมตช์/หน้า
เปิดหน้า "จัดการกลุ่ม" — ใส่ผู้เล่นลงในกลุ่ม, ป้อนคะแนน W/D/L, ระบบคำนวณ point diff + tiebreaker อัตโนมัติ
เปิดหน้า Bracket Config — เลือกรูปแบบ Single/Double Elimination, กำหนด seed, generate bracket อัตโนมัติ
เปิดหน้า "จัดการน็อกเอาต์" — แก้ไขทีมในแต่ละ slot, ป้อนคะแนน, ระบบ auto-advance ทีมชนะไปรอบถัดไปทั้งสายอัตโนมัติ
แก้ไขกฎการแข่ง (มี rich text editor) + อัปโหลดรูปภาพประกอบกติกาได้ — ผู้สมัครทุกคนเห็นทันทีที่อัปเดต
เลือกหลายไฟล์พร้อมกัน (multi-upload) → ระบบ resize อัตโนมัติ → ขึ้นในแกลเลอรี
ลบรูปออกจากแกลเลอรีได้ (เฉพาะรูปของรายการนี้)
กรอกจำนวนลูกที่ทีมใช้ต่อแมตช์ + ราคา/ลูก → ระบบคำนวณค่าลูกที่ทีมต้องจ่ายเพิ่ม
Client Owner ไม่ มีปุ่มแก้ผล (ปุ่มนี้สำหรับ Staff Admin/System Owner เท่านั้น) — เห็นผลแบบ read-only หลังจบรายการ
| หมวด | การกระทำ |
|---|---|
| รายการแข่ง | แก้ไขข้อมูลรายการ (ชื่อ, วันแข่ง, สถานที่, โปสเตอร์) |
| เปลี่ยนสถานะรายการ (เปิด/ปิด/กำลังแข่ง/เสร็จสิ้น) | |
| เปิด/ปิด tab visibility (กติกา, ลูกแบด, รูปภาพ, ผลแข่ง) | |
| เปลี่ยน YouTube Live URL | |
| ผู้สมัคร | เพิ่มรายชื่อทีละทีม |
| แก้ไข/ลบใบสมัคร | |
| เปลี่ยนสถานะการชำระเงิน | |
| ดูเบอร์โทร, รูปผู้เล่น, สลิปโอนเงิน | |
| การแข่ง | วางตารางแข่ง (Schedule Planner) |
| ป้อนคะแนนสด (Live Score) | |
| Bracket | ตั้งค่าสายแข่ง (Group/KO) |
| จัดการกลุ่ม + จัดการน็อกเอาต์ | |
| กติกา | แก้ไขกฎ + อัปโหลดรูปประกอบ |
| รูปภาพ | อัปโหลด/ลบรูปการแข่ง |
| ลูกแบด | บันทึกจำนวนลูกที่ใช้ |
| พิมพ์ | พิมพ์ scoresheet A4 |
| การกระทำ | ทำไม |
|---|---|
| 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
ลำดับการใช้งานทั่วไปจากเปิดสมัคร → จบรายการ:
เห็นอะไร ทำอะไรได้ — ผู้ช่วยกรรมการประจำรายการ
Contributor = "ผู้ช่วยจัดการรายการ" ที่เจ้าของรายการมอบสิทธิ์ให้ — เน้นช่วย ป้อนคะแนน + ดูข้อมูลผู้สมัคร ในรายการนั้น โดยไม่ได้สิทธิ์เรื่องเงินและสถานะรายการ
เปิดหน้ารายการ — ถ้าเห็น แท็กสีม่วง:
Client Owner = "เจ้าของรายการ" จัดการได้เกือบทุกอย่าง
Contributor = "ผู้ช่วย" จัดการได้แค่บางส่วน — โดยเฉพาะ เรื่องเงินและสถานะรายการแตะไม่ได้
| ตำแหน่ง | สิ่งที่เห็น | กดแล้วไป |
|---|---|---|
| มุมขวาบน | 🔴 ปุ่ม "ระบบบันทึกคะแนน" (เฉพาะตอนรายการ "กำลังแข่งขัน") | หน้าป้อนคะแนนสด |
| ใต้ชื่อรายการ | 🏷️ แท็กสีม่วง "Contributor" | — |
| แต่ละ tab | ปุ่มเพิ่มบางอย่าง (รายละเอียดหน้าถัดไป) | — |
เพิ่มทีมใหม่ลงทะเบียนได้ — กรณีมีทีมแจ้งหน้างาน หรือเจ้าของรายการขอให้ช่วยกรอกแทน
แก้ไขชื่อทีม, ชื่อผู้เล่น, เบอร์โทรศัพท์, รุ่น ได้ — แต่เปลี่ยนสถานะการชำระเงินไม่ได้
การเงินและสถานะรายการเป็น "ความรับผิดชอบของเจ้าของรายการ" — Contributor ออกแบบมาให้ช่วยเรื่องการแข่งจริง ไม่ใช่เรื่องเงิน
ขึ้นเมื่อรายการ กำลังแข่งขัน — งานหลักของ Contributor: ป้อนคะแนนของแมตช์ที่กำลังเล่น
เปลี่ยนสนาม/เวลา/เลขคิว/คะแนนของแมตช์ใดก็ได้ — ใช้เมื่อต้องสลับคิวกระทันหัน
พิมพ์ scoresheet เพื่อแจกกรรมการแต่ละสนาม
เปิดหน้าจัดการกลุ่ม — ป้อนคะแนนแต่ละแมตช์ของกลุ่ม ระบบคำนวณตารางคะแนนให้
Contributor เห็น bracket tree เต็มและสามารถ ป้อนคะแนนแต่ละแมตช์ได้ — แต่ "ตั้งค่าสายแข่ง" (Bracket Config) เป็นปุ่มของ Client Owner เท่านั้น
แก้ไขกติกาและอัปโหลดรูปประกอบได้ — เหมือน Client Owner
อัปโหลดรูปได้ — งานที่ช่างภาพรายการมักทำ
ลบรูปได้
กรอกจำนวนลูกที่ทีมใช้ต่อแมตช์
Contributor ไม่ มีปุ่มแก้ผลย้อนหลัง (เป็นของ full admin เท่านั้น) — เห็นผลแบบ read-only หลังจบรายการ
| หมวด | การกระทำ |
|---|---|
| ผู้สมัคร | เพิ่มทีมใหม่ทีละคน |
| แก้ไขข้อมูลทีม (ชื่อ, ผู้เล่น, เบอร์, รุ่น) | |
| ดูเบอร์โทร, รูปผู้เล่น, สลิป | |
| การแข่ง | ป้อนคะแนนสดของแต่ละแมตช์ |
| จัดการคิวด้วยมือ (เปลี่ยนสนาม/เวลา/ลำดับ) | |
| พิมพ์ scoresheet | |
| กลุ่ม | ป้อนคะแนนรอบแบ่งกลุ่ม |
| น็อกเอาต์ | ป้อนคะแนนรอบน็อกเอาต์ (auto-advance ผู้ชนะ) |
| กติกา | แก้ไข + อัปโหลดรูปประกอบ |
| รูปภาพ | อัปโหลด/ลบรูปการแข่ง |
| ลูกแบด | บันทึกจำนวนลูกที่ใช้ |
| การกระทำ | ต้องไปหาใคร |
|---|---|
| เปลี่ยน สถานะการชำระเงิน ของทีม | 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 CSV | Staff Admin |
| Export ผู้สมัคร CSV | Staff Admin |
| แก้ผลย้อนหลัง | Staff Admin / System Owner |
| ลบรายการแข่ง | System Owner |
Contributor มักทำงานช่วงวันแข่งเป็นหลัก — flow ทั่วไป:
Contributor ไม่ต้องทำอะไรเพิ่ม — Client Owner / Staff Admin จะเป็นคนเปลี่ยนสถานะรายการเป็น แข่งขันเสร็จสิ้น
Contributor = "มือป้อนคะแนน + ผู้ช่วยหน้างาน"
ทำทุกอย่างที่ไม่เกี่ยวกับ "เงิน" และ "สถานะรายการ"
| การกระทำ | User (ผู้สมัคร) |
Contributor (ผู้ช่วย) |
Client Owner (เจ้าของรายการ) |
|---|---|---|---|
| ดูข้อมูลรายการ + กติกา | ✅ | ✅ | ✅ |
| สมัครเข้าแข่ง | ✅ | ✅ | ✅ |
| ดูตารางแข่ง + ผล | ✅ | ✅ | ✅ |
| ดูเบอร์โทรของทีมอื่น | ❌ | ✅ | ✅ |
| ดูสลิปโอนเงินของทีมอื่น | ❌ | ✅ | ✅ |
| เพิ่มทีมเข้าแข่ง | ❌ | ✅ | ✅ |
| แก้ไขข้อมูลทีม | ❌ (ของตัวเองได้) | ✅ | ✅ |
| ป้อนคะแนนสด | ❌ | ✅ | ✅ |
| จัดการคิว/สนาม/เวลา | ❌ | ✅ | ✅ |
| พิมพ์ scoresheet | ❌ | ✅ | ✅ |
| อัปโหลด/ลบรูปการแข่ง | ❌ | ✅ | ✅ |
| แก้ไขกติกา | ❌ | ✅ | ✅ |
| บันทึกจำนวนลูก | ❌ | ✅ | ✅ |
| เปลี่ยนสถานะการชำระเงิน | ❌ | ❌ | ✅ |
| อนุมัติ/ปฏิเสธสลิป | ❌ | ❌ | ✅ |
| แก้ไขข้อมูลรายการ | ❌ | ❌ | ✅ |
| เปลี่ยนสถานะรายการ | ❌ | ❌ | ✅ |
| ตั้งค่าสายแข่ง (Bracket) | ❌ | ❌ | ✅ |
| วางตารางแข่ง (Schedule) | ❌ | ❌ | ✅ |
คำสั่ง + Flow ผูกบัญชี + Reminder อัตโนมัติ
Bot LINE Official Account ทำงานควบคู่กับเว็บ สื่อสารกับผู้เล่นผ่าน LINE ทุกขั้นตอน
PIN 6 หลัก เชื่อม LINE UID กับ user account
พิมพ์ "แมตของฉัน" → ดูทุก tournament ที่สมัคร
พิมพ์ "แมตที่เท่าไร" → ดูคิวที่กำลังแข่ง
แจ้งก่อนแข่ง 30 นาที + 1 ชั่วโมง อัตโนมัติ
รับประกาศจากแอดมิน + morning broadcast
แจ้งสลิปอนุมัติ/ปฏิเสธ + LINE Flex Message
สแกน QR code ในหน้า profile.php หรือเสิร์ช @thaibadtournaments ใน LINE
| คำสั่ง | ผลลัพธ์ | ต้อง login? |
|---|---|---|
ลงทะเบียน [PIN] | ผูก LINE กับบัญชีในเว็บ | มี PIN จากเว็บ |
สถานะ | แสดงว่าผูกบัญชีไหน + UID | ✅ |
แมตของฉัน | list ทุก tournament ที่สมัคร + status | ✅ |
แมตที่เท่าไร | ดูคิวที่กำลังแข่ง + แมตช์ถัดไป (ถ้าแข่งวันนี้) | ✅ |
ตรวจสอบการแข่งขัน | Multi-step: เลือก tournament → เลือก event → ดูแมตช์ | ✅ |
ยกเลิก | cancel state machine | — |
help / เมนู | แสดงคำสั่งทั้งหมด | — |
Bot รองรับการพิมพ์ที่ไม่เป๊ะ:
แมตของฉัน = แมทของฉัน = my matchesแมตที่เท่าไร = คิว = queue
User Web LINE Bot DB
│ │ │ │
│── เข้า profile ──>│ │ │
│ │── สร้าง PIN ────────────────────────>│
│ │<── PIN "123456" ──────────────────── │
│<── PIN + QR ──────│ │ │
│ │ │
│── สแกน QR + Add Friend ────────────────>│ │
│ │── ลงทะเบียน ───>│ (check PIN)
│ │<── valid ──────│
│<── "ผูกบัญชีสำเร็จ!" ─────────────────── │── update user ─>│
(line_uid)
ระบบ cron_notify_matches.php รันทุก 2-5 นาที
notify_1h_sent, notify_30m_sent เพื่อไม่ส่งซ้ำ🏸 แจ้งเตือนการแข่ง รายการ: VENSON Kamphaengphet 2026 🎾 ทีม: สมชาย / สมศักดิ์ 🆚 vs: สมหญิง / สมศรี 🏟 สนาม: 2 ⏰ เวลา: 14:30 (อีก 30 นาที) 📍 คิวที่: 18 กรุณามาที่สนามก่อนเวลา 15 นาที
ผู้เล่นสามารถปิด notify_match_reminder ใน notification_settings.php ต่อรายการได้
ส่งสรุปตารางของผู้เล่นแต่ละคนตอน 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 ได้
การตั้งค่าระบบ + Cron + APIs + Migrations
| ไฟล์ | หน้าที่ |
|---|---|
app_config.php | config public (อยู่ใน webroot) |
app_secret.php | secrets — นอก webroot ✅ |
db.php | เชื่อมต่อ MySQL |
smtp_config.php | SMTP server credentials |
line_config.php | LINE Bot channel access token |
lib/bootstrap.php | โหลด wide ทุก session |
ระบบใช้ 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 ต้อง enable 2FA ก่อน → สร้าง App Password ที่ myaccount.google.com/apppasswords
เปิด test_error_monitor.php → จะส่ง test email ไป admin email
อ่านเอกสาร: Line_Admin_Setup.md, Line_Noti.md, Line_User_Guide.md
developers.line.bizline_config.php:
return [ 'channel_access_token' => 'xxxxx...', 'channel_secret' => 'xxxxx...', 'liff_id' => 'xxxxx-xxxxx', ];
https://thaibadtournaments.com/badminton/line_webhook.phpสำหรับ login ผ่าน LINE ในเว็บ — สร้าง LIFF app type=Full → URL ชี้ไปที่ auth_line.php
ระบบมี 2 cron jobs หลักที่ต้องตั้งใน server
*/3 * * * * curl -s -H "X-Cron-Secret: YOUR_SECRET" \ https://thaibadtournaments.com/badminton/cron_notify_matches.php \ >> /var/log/thaibad_cron.log 2>&1
0 6 * * * curl -s -H "X-Cron-Secret: YOUR_SECRET" \ "https://thaibadtournaments.com/badminton/admin_morning_broadcast.php?auto=1&date=TODAY"
0 3 * * 0 php /path/to/cleanup_old_logs.php
ตั้ง CRON_SECRET ใน app_secret.php → ใช้เป็น header X-Cron-Secret เพื่อกัน cron URL ถูกเรียกจากภายนอก
สำหรับการตรวจสลิปอัตโนมัติ
slipok.com → เลือกแพ็กเกจbranch_idapi_keyedit_match.php → ฟิลด์:
slipok_branch_idslipok_api_keypayment_account_name — ต้องตรงกับใน SlipOKlib/slipok.php ส่ง POST ไปยัง https://api.slipok.com/api/line/apikey/{branch_id} พร้อมรูปสลิป
1000 = ตรวจผ่าน1002 = ยอดไม่ตรง1003 = สลิปซ้ำ (duplicate)1010 = ชื่อผู้รับไม่ตรงai.google.dev → สร้าง API Keyapp_secret.php:
'GEMINI_API_KEY' => 'AIzaSy...',
gemini-2.5-flash-preview-tts + voice Kore (Thai)ระบบเก็บไฟล์เสียงใน /uploads/tts_cache/SHA256(text+voice).wav
admin_tts_cache.php → batch generateเมื่ออัปเดตระบบ — รัน migration scripts ใน root ของ project
| Script | เพิ่มอะไร |
|---|---|
migrate_2fa_tables.php | 2FA + backup codes |
migrate_payment_system.php | payment_mode, slipok, slip status |
migrate_clubs.php | clubs, members, banner_designs |
migrate_lockout.php | failed_login_attempts, lockout_until |
migrate_add_gender.php | users.gender (M/F) |
migrate_age_categories.php | available_age_categories JSON |
migrate_identity_verification.php | identity_verified + id_card_image |
migrate_errors_log.php | errors_log table |
migrate_line_chat_states.php | state machine ของ webhook |
migrate_line_link_pins.php | PIN 6 หลักผูก LINE |
migrate_notify_flags.php | notify_* flags ต่อ tournament |
migrate_calendar_province.php | filter จังหวัด |
migrate_calendar_map_url.php | Google Maps URL |
migrate_match_tab_visibility.php | tab_*_enabled flags |
migrate_match_permissions_role.php | per-tournament role |
migrate_tts_cache.php | tts_quota_daily + cache table |
migrate_cleanup_legacy_roles.php | cleanup เก่า ๆ |
ใช้ mysqldump backup ก่อนรันทุกครั้ง — ไม่มี rollback automatic
อ่านเอกสาร Real_time_Co_work.md
ตาราง editing_presence:
user_id, tournament_id, field_name, started_atmatch_order_api.php — GET ดู order + presence, POST update + lockschedule_api.php — build_pairings, auto_schedule, save_scheduleFrontend poll ทุก 2 วินาที — ไม่ใช้ WebSocket (เพื่อง่ายในการ host บน shared hosting)
ค้นหารูปการแข่งด้วยใบหน้าตัวเอง (AI Face Recognition)
UI ของฟีเจอร์นี้ออกแบบและ deploy แล้ว — ผู้ใช้สามารถเข้าหน้า photo_search.php?id=N ดูแกลเลอรีรูปได้ แต่ปุ่ม "อัปโหลด selfie" ยังถูกปิดอยู่จนกว่า Face API Server บน Proxmox จะติดตั้งเสร็จ
ผู้เล่นต้องการดูรูปของตัวเองในรายการแข่ง — แทนที่จะต้อง scroll หารูปทั้งหมด ระบบจะให้ อัปโหลด selfie 1 รูป → AI หารูปที่มีใบหน้าใกล้เคียงให้ทั้งหมด
| Component | เทคโนโลยี |
|---|---|
| Face Detection | InsightFace (RetinaFace + ArcFace) |
| Embedding | 512-dim vector ต่อใบหน้า |
| Similarity | Cosine similarity (threshold ~0.5) |
| Backend | Python Flask API บน Ubuntu 22.04 |
| Hardware | NVIDIA RTX 3060 (Proxmox passthrough) |
หน้าจอที่ออกแบบไว้ตาม photo_search.php:
รูปที่ 7.2 — UI ปัจจุบัน (Backend ปิด) สร้างจากการอ่านโค้ด photo_search.php
match_detail.php?id=N → tab "รูปภาพ"photo_search.phpBrowser 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 ─────│ │ │
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
}
อ่านเอกสารเต็มที่ Proxmox_Setup.md
| ส่วน | รายละเอียด |
|---|---|
| CPU | AMD Ryzen 9 5900X (12C/24T) |
| RAM | 48 GB |
| GPU #1 | NVIDIA RTX 3060 (passthrough → VM2) |
| GPU #2 | Quadro P1000 (host) |
| VM | หน้าที่ | vCPU | RAM | Disk | IP |
|---|---|---|---|---|---|
| VM1 | Web (Apache+PHP+MySQL+LINE) | 4 | 6 GB | 50 GB | 192.168.1.101 |
| VM2 | Face Detection API | 8 | 16 GB | 80 GB | 192.168.1.102 |
pip install insightface flask onnxruntime-gpu opencv-python/api/face/searchprivacy_photo.php)ระบบ search ได้เฉพาะ รูปของรายการที่ผู้ใช้สมัครเข้าแข่งเท่านั้น — ไม่ใช่รูปทั้งระบบ และไม่อนุญาตให้ admin export embeddings ออกนอก server
FAQ, 4 สถานะรายการ, คีย์ลัด, ติดต่อ Support
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 "รายชื่อผู้สมัคร" → หาแถวของคุณ → "อัปโหลดสลิป" — ยังทำได้จนกว่ารายการจะ ปิดรับสมัคร
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: ติดต่อแอดมินของรายการ — มีสิทธิ์ลบเฉพาะคนนั้น
| Action | เปิดรับสมัคร | ปิดรับสมัคร | กำลังแข่งขัน | เสร็จสิ้น |
|---|---|---|---|---|
| ดูรายการ | ✅ | ✅ | ✅ | ✅ |
| สมัครเข้าแข่ง | ✅ | ❌ | ❌ | ❌ |
| อัปโหลดสลิป | ✅ | ⚠️ (ภายในกำหนด) | ❌ | ❌ |
| ยกเลิกการสมัคร | ✅ | ❌ | ❌ | ❌ |
| ดูรายชื่อผู้สมัคร | ✅ | ✅ | ✅ | ✅ |
| ดูสายแข่ง | ❌ | ✅ | ✅ | ✅ |
| ดูตารางการแข่ง | ❌ | ✅ | ✅ | ✅ |
| ดูคะแนนสด | ❌ | ❌ | ✅ | ❌ |
| รับ LINE reminder | ❌ | ❌ | ✅ | ❌ |
| ดูผลย้อนหลัง | ❌ | ❌ | ⚠️ (บางส่วน) | ✅ |
| ดูรูปภาพ | ❌ | ❌ | ✅ | ✅ |
| Admin: จัดสาย | ⚠️ | ✅ | ⚠️ | ❌ |
| Admin: ป้อนคะแนน | ❌ | ⚠️ | ✅ | ✅ |
| Admin: อนุมัติสลิป | ✅ | ✅ | ⚠️ | ❌ |
| Admin: Broadcast LINE | ✅ | ✅ | ✅ | ⚠️ |
✅ = ทำได้ ❌ = ทำไม่ได้ ⚠️ = ทำได้แต่มีเงื่อนไข
| Ctrl + P | พิมพ์/บันทึก PDF |
| F11 | Fullscreen (สำหรับ scoreboard kiosk) |
| Esc | ปิด lightbox/modal |
| Tab | ไปช่องถัดไป |
| Enter | บันทึก + ไปแมตช์ถัดไป |
| Esc | ยกเลิกการแก้ไข |
ลงทะเบียน [PIN] | ผูกบัญชี |
สถานะ | เช็คการเชื่อมต่อ |
แมตของฉัน | ตารางแข่งทั้งหมด |
แมตที่เท่าไร | คิวปัจจุบัน |
ตรวจสอบการแข่งขัน | multi-step lookup |
ยกเลิก | cancel state |
เมนู | แสดง help |
ใส่ password ผิด 5 ครั้ง → ล็อก 15 นาที — รอครบเวลาแล้วลองใหม่ หรือใช้ "ลืมรหัสผ่าน" reset
session expired — refresh หน้า + login ใหม่
ตรวจ payment_account_name ใน edit_match.php ให้ตรงกับชื่อบัญชีที่ระบุใน SlipOK dashboard
developers.line.biz → ตรวจ webhook URLadmin_errors.php ดู errorline_config.phpai.google.dev/uploads/tts_cache/ ต้อง writableเช็ค bracket_config: ทีม seed ทุกที่ต้องมีค่า team1_cond / team2_cond ที่ map ได้ — ดูรายละเอียดใน admin_live_match_helpers.php
[email protected]
(System Owner)
@thaibadtournaments
(Official Account)
thaibadtournaments.com
ส่ง screenshot + URL
ไปที่ email ด้านบน
📕 จบคู่มือ ThaibadTournaments.com v1.0
จัดทำ 15 พฤษภาคม 2569 จากการอ่านโค้ดและ Screenshot จริงทั้งระบบ