takeone-event-managment/doc/displays-signals.md

439 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 📡 Taekwondo Scoring System Score Control to Display Communication
> **Version:** 1.0
> **Last Updated:** July 2025
> **Target Developer:** .NET Android (Score Control) & Android TV App Developers
> **Purpose:** Define **real-time data signals** from **Score Control Unit** to **Scoreboard** and **Upcoming Matches** displays
---
## 📌 Table of Contents
- [1. Overview](#1-overview)
- [2. System Architecture](#2-system-architecture)
- [3. Communication Protocol (TCP)](#3-communication-protocol-tcp)
- [4. Scoreboard (Live Match Display)](#4-scoreboard-live-match-display)
- [5. Upcoming Matches Screen](#5-upcoming-matches-screen)
- [6. Message Format (JSON)](#6-message-format-json)
- [7. C# Server Code (Score Control)](#7-c-server-code-score-control)
- [8. Android TV App Logic](#8-android-tv-app-logic)
- [9. Display Modes & Transitions](#9-display-modes--transitions)
- [10. Best Practices](#10-best-practices)
---
## 1. Overview
The **Score Control Unit (Android tablet)** sends **real-time data** to **two Android TVs**:
| Display | Purpose |
|--------|--------|
| **Scoreboard TV** | Live match: score, timer, fighter info |
| **Upcoming Matches TV** | Lobby: next matches, tournament flow |
All communication is:
-**Real-time**
-**Bidirectional-ready** (optional)
-**Over Wi-Fi (TCP)**
-**Zero-config for users**
---
## 2. System Architecture
```
[Score Control Tablet] → Wi-Fi → [Scoreboard TV (Port 5001)]
[Upcoming Matches TV (Port 5002)]
```
- Score Control acts as **TCP server**
- TVs act as **TCP clients**
- TVs connect at startup and **stay connected**
- Score Control **broadcasts** JSON messages
> ✅ All devices on same network (`TKD_SCORING_COURT1`)
---
## 3. Communication Protocol (TCP)
### 🔌 Connection Flow
1. TV powers on → connects to `TKD_SCORING_COURT1`
2. TV app starts → connects to tablet IP (`192.168.4.1`)
3. TV sends identity:
```
DISPLAY:NAME=TV_SCOREBOARD,TYPE=SCOREBOARD,MAC=18:3D:A2:01:02:03
```
4. Score Control registers TV
5. TV listens for JSON messages
---
## 4. Scoreboard (Live Match Display)
Displays real-time match data.
### 🖼️ 13 Display Elements
| Element | Source |
|-------|--------|
| Court Number | Match data |
| Match Number | Schedule |
| Match Timer | App timer |
| Round Counter | Match state |
| Country Flag | Fighter data |
| Country ISO3 | Fighter data |
| Team Logo | Fighter data |
| Fighter Name | Match setup |
| Fighter Score | Scoring engine |
| Fighter Fouls | Penalty tracker |
| Fighter Weight (kg) | Fighter profile |
| Weight Class & Category | Match data |
| Team Name | Fighter data |
---
### 🔄 Display Modes
| Mode | Trigger | Duration |
|------|--------|---------|
| `faceoff` | Before match | 10 sec |
| `score` | Match start | 2:00 |
| `break` | Round end | 60 sec |
| `call_to_action` | Last 10 sec of break | 10 sec |
| `winner` | Match end | 15 sec |
---
## 5. Upcoming Matches Screen
Displays next 35 matches.
### 🖼️ Display Elements
- Match number
- Red vs Blue names
- Weight class
- Round
- Scheduled time
- Tournament logo
### 🔄 Auto-Advance
- Updates when current match ends
- Pulls from CSV or cloud
- Scrolls if more than 5 matches
---
## 6. Message Format (JSON)
All messages are **JSON** and end with `\n`.
---
### 6.1 To Scoreboard TV (Port 5001)
#### `faceoff` Mode
```json
{
"mode": "faceoff",
"red": {
"name": "Kim Min-jae",
"country": "KOR",
"flag": "https://flags/kor.png",
"photo": "https://photos/kim.jpg"
},
"blue": {
"name": "Lee Jung-ho",
"country": "CHN",
"flag": "https://flags/chn.png",
"photo": "https://photos/lee.jpg"
},
"weight_class": "Men's -68kg",
"round": "Semifinal"
}
```
#### `score` Mode
```json
{
"mode": "score",
"court": "1",
"match_number": "105",
"weight_class": "Men's -68kg",
"category": "Semifinal",
"round": "2",
"timer": "01:45",
"red": {
"name": "Kim Min-jae",
"country": "KOR",
"team": "Seoul TKD Club",
"logo": "https://logos/seoul.png",
"flag": "https://flags/kor.png",
"score": 8,
"fouls": 1,
"weight_kg": 67.2
},
"blue": {
"name": "Lee Jung-ho",
"country": "CHN",
"team": "Beijing TKD",
"logo": "https://logos/beijing.png",
"flag": "https://flags/chn.png",
"score": 5,
"fouls": 2,
"weight_kg": 67.8
}
}
```
#### `break` Mode
```json
{
"mode": "break",
"ad_image": "https://ads/sponsor1.png",
"highlight_video": "https://videos/round1.mp4",
"countdown": true
}
```
#### `call_to_action` Mode
```json
{
"mode": "call_to_action",
"message": "FIGHTERS, RETURN TO THE RING!",
"timer": 10
}
```
#### `winner` Mode
```json
{
"mode": "winner",
"winner": "red",
"red": {
"name": "Kim Min-jae",
"photo": "https://photos/kim.jpg",
"final_score": 8
},
"blue": {
"name": "Lee Jung-ho",
"photo": "https://photos/lee.jpg",
"final_score": 5
},
"weight_class": "Men's -68kg",
"round": "Final",
"animation": "fireworks"
}
```
---
### 6.2 To Upcoming Matches TV (Port 5002)
```json
{
"mode": "next_matches",
"matches": [
{
"match_number": "106",
"red": "Park S.",
"blue": "Wang L.",
"weight": "+87kg",
"round": "Final",
"time": "11:30",
"category": "Men's"
},
{
"match_number": "107",
"red": "Choi M.",
"blue": "Tanaka Y.",
"weight": "-58kg",
"round": "Semifinal",
"time": "11:50",
"category": "Women's"
}
],
"tournament_name": "National Taekwondo Championship 2025",
"logo": "https://logos/tournament.png"
}
```
---
## 7. C# Server Code (Score Control)
```csharp
public class DisplayServer
{
private TcpListener _scoreboardServer;
private TcpListener _matchesServer;
private List<TcpClient> _scoreboardClients = new();
private List<TcpClient> _matchesClients = new();
public async Task Start()
{
_scoreboardServer = new TcpListener(IPAddress.Any, 5001);
_matchesServer = new TcpListener(IPAddress.Any, 5002);
_scoreboardServer.Start();
_matchesServer.Start();
_ = AcceptScoreboardClients();
_ = AcceptMatchesClients();
}
private async Task AcceptScoreboardClients()
{
while (true)
{
var client = await _scoreboardServer.AcceptTcpClientAsync();
_scoreboardClients.Add(client);
_ = HandleDisplayClient(client, "SCOREBOARD");
}
}
private async Task AcceptMatchesClients()
{
while (true)
{
var client = await _matchesServer.AcceptTcpClientAsync();
_matchesClients.Add(client);
_ = HandleDisplayClient(client, "MATCHES");
}
}
private async Task HandleDisplayClient(TcpClient client, string type)
{
using var stream = client.GetStream();
using var reader = new StreamReader(stream);
string identity = await reader.ReadLineAsync();
// Validate: DISPLAY:NAME=...,TYPE=...,MAC=...
// Keep connection open
while (client.Connected)
{
await Task.Delay(1000); // Wait for broadcast
}
// Remove on disconnect
if (type == "SCOREBOARD")
_scoreboardClients.Remove(client);
else
_matchesClients.Remove(client);
}
public void BroadcastToScoreboard(object data)
{
string json = JsonSerializer.Serialize(data) + "\n";
byte[] bytes = Encoding.UTF8.GetBytes(json);
for (int i = _scoreboardClients.Count - 1; i >= 0; i--)
{
var client = _scoreboardClients[i];
if (client?.Connected == true)
{
try
{
client.GetStream().Write(bytes, 0, bytes.Length);
}
catch
{
_scoreboardClients.RemoveAt(i); // Cleanup
}
}
}
}
public void BroadcastToMatches(object data)
{
string json = JsonSerializer.Serialize(data) + "\n";
byte[] bytes = Encoding.UTF8.GetBytes(json);
for (int i = _matchesClients.Count - 1; i >= 0; i--)
{
var client = _matchesClients[i];
if (client?.Connected == true)
{
try
{
client.GetStream().Write(bytes, 0, bytes.Length);
}
catch
{
_matchesClients.RemoveAt(i);
}
}
}
}
}
```
---
## 8. Android TV App Logic
### 📺 Scoreboard TV App
- Connects to `192.168.4.1:5001`
- Sends identity
- Listens for JSON
- Renders based on `mode`
- Supports video playback for `highlight_video`
### 📺 Upcoming Matches TV App
- Connects to `192.168.4.1:5002`
- Displays scrollable list
- Updates on new message
- Shows tournament logo
---
## 9. Display Modes & Transitions
| Action | Broadcast To | Mode |
|-------|--------------|------|
| Match selected | Scoreboard | `faceoff` |
| "Shi-jak" pressed | Scoreboard | `score` |
| Round ends | Scoreboard | `break` |
| 10 sec before next round | Scoreboard | `call_to_action` |
| Match ends | Scoreboard | `winner` |
| Match ends | Upcoming Matches | `next_matches` |
| Tournament starts | Upcoming Matches | `next_matches` |
---
## 10. Best Practices
| Practice | Why |
|--------|-----|
| Use separate ports (5001, 5002) | Avoid mode conflicts |
| Send `\n` after each message | Easy parsing |
| Validate device identity | Security |
| Reconnect logic on TV | Handle Wi-Fi drops |
| Broadcast only on change | Reduce network load |
| Use UTC time in logs | Debugging |
| Include `mode` in every message | Safe rendering |
---
🎯 **This document fully defines the communication between Score Control and Displays.**
You now have everything to build **real-time, synchronized, broadcast-quality displays**.
📬 For help: Contact project lead.
```
---
### ✅ How to Use
1. Save as `DISPLAY_COMMUNICATION.md`
2. Place in `/docs` folder
3. Commit to GitHub
---
Let me know if you want:
- A **Figma mockup** of the TV screens
- A **sample Android TV app** (Kotlin)
- A **test tool** to simulate messages
- A **Lottie animation** for the winner screen
You're now building a **fully integrated, professional tournament system**. 🏆