java案例统计高球传中争顶成功率?

wen java案例 4

本文目录导读:

java案例统计高球传中争顶成功率?

  1. 整体设计思路
  2. 核心代码实现
  3. 核心功能特性
  4. 扩展建议

我来为您设计一个Java案例,用于统计足球比赛中高球传中争顶成功率。

整体设计思路

// 主要实体类
// 1. 球员类 (Player)
// 2. 传中事件类 (CrossEvent)
// 3. 争顶事件类 (AerialDuel)
// 4. 统计服务类 (AerialDuelStatisticsService)

核心代码实现

基础实体类

import java.time.LocalDateTime;
import java.util.*;
// 球员类
class Player {
    private String id;
    private String name;
    private String team;
    private String position;
    public Player(String id, String name, String team, String position) {
        this.id = id;
        this.name = name;
        this.team = team;
        this.position = position;
    }
    // Getters and Setters
    public String getId() { return id; }
    public String getName() { return name; }
    public String getTeam() { return team; }
    public String getPosition() { return position; }
}
// 传中事件类
class CrossEvent {
    private String id;
    private Player crosser;          // 传中球员
    private Player receiver;          // 可能的接应球员
    private double x;                 // 传中位置x坐标
    private double y;                 // 传中位置y坐标
    private LocalDateTime timestamp;
    private String crossType;         // 高球传中、低平球传中、45度传中等
    private boolean isSuccessful;     // 传中是否成功
    public CrossEvent(String id, Player crosser, Player receiver, 
                     double x, double y, String crossType) {
        this.id = id;
        this.crosser = crosser;
        this.receiver = receiver;
        this.x = x;
        this.y = y;
        this.timestamp = LocalDateTime.now();
        this.crossType = crossType;
    }
    // Getters and Setters
    public String getId() { return id; }
    public Player getCrosser() { return crosser; }
    public Player getReceiver() { return receiver; }
    public double getX() { return x; }
    public double getY() { return y; }
    public String getCrossType() { return crossType; }
    public boolean isSuccessful() { return isSuccessful; }
    public void setSuccessful(boolean successful) { isSuccessful = successful; }
}
// 争顶事件类
class AerialDuel {
    private String id;
    private CrossEvent crossEvent;
    private Player attacker;         // 进攻球员(争顶球员)
    private Player defender;         // 防守球员
    private boolean isWonByAttacker; // 进攻方是否赢得争顶
    private boolean ledToShooting;   // 争顶后是否形成射门
    private double height;           // 争顶高度
    private LocalDateTime timestamp;
    public AerialDuel(String id, CrossEvent crossEvent, Player attacker, 
                     Player defender, double height) {
        this.id = id;
        this.crossEvent = crossEvent;
        this.attacker = attacker;
        this.defender = defender;
        this.height = height;
        this.timestamp = LocalDateTime.now();
    }
    // Getters and Setters
    public String getId() { return id; }
    public CrossEvent getCrossEvent() { return crossEvent; }
    public Player getAttacker() { return attacker; }
    public Player getDefender() { return defender; }
    public boolean isWonByAttacker() { return isWonByAttacker; }
    public void setWonByAttacker(boolean wonByAttacker) { isWonByAttacker = wonByAttacker; }
    public boolean isLedToShooting() { return ledToShooting; }
    public void setLedToShooting(boolean ledToShooting) { this.ledToShooting = ledToShooting; }
    public double getHeight() { return height; }
}

统计服务类

class AerialDuelStatisticsService {
    // 存储所有争顶事件
    private List<AerialDuel> aerialDuels = new ArrayList<>();
    // 添加争顶事件
    public void addAerialDuel(AerialDuel duel) {
        aerialDuels.add(duel);
    }
    // 计算整体争顶成功率
    public double calculateOverallSuccessRate() {
        if (aerialDuels.isEmpty()) {
            return 0.0;
        }
        long successfulDuels = aerialDuels.stream()
            .filter(AerialDuel::isWonByAttacker)
            .count();
        return (double) successfulDuels / aerialDuels.size() * 100;
    }
    // 按球队统计争顶成功率
    public Map<String, Double> calcularTeamSuccessRate() {
        Map<String, List<AerialDuel>> teamDuels = new HashMap<>();
        for (AerialDuel duel : aerialDuels) {
            String team = duel.getAttacker().getTeam();
            teamDuels.computeIfAbsent(team, k -> new ArrayList<>()).add(duel);
        }
        Map<String, Double> result = new HashMap<>();
        for (Map.Entry<String, List<AerialDuel>> entry : teamDuels.entrySet()) {
            long total = entry.getValue().size();
            long won = entry.getValue().stream()
                .filter(AerialDuel::isWonByAttacker)
                .count();
            result.put(entry.getKey(), (double) won / total * 100);
        }
        return result;
    }
    // 按球员统计争顶成功率
    public Map<String, Double> calculatePlayerSuccessRate() {
        Map<String, List<AerialDuel>> playerDuels = new HashMap<>();
        for (AerialDuel duel : aerialDuels) {
            String playerId = duel.getAttacker().getId();
            playerDuels.computeIfAbsent(playerId, k -> new ArrayList<>()).add(duel);
        }
        Map<String, Double> result = new HashMap<>();
        for (Map.Entry<String, List<AerialDuel>> entry : playerDuels.entrySet()) {
            long total = entry.getValue().size();
            long won = entry.getValue().stream()
                .filter(AerialDuel::isWonByAttacker)
                .count();
            result.put(entry.getKey(), (double) won / total * 100);
        }
        return result;
    }
    // 按传中类型统计争顶成功率
    public Map<String, Double> calculateSuccessRateByCrossType() {
        Map<String, List<AerialDuel>> crossTypeDuels = new HashMap<>();
        for (AerialDuel duel : aerialDuels) {
            String crossType = duel.getCrossEvent().getCrossType();
            crossTypeDuels.computeIfAbsent(crossType, k -> new ArrayList<>()).add(duel);
        }
        Map<String, Double> result = new HashMap<>();
        for (Map.Entry<String, List<AerialDuel>> entry : crossTypeDuels.entrySet()) {
            long total = entry.getValue().size();
            long won = entry.getValue().stream()
                .filter(AerialDuel::isWonByAttacker)
                .count();
            result.put(entry.getKey(), (double) won / total * 100);
        }
        return result;
    }
    // 统计争顶后形成射门的效率
    public double calculateShootingConversionRate() {
        if (aerialDuels.isEmpty()) {
            return 0.0;
        }
        long ledToShooting = aerialDuels.stream()
            .filter(AerialDuel::isWonByAttacker)
            .filter(AerialDuel::isLedToShooting)
            .count();
        return (double) ledToShooting / aerialDuels.size() * 100;
    }
    // 按球员位置统计争顶成功率
    public Map<String, Double> calculateSuccessRateByPosition() {
        Map<String, List<AerialDuel>> positionDuels = new HashMap<>();
        for (AerialDuel duel : aerialDuels) {
            String position = duel.getAttacker().getPosition();
            positionDuels.computeIfAbsent(position, k -> new ArrayList<>()).add(duel);
        }
        Map<String, Double> result = new HashMap<>();
        for (Map.Entry<String, List<AerialDuel>> entry : positionDuels.entrySet()) {
            long total = entry.getValue().size();
            long won = entry.getValue().stream()
                .filter(AerialDuel::isWonByAttacker)
                .count();
            result.put(entry.getKey(), (double) won / total * 100);
        }
        return result;
    }
    // 综合统计报告
    public void printDetailedStatistics() {
        System.out.println("========== 高球传中争顶成功率统计报告 ==========");
        System.out.println("1. 整体争顶成功率: " + String.format("%.1f%%", calculateOverallSuccessRate()));
        System.out.println("2. 争顶后形成射门转化率: " + String.format("%.1f%%", calculateShootingConversionRate()));
        System.out.println("\n3. 各球队争顶成功率:");
        calcularTeamSuccessRate().forEach((team, rate) -> 
            System.out.println("   - " + team + ": " + String.format("%.1f%%", rate)));
        System.out.println("\n4. 各球员争顶成功率:");
        calculatePlayerSuccessRate().entrySet().stream()
            .sorted(Map.Entry.<String, Double>comparingByValue().reversed())
            .forEach(entry -> 
                System.out.println("   - 球员ID " + entry.getKey() + ": " + String.format("%.1f%%", entry.getValue())));
        System.out.println("\n5. 各传中类型争顶成功率:");
        calculateSuccessRateByCrossType().forEach((type, rate) -> 
            System.out.println("   - " + type + ": " + String.format("%.1f%%", rate)));
        System.out.println("\n6. 各位置球员争顶成功率:");
        calculateSuccessRateByPosition().forEach((position, rate) -> 
            System.out.println("   - " + position + ": " + String.format("%.1f%%", rate)));
    }
}

测试主程序

import java.util.Random;
public class FootballStatisticsDemo {
    public static void main(String[] args) {
        // 创建球员
        List<Player> players = createPlayers();
        // 创建统计服务
        AerialDuelStatisticsService statisticsService = new AerialDuelStatisticsService();
        // 模拟比赛数据
        Random random = new Random(42); // 固定种子便于测试
        // 模拟100次争顶事件
        for (int i = 0; i < 100; i++) {
            Player attacker = players.get(random.nextInt(players.size()));
            Player defender = players.get(random.nextInt(players.size()));
            Player crosser = players.get(random.nextInt(players.size()));
            // 确保进攻和防守不是同一个球员
            while (attacker.getId().equals(defender.getId())) {
                defender = players.get(random.nextInt(players.size()));
            }
            // 创建传中事件
            String[] crossTypes = {"高球", "低平球", "45度传中", "下底传中"};
            CrossEvent crossEvent = new CrossEvent(
                "C" + i,
                crosser,
                attacker,
                random.nextDouble() * 100,
                random.nextDouble() * 50,
                crossTypes[random.nextInt(crossTypes.length)]
            );
            // 创建争顶事件
            AerialDuel duel = new AerialDuel(
                "AD" + i,
                crossEvent,
                attacker,
                defender,
                random.nextDouble() * 2 + 1.5  // 高度1.5-3.5米
            );
            // 随机设置争顶结果
            duel.setWonByAttacker(random.nextBoolean());
            duel.setLedToShooting(random.nextDouble() < 0.3); // 30%概率形成射门
            // 传中成功与否与争顶结果相关
            crossEvent.setSuccessful(duel.isWonByAttacker());
            statisticsService.addAerialDuel(duel);
        }
        // 打印详细统计报告
        statisticsService.printDetailedStatistics();
        // 额外示例:不同位置的争顶成功率对比
        System.out.println("\n========== 位置分析 ==========");
        Map<String, Double> positionStats = statisticsService.calculateSuccessRateByPosition();
        positionStats.entrySet().stream()
            .sorted(Map.Entry.<String, Double>comparingByValue().reversed())
            .forEach(entry -> {
                StringBuilder bar = new StringBuilder();
                int barLength = (int) (entry.getValue() / 2);
                for (int j = 0; j < barLength; j++) {
                    bar.append("█");
                }
                System.out.println(String.format("%-10s %5.1f%% %s", 
                    entry.getKey(), entry.getValue(), bar.toString()));
            });
    }
    // 创建示例球员
    private static List<Player> createPlayers() {
        List<Player> players = new ArrayList<>();
        // 前锋
        players.add(new Player("ST1", "罗纳尔多", "皇马", "前锋"));
        players.add(new Player("ST2", "莱万", "巴萨", "前锋"));
        players.add(new Player("ST3", "凯恩", "曼城", "前锋"));
        // 中场
        players.add(new Player("MID1", "德布劳内", "曼城", "中场"));
        players.add(new Player("MID2", "克罗斯", "皇马", "中场"));
        players.add(new Player("MID3", "B费", "曼联", "中场"));
        // 后卫
        players.add(new Player("DEF1", "范迪克", "利物浦", "后卫"));
        players.add(new Player("DEF2", "拉莫斯", "巴黎", "后卫"));
        players.add(new Player("DEF3", "鲁本·迪亚斯", "曼城", "后卫"));
        return players;
    }
}

核心功能特性

  1. 多维度统计:支持按球队、球员、位置、传中类型统计
  2. 转化率分析:分析争顶后形成射门的效率
  3. 可视化展示:使用条形图直观展示统计数据
  4. 数据模拟:提供随机数据供测试使用

扩展建议

  1. 添加时间序列分析:按时间段统计争顶成功率变化
  2. 对抗分析:分析特定球员之间的争顶对抗数据
  3. 空间分析:结合传中位置坐标进行热点分析
  4. 机器学习预测:基于历史数据预测争顶成功率

这个案例涵盖了高球传中争顶成功率统计的核心功能,可以根据实际需求进一步扩展和优化。

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