import { ThemedText } from "@/components/themed-text"; import { ThemedView } from "@/components/themed-view"; import { LiveScoreMatch } from "@/types/api"; import React, { useMemo } from "react"; import { useTranslation } from "react-i18next"; import { Image, ScrollView, StyleSheet, View } from "react-native"; interface TennisPowerGraphProps { match: LiveScoreMatch; isDark: boolean; } export function TennisPowerGraph({ match, isDark }: TennisPowerGraphProps) { const { t } = useTranslation(); const pointData = match.pointbypoint; if (!pointData || pointData.length === 0) { return null; } // Grouped Data by Game // Structure: { gameIndex: number, score: string, set: string, points: {winner: 1|2}[] } const gameData = useMemo(() => { return pointData.map((game) => { const points = game.points || []; const bars: { winner: 1 | 2 }[] = []; let prevP1Score = 0; let prevP2Score = 0; const parseScore = (s: string) => { if (s === "A") return 45; return parseInt(s) || 0; }; points.forEach((point: { score: string }) => { const parts = point.score.split("-").map((s) => s.trim()); if (parts.length !== 2) return; const p1 = parseScore(parts[0]); const p2 = parseScore(parts[1]); let winner: 1 | 2 | null = null; if (p1 > prevP1Score && p2 === prevP2Score) winner = 1; else if (p2 > prevP2Score && p1 === prevP1Score) winner = 2; else if (p1 === 45 && prevP1Score === 40) winner = 1; else if (p2 === 45 && prevP2Score === 40) winner = 2; else if (p1 === 40 && prevP1Score === 45) winner = 2; else if (p2 === 40 && prevP2Score === 45) winner = 1; else if ( points.length === 1 && prevP1Score === 0 && prevP2Score === 0 ) { if (p1 > 0) winner = 1; if (p2 > 0) winner = 2; } else if (p1 > prevP1Score || (p2 < prevP2Score && prevP2Score === 45)) winner = 1; else if (p2 > prevP2Score || (p1 < prevP1Score && prevP1Score === 45)) winner = 2; if (winner) { bars.push({ winner }); } prevP1Score = p1; prevP2Score = p2; }); // Find if this game ended a set? Or just carry current set score/game score. // `game.score` is e.g. "1 - 0" (Set Score or Game Score within set?) // Usually `pointbypoint` item has `score` field which is the score in Games for that Set. return { gameIndex: parseInt(game.number_game), setNumber: game.set_number, // "Set 1" score: game.score, // "6 - 4" or "1 - 0" serveWinner: game.serve_winner, // "First Player" or "Second Player" bars, }; }); }, [pointData]); if (gameData.length === 0) return null; // Render logic // Left side: Avatars // Right side: ScrollView of Game Blocks // Avatars const p1Logo = match.event_first_player_logo; const p2Logo = match.event_second_player_logo; return ( {t("detail.power_graph")} {/* Sidebar - Avatars */} {/* Spacer top */} {p1Logo ? ( ) : ( )} {/* Gap corresponding to center line if needed, but styling is easier with even spacing */} {p2Logo ? ( ) : ( )} {/* Spacer bottom */} {/* Scrollable Graph */} {gameData.map((game, i) => { // Updated to match screenshot: Split background (Blue top, Yellow bottom) const topBg = isDark ? "rgba(33, 150, 243, 0.15)" : "#E3F2FD"; const botBg = isDark ? "rgba(255, 193, 7, 0.15)" : "#FFF8E1"; return ( {/* Top Score Label if needed */} {/* Bars Area */} {/* Backgrounds */} {/* Center Line */} {game.bars.map((bar, bi) => ( {/* P1 Bar (Top) */} {bar.winner === 1 && ( )} {/* P2 Bar (Bottom) */} {bar.winner === 2 && ( )} ))} {/* Bottom Game Number */} {game.gameIndex} ); })} ); } const styles = StyleSheet.create({ container: { margin: 16, padding: 16, borderRadius: 12, }, title: { fontSize: 16, fontWeight: "bold", marginBottom: 20, }, contentRow: { flexDirection: "row", height: 120, // Total height for graph area }, sidebar: { width: 40, alignItems: "center", justifyContent: "center", // Center avatars vertically relative to bars paddingBottom: 20, // Adjust for game number row }, avatarContainer: { width: 32, height: 32, borderRadius: 16, overflow: "hidden", borderWidth: 1, borderColor: "#333", }, avatar: { width: "100%", height: "100%", }, graphScroll: { flex: 1, marginLeft: 8, }, gameBlock: { paddingHorizontal: 4, marginRight: 2, minWidth: 40, borderRadius: 4, }, gameTopLabel: { height: 20, alignItems: "center", justifyContent: "center", }, barsArea: { flexDirection: "row", alignItems: "center", height: 60, // Central bar area position: "relative", justifyContent: "center", }, centerLine: { position: "absolute", width: "100%", height: 1, top: 30, // Middle of 60 }, barColumn: { width: 6, marginHorizontal: 1, height: "100%", justifyContent: "center", }, barSegment: { width: "100%", }, activeBar: { width: "100%", borderRadius: 2, }, gameBottomLabel: { height: 20, alignItems: "center", justifyContent: "center", }, gameNumberText: { fontSize: 10, opacity: 0.6, }, });