java案例统计马赛回旋使用频率如何?

wen java案例 3

本文目录导读:

java案例统计马赛回旋使用频率如何?

  1. 完整Java实现
  2. 使用建议

统计马赛回旋使用频率”的Java案例,这是一个比较具体的足球数据分析项目,我来为你设计一个完整的实现方案。

马赛回旋(Marseille Turn)是足球中的一种过人技巧,由齐达内等球星发扬光大,统计其使用频率需要从比赛数据中识别该动作。

完整Java实现

数据模型设计

// 动作数据模型
public class FootballAction {
    private String playerName;
    private String team;
    private String actionType;  // "MARSEILLE_TURN", "OTHER"
    private double timestamp;   // 比赛时间(分钟)
    private double x, y;        // 位置坐标
    private boolean successful; // 是否成功
    // 构造函数、getter/setter省略
    public FootballAction(String playerName, String team, String actionType, 
                         double timestamp, double x, double y, boolean successful) {
        this.playerName = playerName;
        this.team = team;
        this.actionType = actionType;
        this.timestamp = timestamp;
        this.x = x;
        this.y = y;
        this.successful = successful;
    }
    // getter/setter...
}

马赛回旋识别算法

public class MarseilleTurnDetector {
    // 识别马赛回旋的核心算法
    public static boolean isMarseilleTurn(double[] positions) {
        // positions是球员的轨迹点序列 [x1,y1,x2,y2,...,xn,yn]
        if (positions.length < 6) return false;  // 至少需要3个点
        double startX = positions[0];
        double startY = positions[1];
        double endX = positions[positions.length - 2];
        double endY = positions[positions.length - 1];
        // 1. 检查是否发生旋转(角度变化)
        double rotationAngle = calculateRotationAngle(positions);
        if (Math.abs(rotationAngle) < 150) return false;  // 旋转角度需大于150度
        // 2. 检查结束位置与起始位置的关系
        double displacement = Math.sqrt(Math.pow(endX - startX, 2) + Math.pow(endY - startY, 2));
        double traveledDistance = calculateTraveledDistance(positions);
        // 3. 马赛回旋的特点是:位移小但路径长(小半径旋转)
        double pathToDisplacementRatio = traveledDistance / (displacement + 0.001);
        if (pathToDisplacementRatio < 2.0) return false;
        // 4. 检查是否绕过对手(假设对手位置已知)
        // 这里简化为检查旋转中心附近是否有对手
        return true;
    }
    private static double calculateRotationAngle(double[] positions) {
        // 简化计算:使用首尾点和中间点的角度
        if (positions.length < 6) return 0;
        double midX = positions[positions.length / 2];
        double midY = positions[positions.length / 2 + 1];
        double angle1 = Math.toDegrees(Math.atan2(positions[1] - midY, positions[0] - midX));
        double angle2 = Math.toDegrees(Math.atan2(positions[positions.length-1] - midY, 
                                                 positions[positions.length-2] - midX));
        double diff = angle2 - angle1;
        if (diff > 180) diff -= 360;
        if (diff < -180) diff += 360;
        return diff;
    }
    private static double calculateTraveledDistance(double[] positions) {
        double distance = 0;
        for (int i = 0; i < positions.length - 2; i += 2) {
            distance += Math.sqrt(Math.pow(positions[i+2] - positions[i], 2) + 
                                 Math.pow(positions[i+3] - positions[i+1], 2));
        }
        return distance;
    }
}

统计引擎

public class MarseilleTurnStatistician {
    private Map<String, PlayerStats> playerStatsMap = new HashMap<>();
    private Map<String, TeamStats> teamStatsMap = new HashMap<>();
    public static class PlayerStats {
        private String playerName;
        private int totalAttempts;
        private int successfulAttempts;
        private double totalTimestamp;
        public void addAction(FootballAction action) {
            totalAttempts++;
            if (action.isSuccessful()) {
                successfulAttempts++;
            }
            totalTimestamp += action.getTimestamp();
        }
        public double getSuccessRate() {
            return totalAttempts == 0 ? 0 : (double) successfulAttempts / totalAttempts * 100;
        }
        public double getFrequencyPerMatch() {
            // 假设一场比赛90分钟
            return totalAttempts / (totalTimestamp / 90.0);
        }
        // getter/setter...
    }
    public static class TeamStats {
        private String teamName;
        private int totalAttempts;
        private int successfulAttempts;
        private List<PlayerStats> playerStatsList = new ArrayList<>();
        // 类似的方法...
    }
    // 统计方法
    public void analyzeActions(List<FootballAction> actions) {
        for (FootballAction action : actions) {
            if ("MARSEILLE_TURN".equals(action.getActionType())) {
                updatePlayerStats(action);
                updateTeamStats(action);
            }
        }
    }
    private void updatePlayerStats(FootballAction action) {
        PlayerStats stats = playerStatsMap.computeIfAbsent(
            action.getPlayerName(), k -> new PlayerStats());
        stats.addAction(action);
    }
    private void updateTeamStats(FootballAction action) {
        TeamStats stats = teamStatsMap.computeIfAbsent(
            action.getTeam(), k -> new TeamStats());
        stats.totalAttempts++;
        if (action.isSuccessful()) {
            stats.successfulAttempts++;
        }
    }
    // 排名输出
    public String generateRankingReport() {
        StringBuilder report = new StringBuilder();
        report.append("=== 马赛回旋使用频率统计报告 ===\n\n");
        report.append("【球员排名】(按使用次数)\n");
        playerStatsMap.entrySet().stream()
            .sorted(Comparator.comparingInt(e -> -e.getValue().totalAttempts))
            .limit(20)
            .forEach(e -> {
                PlayerStats stats = e.getValue();
                report.append(String.format(
                    "%-20s 尝试:%-3d 成功:%-3d 成功率:%.1f%% 频率:%.2f次/场\n",
                    e.getKey(), stats.totalAttempts, stats.successfulAttempts,
                    stats.getSuccessRate(), stats.getFrequencyPerMatch()));
            });
        return report.toString();
    }
}

主程序单元

public class MarseilleTurnAnalysisApp {
    public static void main(String[] args) {
        // 模拟数据(实际应从数据源加载)
        List<FootballAction> actions = generateSimulatedData();
        // 创建统计引擎
        MarseilleTurnStatistician statistician = new MarseilleTurnStatistician();
        // 执行分析
        statistician.analyzeActions(actions);
        // 输出报告
        System.out.println(statistician.generateRankingReport());
        // 可视化(可选)
        generateVisualizationCharts(statistician);
    }
    private static List<FootballAction> generateSimulatedData() {
        List<FootballAction> actions = new ArrayList<>();
        // 模拟几位球员的数据
        String[][] playerData = {
            {"齐达内", "法国队", "3", "TRUE"},
            {"梅西", "阿根廷队", "2", "TRUE"},
            {"内马尔", "巴西队", "5", "FALSE"},
            {"C罗", "葡萄牙队", "1", "TRUE"},
            {"德布劳内", "比利时队", "2", "FALSE"}
        };
        Random random = new Random(42);
        for (String[] data : playerData) {
            int attemptCount = Integer.parseInt(data[2]);
            for (int i = 0; i < attemptCount * 3; i++) {
                boolean successful = random.nextBoolean();
                FootballAction action = new FootballAction(
                    data[0], data[1], "MARSEILLE_TURN",
                    random.nextDouble() * 90,
                    random.nextDouble() * 100, random.nextDouble() * 50,
                    successful
                );
                actions.add(action);
            }
        }
        return actions;
    }
    private static void generateVisualizationCharts(MarseilleTurnStatistician statistician) {
        // 使用JavaFX或Chart库生成图表
        // 这里简单输出为文本
        System.out.println("\n【可视化占位】");
        System.out.println("建议使用JavaFX/JFreeChart生成柱状图、饼图");
    }
}

进阶功能

public class AdvancedMarseilleTurnAnalyzer {
    // 按比赛阶段分析
    public Map<String, Integer> analyzeByMatchPhase(List<FootballAction> actions) {
        Map<String, Integer> phaseStats = new HashMap<>();
        for (FootballAction action : actions) {
            String phase;
            double time = action.getTimestamp();
            if (time < 15) phase = "开场阶段(0-15min)";
            else if (time < 30) phase = "热身阶段(15-30min)";
            else if (time < 45) phase = "上半场末段(30-45min)";
            else if (time < 60) phase = "下半场初段(45-60min)";
            else if (time < 75) phase = "关键阶段(60-75min)";
            else phase = "决胜阶段(75-90min)";
            phaseStats.merge(phase, 1, Integer::sum);
        }
        return phaseStats;
    }
    // 按位置分析
    public Map<String, Integer> analyzeByFieldPosition(List<FootballAction> actions) {
        Map<String, Integer> positionStats = new HashMap<>();
        for (FootballAction action : actions) {
            String zone;
            if (action.getX() < 33) zone = "防守三区";
            else if (action.getX() < 66) zone = "中场区域";
            else zone = "进攻三区";
            positionStats.merge(zone, 1, Integer::sum);
        }
        return positionStats;
    }
}

使用建议

数据源集成

// 从FIFA比赛数据或Kaggle数据集加载
public interface IFootballDataLoader {
    List<FootballAction> loadMatchData(String matchId);
    List<FootballAction> loadSeasonData(String season);
}

性能优化

// 使用并行流处理大数据
public void analyzeLargeDataset(List<FootballAction> actions) {
    actions.parallelStream()
        .filter(a -> "MARSEILLE_TURN".equals(a.getActionType()))
        .forEach(this::processAction);
}

这套系统可以用于:

  • 球员技术统计比较
  • 战术分析
  • 球探报告生成
  • 比赛直播实时统计

需要我详细解释某个部分或添加特定功能吗?

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