# 📡 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 3–5 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**. 🏆