实时python案例显示场上谁更占优势?

wen python案例 2

我来为您设计一个实时显示场上优势的Python案例,这个案例模拟一场足球比赛,实时计算并显示双方的攻防优势。

实时python案例显示场上谁更占优势?

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import time
from collections import deque
import random
class MatchTracker:
    """实时比赛优势追踪器"""
    def __init__(self, team1="主队", team2="客队"):
        self.team1_name = team1
        self.team2_name = team2
        # 实时数据存储(缓存最近60秒数据)
        self.time_window = 60
        self.timestamps = deque(maxlen=self.time_window)
        # 主队数据
        self.team1_possession = deque(maxlen=self.time_window)  # 控球率
        self.team1_shots = deque(maxlen=self.time_window)      # 射门
        self.team1_corners = deque(maxlen=self.time_window)    # 角球
        self.team1_danger = deque(maxlen=self.time_window)     # 危险进攻
        # 客队数据
        self.team2_possession = deque(maxlen=self.time_window)
        self.team2_shots = deque(maxlen=self.time_window)
        self.team2_corners = deque(maxlen=self.time_window)
        self.team2_danger = deque(maxlen=self.time_window)
        # 综合优势评分
        self.team1_advantage = deque(maxlen=self.time_window)
        self.team2_advantage = deque(maxlen=self.time_window)
        # 比赛数据累计
        self.total_possession_t1 = 50
        self.total_possession_t2 = 50
        self.score_t1 = 0
        self.score_t2 = 0
        # 统计权重
        self.weights = {
            'possession': 0.3,   # 控球率权重
            'shots': 0.25,       # 射门权重
            'corners': 0.15,     # 角球权重
            'danger': 0.3        # 危险进攻权重
        }
        # 创建图表
        self.setup_plot()
    def setup_plot(self):
        """初始化图表布局"""
        self.fig = plt.figure(figsize=(15, 8))
        gs = self.fig.add_gridspec(3, 3)
        # 主优势仪表盘
        self.ax_gauge = self.fig.add_subplot(gs[0, :])
        self.ax_gauge.set_xlim(-1.5, 1.5)
        self.ax_gauge.set_ylim(-1, 1)
        self.ax_gauge.axis('off')
        # 控球率
        self.ax_possession = self.fig.add_subplot(gs[1, 0])
        self.ax_possession.set_ylabel('控球率')
        # 射门统计
        self.ax_shots = self.fig.add_subplot(gs[1, 1])
        self.ax_shots.set_ylabel('射门')
        # 危险进攻
        self.ax_danger = self.fig.add_subplot(gs[1, 2])
        self.ax_danger.set_ylabel('危险进攻')
        # 整体优势趋势
        self.ax_trend = self.fig.add_subplot(gs[2, :])
        self.ax_trend.set_ylabel('优势度')
        self.ax_trend.set_xlabel('时间(秒)')
        self.ax_trend.axhline(y=0, color='gray', linestyle='--', alpha=0.5)
        self.fig.suptitle(f'{self.team1_name} vs {self.team2_name} 实时优势分析', fontsize=16, fontweight='bold')
        # 颜色设置
        self.color_t1 = '#1e88e5'
        self.color_t2 = '#e53935'
    def calculate_advantage(self):
        """计算综合优势"""
        if not self.timestamps:
            return 0, 0
        # 获取最近的数据
        t1_pos = np.mean(self.team1_possession) if self.team1_possession else 50
        t2_pos = np.mean(self.team2_possession) if self.team2_possession else 50
        t1_shot = np.sum(self.team1_shots) if self.team1_shots else 0
        t2_shot = np.sum(self.team2_shots) if self.team2_shots else 0
        t1_corner = np.sum(self.team1_corners) if self.team1_corners else 0
        t2_corner = np.sum(self.team2_corners) if self.team2_corners else 0
        t1_danger = np.sum(self.team1_danger) if self.team1_danger else 0
        t2_danger = np.sum(self.team2_danger) if self.team2_danger else 0
        # 归一化处理
        max_shots = max(t1_shot, t2_shot, 1)
        max_corners = max(t1_corner, t2_corner, 1)
        max_danger = max(t1_danger, t2_danger, 1)
        # 计算各项比分
        possession_score = (t1_pos - t2_pos) / 100
        shots_score = (t1_shot - t2_shot) / max_shots
        corners_score = (t1_corner - t2_corner) / max_corners
        danger_score = (t1_danger - t2_danger) / max_danger
        # 加权计算总优势
        t1_adv = (possession_score * self.weights['possession'] + 
                 shots_score * self.weights['shots'] + 
                 corners_score * self.weights['corners'] + 
                 danger_score * self.weights['danger'])
        # 加上比分权重
        score_advantage = (self.score_t1 - self.score_t2) * 0.2
        return t1_adv + score_advantage, -(t1_adv + score_advantage)
    def update_data(self):
        """模拟实时数据更新"""
        current_time = time.time()
        self.timestamps.append(current_time)
        # 模拟比赛数据(真实应用中从传感器/数据源获取)
        # 主队数据
        t1_possession = 40 + random.uniform(-15, 15)
        t1_shots = random.choice([0, 0, 0, 0, 1, 1, 1, 2])
        t1_corners = random.choice([0, 0, 0, 1, 1, 2])
        t1_danger = random.choice([0, 0, 1, 1, 1, 2, 3])
        # 客队数据(反相关增加对抗性)
        t2_possession = 100 - t1_possession
        t2_shots = random.choice([0, 0, 0, 0, 1, 1, 1, 2])
        t2_corners = random.choice([0, 0, 0, 1, 1, 2])
        t2_danger = random.choice([0, 0, 1, 1, 1, 2, 3])
        # 更新数据存储
        self.team1_possession.append(t1_possession)
        self.team1_shots.append(t1_shots)
        self.team1_corners.append(t1_corners)
        self.team1_danger.append(t1_danger)
        self.team2_possession.append(t2_possession)
        self.team2_shots.append(t2_shots)
        self.team2_corners.append(t2_corners)
        self.team2_danger.append(t2_danger)
        # 更新总控球率
        self.total_possession_t1 = 0.95 * self.total_possession_t1 + 0.05 * t1_possession
        self.total_possession_t2 = 100 - self.total_possession_t1
        # 模拟进球(小概率)
        if random.random() < 0.01:  # 1%概率进球
            if random.random() < 0.5:
                self.score_t1 += 1
                self.team1_advantage.append(0.5)  # 进球加分
            else:
                self.score_t2 += 1
                self.team2_advantage.append(0.5)
        # 计算综合优势
        t1_adv, t2_adv = self.calculate_advantage()
        self.team1_advantage.append(t1_adv)
        self.team2_advantage.append(t2_adv)
    def update_plot(self, frame):
        """更新图表"""
        # 更新数据
        self.update_data()
        # 清空所有子图
        for ax in [self.ax_gauge, self.ax_possession, self.ax_shots,
                  self.ax_danger, self.ax_trend]:
            ax.clear()
        # 1. 仪表盘显示
        advantage = self.team1_advantage[-1] if self.team1_advantage else 0
        self.draw_gauge(self.ax_gauge, advantage)
        # 2. 控球率饼图
        sizes = [self.total_possession_t1, self.total_possession_t2]
        labels = [f'{self.team1_name}\n{sizes[0]:.1f}%', 
                 f'{self.team2_name}\n{sizes[1]:.1f}%']
        colors = [self.color_t1, self.color_t2]
        self.ax_possession.clear()
        wedges, texts, autotexts = self.ax_possession.pie(
            sizes, labels=labels, colors=colors, autopct='%1.1f%%',
            startangle=90, explode=(0.05, 0.05)
        )
        self.ax_possession.set_title('控球率')
        # 3. 射门统计
        if self.team1_shots and self.team2_shots:
            shots_t1 = np.sum(self.team1_shots)
            shots_t2 = np.sum(self.team2_shots)
            self.ax_shots.bar([0, 1], [shots_t1, shots_t2], 
                            color=[self.color_t1, self.color_t2], alpha=0.7)
            self.ax_shots.set_xticks([0, 1])
            self.ax_shots.set_xticklabels([self.team1_name, self.team2_name])
            self.ax_shots.set_title(f'射门(主队:{shots_t1} 客队:{shots_t2})')
        # 4. 危险进攻
        if self.team1_danger and self.team2_danger:
            danger_t1 = np.sum(self.team1_danger)
            danger_t2 = np.sum(self.team2_danger)
            self.ax_danger.bar([0, 1], [danger_t1, danger_t2],
                             color=[self.color_t1, self.color_t2], alpha=0.7)
            self.ax_danger.set_xticks([0, 1])
            self.ax_danger.set_xticklabels([self.team1_name, self.team2_name])
            self.ax_danger.set_title(f'危险进攻(主队:{danger_t1} 客队:{danger_t2})')
        # 5. 优势趋势图
        if len(self.team1_advantage) > 1:
            x = range(len(self.team1_advantage))
            self.ax_trend.plot(x, list(self.team1_advantage), 
                             color=self.color_t1, label=f'{self.team1_name}优势', linewidth=2)
            self.ax_trend.plot(x, list(self.team2_advantage), 
                             color=self.color_t2, label=f'{self.team2_name}优势', linewidth=2)
            # 填充优势区域
            self.ax_trend.fill_between(x, 0, list(self.team1_advantage), 
                                      alpha=0.2, color=self.color_t1)
            self.ax_trend.fill_between(x, 0, list(self.team2_advantage), 
                                      alpha=0.2, color=self.color_t2)
            self.ax_trend.legend(loc='upper right')
            self.ax_trend.grid(True, alpha=0.3)
            self.ax_trend.set_ylim(-1.5, 1.5)
        # 在仪表盘下方显示比分
        self.fig.text(0.5, 0.88, 
                     f'比分: {self.team1_name} {self.score_t1} - {self.score_t2} {self.team2_name}', 
                     ha='center', fontsize=12, color='black',
                     bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.5))
    def draw_gauge(self, ax, value):
        """绘制优势仪表盘"""
        # 背景圆环
        theta = np.linspace(0, 2*np.pi, 100)
        x = np.cos(theta)
        y = np.sin(theta)
        # 绘制半圆背景
        theta_half = np.linspace(np.pi, 2*np.pi, 50)
        ax.fill(np.cos(theta_half), np.sin(theta_half), color='lightgray', alpha=0.3)
        # 绘制优势指示
        angle = np.pi + (np.clip(value, -1, 1) + 1) * np.pi/2
        arrow_length = 0.8
        ax.annotate('', xy=(arrow_length*np.cos(angle), arrow_length*np.sin(angle)),
                   xytext=(0, 0),
                   arrowprops=dict(arrowstyle='->', lw=3, color='black'))
        # 添加标签
        ax.text(0, -0.2, f'优势度: {value:.2f}', ha='center', fontsize=12)
        ax.text(-1.2, 0, self.team1_name, color=self.color_t1, fontweight='bold')
        ax.text(1.2, 0, self.team2_name, color=self.color_t2, fontweight='bold')
        # 绘制刻度和文字
        for i in range(-2, 3):
            angle_i = np.pi + (i + 2) * np.pi/4
            value_i = i/2
            ax.text(1.1*np.cos(angle_i), 1.1*np.sin(angle_i), 
                   f'{value_i:.1f}', ha='center', fontsize=8)
        # 判断优势方
        if value > 0.1:
            ax.text(0, 0.5, f'{self.team1_name}占优!', ha='center', 
                   fontsize=14, color=self.color_t1, fontweight='bold')
        elif value < -0.1:
            ax.text(0, 0.5, f'{self.team2_name}占优!', ha='center',
                   fontsize=14, color=self.color_t2, fontweight='bold')
        else:
            ax.text(0, 0.5, '势均力敌', ha='center', fontsize=14, color='gray')
def main():
    """主函数"""
    # 创建追踪器
    tracker = MatchTracker("主队", "客队")
    # 创建动画
    ani = FuncAnimation(tracker.fig, tracker.update_plot, 
                       interval=1000,  # 1秒更新一次
                       save_count=100)
    print("实时比赛优势追踪器已启动")
    print("按Ctrl+C停止运行")
    try:
        plt.tight_layout()
        plt.show()
    except KeyboardInterrupt:
        print("\n追踪器已停止")
    # 显示最终统计
    print("\n===== 比赛总结 =====")
    print(f"最终比分: {tracker.team1_name} {tracker.score_t1} - {tracker.score_t2} {tracker.team2_name}")
    print(f"最终控球率: {tracker.team1_name} {tracker.total_possession_t1:.1f}% - {tracker.total_possession_t2:.1f}% {tracker.team2_name}")
    if tracker.team1_advantage:
        final_adv = tracker.team1_advantage[-1]
        print(f"最终优势度: {final_adv:.2f}")
        if final_adv > 0.1:
            print(f" {tracker.team1_name}在场上更具优势!")
        elif final_adv < -0.1:
            print(f" {tracker.team2_name}在场上更具优势!")
        else:
            print(" 两队势均力敌")
if __name__ == "__main__":
    main()

运行效果:

  1. 实时仪表盘:顶部显示当前优势度,指针偏向优势方
  2. 控球率:直观的饼图显示双方控球比例
  3. 射门统计:柱状图展示双方射门次数
  4. 危险进攻:显示创造的威胁机会
  5. 优势趋势:动态折线图展示整场比赛的优势变化

扩展建议:

  • 接入真实比赛数据(如API、传感器)
  • 添加更多统计指标(传球成功率、抢断、犯规等)
  • 增加比赛事件标记(进球、红黄牌等)
  • 支持多场比赛同时监控
  • 添加预警系统(某队连续占优时提醒)

这个系统可以用于体育分析、比赛直播辅助、战术分析等场景,实时反映场上哪一方更具优势。

抱歉,评论功能暂时关闭!