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

รูปที่ 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 — เพิ่ม/แก้ไขจังหวัดให้ตัวกรอง