java案例统计伤病停赛影响数据对比?

wen java案例 4

本文目录导读:

java案例统计伤病停赛影响数据对比?

  1. 系统架构设计
  2. 统计分析引擎
  3. 数据统计结果类
  4. 数据可视化组件
  5. 主程序入口
  6. 扩展功能
  7. 使用建议

我将为您设计一个Java案例,用于统计和分析体育赛事中伤病停赛对球队表现的影响,这个系统将包括数据模型、统计分析和可视化展示。

系统架构设计

// 1. 基础数据模型
public class Player {
    private int id;
    private String name;
    private String position;
    private int age;
    private double marketValue;
    private double performanceRating;
    // 构造函数、getter/setter
    public Player(int id, String name, String position, int age, 
                  double marketValue, double performanceRating) {
        this.id = id;
        this.name = name;
        this.position = position;
        this.age = age;
        this.marketValue = marketValue;
        this.performanceRating = performanceRating;
    }
    // getters and setters...
}
public class InjuryRecord {
    private int playerId;
    private String injuryType;
    private LocalDate injuryDate;
    private LocalDate returnDate;
    private int daysOut;
    private String severity; // "轻度", "中度", "严重"
    public InjuryRecord(int playerId, String injuryType, 
                       LocalDate injuryDate, LocalDate returnDate) {
        this.playerId = playerId;
        this.injuryType = injuryType;
        this.injuryDate = injuryDate;
        this.returnDate = returnDate;
        this.daysOut = ChronoUnit.DAYS.between(injuryDate, returnDate);
        this.severity = classifySeverity(daysOut);
    }
    private String classifySeverity(int days) {
        if (days < 7) return "轻度";
        else if (days < 30) return "中度";
        else return "严重";
    }
}
public class Team {
    private String name;
    private Map<Integer, Player> players;
    private List<MatchResult> matchResults;
    public Team(String name) {
        this.name = name;
        this.players = new HashMap<>();
        this.matchResults = new ArrayList<>();
    }
}
public class MatchResult {
    private LocalDate matchDate;
    private String opponent;
    private int goalsFor;
    private int goalsAgainst;
    private List<Integer> injuredPlayersDuringMatch;
    private double possession;
    private int shotsOnTarget;
    private int tackles;
    public MatchResult(LocalDate matchDate, String opponent, 
                      int goalsFor, int goalsAgainst, 
                      List<Integer> injuredPlayersDuringMatch,
                      double possession, int shotsOnTarget, int tackles) {
        this.matchDate = matchDate;
        this.opponent = opponent;
        this.goalsFor = goalsFor;
        this.goalsAgainst = goalsAgainst;
        this.injuredPlayersDuringMatch = injuredPlayersDuringMatch;
        this.possession = possession;
        this.shotsOnTarget = shotsOnTarget;
        this.tackles = tackles;
    }
}

统计分析引擎

public class InjuryImpactAnalyzer {
    private Team team;
    private Map<Integer, List<InjuryRecord>> playerInjuries;
    public InjuryImpactAnalyzer(Team team) {
        this.team = team;
        this.playerInjuries = new HashMap<>();
    }
    // 核心统计方法
    public ImpactStatistics analyzeImpact() {
        ImpactStatistics stats = new ImpactStatistics();
        // 1. 基本统计
        stats.setTotalMatches(team.matchResults.size());
        stats.setAverageInjuriesPerMatch(calculateAvgInjuriesPerMatch());
        // 2. 胜率对比
        stats.setWinRateWithInjuries(calculateWinRate(true));
        stats.setWinRateWithoutInjuries(calculateWinRate(false));
        // 3. 进球效率
        stats.setAvgGoalsWithInjuries(calculateAvgGoals(true));
        stats.setAvgGoalsWithoutInjuries(calculateAvgGoals(false));
        // 4. 防守效率
        stats.setAvgConcededWithInjuries(calculateAvgConceded(true));
        stats.setAvgConcededWithoutInjuries(calculateAvgConceded(false));
        // 5. 控球率影响
        stats.setPossessionImpact(calculatePossessionImpact());
        // 6. 关键球员影响
        stats.setKeyPlayerImpact(analyzeKeyPlayers());
        return stats;
    }
    private int calculateAvgInjuriesPerMatch() {
        if (team.matchResults.isEmpty()) return 0;
        int totalInjuries = team.matchResults.stream()
            .mapToInt(m -> m.injuredPlayersDuringMatch.size())
            .sum();
        return totalInjuries / team.matchResults.size();
    }
    private double calculateWinRate(boolean withInjuries) {
        List<MatchResult> matches = filterMatches(withInjuries);
        if (matches.isEmpty()) return 0;
        long wins = matches.stream()
            .filter(m -> m.goalsFor > m.goalsAgainst)
            .count();
        return (double) wins / matches.size() * 100;
    }
    private List<MatchResult> filterMatches(boolean withInjuries) {
        return team.matchResults.stream()
            .filter(m -> withInjuries ? 
                !m.injuredPlayersDuringMatch.isEmpty() : 
                m.injuredPlayersDuringMatch.isEmpty())
            .collect(Collectors.toList());
    }
    private double calculateAvgGoals(boolean withInjuries) {
        List<MatchResult> matches = filterMatches(withInjuries);
        if (matches.isEmpty()) return 0;
        return matches.stream()
            .mapToInt(m -> m.goalsFor)
            .average()
            .orElse(0);
    }
    private double calculateAvgConceded(boolean withInjuries) {
        List<MatchResult> matches = filterMatches(withInjuries);
        if (matches.isEmpty()) return 0;
        return matches.stream()
            .mapToInt(m -> m.goalsAgainst)
            .average()
            .orElse(0);
    }
    private double calculatePossessionImpact() {
        List<MatchResult> matchesWithInjuries = filterMatches(true);
        List<MatchResult> matchesWithoutInjuries = filterMatches(false);
        if (matchesWithInjuries.isEmpty() || matchesWithoutInjuries.isEmpty()) return 0;
        double avgPossessionWithInjuries = matchesWithInjuries.stream()
            .mapToDouble(m -> m.possession)
            .average().orElse(0);
        double avgPossessionWithoutInjuries = matchesWithoutInjuries.stream()
            .mapToDouble(m -> m.possession)
            .average().orElse(0);
        return avgPossessionWithoutInjuries - avgPossessionWithInjuries;
    }
    private Map<String, Double> analyzeKeyPlayers() {
        Map<String, Double> keyPlayerImpact = new HashMap<>();
        // 分析每位球员缺阵时的球队表现
        for (Player player : team.players.values()) {
            String playerName = player.getName();
            List<MatchResult> matchesWithoutPlayer = team.matchResults.stream()
                .filter(m -> m.injuredPlayersDuringMatch.contains(player.getId()))
                .collect(Collectors.toList());
            if (!matchesWithoutPlayer.isEmpty()) {
                double winRate = matchesWithoutPlayer.stream()
                    .filter(m -> m.goalsFor > m.goalsAgainst)
                    .count() / (double) matchesWithoutPlayer.size() * 100;
                keyPlayerImpact.put(playerName, winRate);
            }
        }
        return keyPlayerImpact;
    }
}

数据统计结果类

public class ImpactStatistics {
    private int totalMatches;
    private int averageInjuriesPerMatch;
    private double winRateWithInjuries;
    private double winRateWithoutInjuries;
    private double avgGoalsWithInjuries;
    private double avgGoalsWithoutInjuries;
    private double avgConcededWithInjuries;
    private double avgConcededWithoutInjuries;
    private double possessionImpact;
    private Map<String, Double> keyPlayerImpact;
    // getters and setters...
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("=== 伤病停赛影响统计分析 ===\n");
        sb.append(String.format("总比赛场次: %d\n", totalMatches));
        sb.append(String.format("平均每场伤病人数: %.2f\n", averageInjuriesPerMatch));
        sb.append("\n【胜率对比】\n");
        sb.append(String.format("有伤病: %.1f%% | 无伤病: %.1f%%\n", 
            winRateWithInjuries, winRateWithoutInjuries));
        sb.append(String.format("影响差: %.1f%%\n", 
            winRateWithoutInjuries - winRateWithInjuries));
        sb.append("\n【进球效率】\n");
        sb.append(String.format("有伤病: %.2f球/场 | 无伤病: %.2f球/场\n", 
            avgGoalsWithInjuries, avgGoalsWithoutInjuries));
        sb.append("\n【防守表现】\n");
        sb.append(String.format("有伤病失球: %.2f球/场 | 无伤病失球: %.2f球/场\n", 
            avgConcededWithInjuries, avgConcededWithoutInjuries));
        sb.append("\n【控球率影响】\n");
        sb.append(String.format("平均降低: %.1f%%\n", possessionImpact));
        if (!keyPlayerImpact.isEmpty()) {
            sb.append("\n【关键球员影响】\n");
            keyPlayerImpact.forEach((player, winRate) -> 
                sb.append(String.format("%s缺阵时胜率: %.1f%%\n", player, winRate)));
        }
        return sb.toString();
    }
}

数据可视化组件

import java.awt.*;
import javax.swing.*;
public class ImpactChartPanel extends JPanel {
    private ImpactStatistics stats;
    public ImpactChartPanel(ImpactStatistics stats) {
        this.stats = stats;
        setPreferredSize(new Dimension(800, 500));
    }
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
                             RenderingHints.VALUE_ANTIALIAS_ON);
        // 绘制柱状图
        drawBarChart(g2d);
        // 绘制饼图
        // drawPieChart(g2d);
    }
    private void drawBarChart(Graphics2D g2d) {
        int margin = 50;
        int barWidth = 40;
        int chartHeight = 300;
        int maxValue = 100;
        // 标题
        g2d.setColor(Color.BLACK);
        g2d.setFont(new Font("Arial", Font.BOLD, 16));
        g2d.drawString("伤病对胜率的影响", 300, 30);
        // 数据条
        int xPos = margin;
        // Win rate with injuries
        g2d.setColor(Color.RED);
        int height = (int)(stats.getWinRateWithInjuries() / maxValue * chartHeight);
        g2d.fillRect(xPos, 300 - height, barWidth, height);
        g2d.drawString(String.format("%.1f%%", stats.getWinRateWithInjuries()), 
                      xPos, 320);
        xPos += 100;
        // Win rate without injuries
        g2d.setColor(Color.GREEN);
        height = (int)(stats.getWinRateWithoutInjuries() / maxValue * chartHeight);
        g2d.fillRect(xPos, 300 - height, barWidth, height);
        g2d.drawString(String.format("%.1f%%", stats.getWinRateWithoutInjuries()), 
                      xPos, 320);
        // 图例
        g2d.setColor(Color.RED);
        g2d.fillRect(margin, 350, 20, 20);
        g2d.setColor(Color.BLACK);
        g2d.drawString("有伤病", margin + 25, 365);
        g2d.setColor(Color.GREEN);
        g2d.fillRect(margin + 100, 350, 20, 20);
        g2d.setColor(Color.BLACK);
        g2d.drawString("无伤病", margin + 125, 365);
    }
}

主程序入口

public class InjuryImpactAnalysisSystem {
    public static void main(String[] args) {
        // 1. 创建球队数据
        Team team = createSampleTeam();
        // 2. 创建分析器
        InjuryImpactAnalyzer analyzer = new InjuryImpactAnalyzer(team);
        // 3. 执行分析
        ImpactStatistics stats = analyzer.analyzeImpact();
        // 4. 输出结果
        System.out.println(stats);
        // 5. 生成可视化图表
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("伤病影响分析");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(new ImpactChartPanel(stats));
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        });
        // 6. 导出CSV报告
        exportToCSV(stats);
    }
    private static Team createSampleTeam() {
        Team team = new Team("示例足球俱乐部");
        // 创建球员
        addPlayer(team, 1, "前锋A", "前锋", 25, 8000000, 85);
        addPlayer(team, 2, "中场B", "中场", 28, 6500000, 88);
        addPlayer(team, 3, "后卫C", "后卫", 26, 7000000, 82);
        // ... 更多球员
        // 添加比赛数据
        addMatchResult(team, LocalDate.of(2024, 1, 15), "对手1", 
                      2, 1, Arrays.asList(), 55.5, 15, 20);
        addMatchResult(team, LocalDate.of(2024, 1, 22), "对手2",
                      1, 2, Arrays.asList(1), 48.2, 10, 18);
        addMatchResult(team, LocalDate.of(2024, 2, 1), "对手3",
                      3, 0, Arrays.asList(), 60.1, 18, 22);
        // ... 更多比赛
        // 添加伤病记录
        analyzer.addInjuryRecord(1, "大腿肌肉拉伤", 
                                LocalDate.of(2024, 1, 20), 
                                LocalDate.of(2024, 2, 5));
        return team;
    }
    private static void exportToCSV(ImpactStatistics stats) {
        try (FileWriter writer = new FileWriter("injury_impact_report.csv")) {
            writer.append("指标,有伤病,无伤病,差异\n");
            writer.append(String.format("胜率,%s,%s,%s\n", 
                formatPercent(stats.getWinRateWithInjuries()),
                formatPercent(stats.getWinRateWithoutInjuries()),
                formatPercent(stats.getWinRateWithoutInjuries() - 
                              stats.getWinRateWithInjuries())));
            writer.append(String.format("场均进球,%s,%s,%s\n",
                stats.getAvgGoalsWithInjuries(),
                stats.getAvgGoalsWithoutInjuries(),
                stats.getAvgGoalsWithoutInjuries() - 
                stats.getAvgGoalsWithInjuries()));
            writer.append(String.format("场均失球,%s,%s,%s\n",
                stats.getAvgConcededWithInjuries(),
                stats.getAvgConcededWithoutInjuries(),
                stats.getAvgConcededWithoutInjuries() - 
                stats.getAvgConcededWithInjuries()));
            writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    private static String formatPercent(double value) {
        return String.format("%.1f%%", value);
    }
}

扩展功能

// 1. 预测模型
public class InjuryRiskPredictor {
    public double predictImpact(Player player, int daysOut) {
        // 基于历史数据建立预测模型
        double baseImpact = 0.3;
        double severityMultiplier = daysOut > 30 ? 1.5 : 
                                  daysOut > 15 ? 1.2 : 1.0;
        double positionMultiplier = player.getPosition().equals("前锋") ? 
                                  0.35 : 0.25;
        return baseImpact * severityMultiplier * 
               (player.getPerformanceRating() / 100);
    }
}
// 2. 可视化增强
public class RadarChart extends JPanel {
    private double[] values;
    private String[] labels;
    // 雷达图绘制逻辑
}
// 3. 时间序列分析
public class TimeSeriesAnalyzer {
    public Map<LocalDate, Double> calculateTrend(List<MatchResult> matches) {
        // 计算滚动平均胜率
        int windowSize = 5;
        Map<LocalDate, Double> trends = new LinkedHashMap<>();
        for (int i = windowSize; i <= matches.size(); i++) {
            double avg = matches.subList(i - windowSize, i).stream()
                .mapToDouble(m -> m.goalsFor > m.goalsAgainst ? 100 : 0)
                .average().orElse(0);
            trends.put(matches.get(i).getMatchDate(), avg);
        }
        return trends;
    }
}

使用建议

  1. 数据准备:确保数据完整,包括球员历史表现、伤病记录和完整比赛数据
  2. 指标选择:根据项目需求选择关键指标,如胜率、进球效率、防守稳定性等
  3. 可视化选择:根据受众选择图表类型,管理层面板推荐使用折线图和柱状图
  4. 定期更新:系统应支持数据定期更新,保持统计分析的时效性
  5. 结合业务:分析结果应结合俱乐部实际运营情况,给出针对性建议

这个系统可以很好地帮助教练组和管理层了解伤病对球队的影响,为阵容调整和伤病管理提供数据支持。

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