java案例统计落叶球射门成功率如何?

wen java案例 3

本文目录导读:

java案例统计落叶球射门成功率如何?

  1. 落叶球射门成功率统计系统
  2. 主要功能说明
  3. 使用建议

我来为你设计一个Java案例,用于统计和分析落叶球射门成功率。

落叶球射门成功率统计系统

核心模型类

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
// 射门记录类
class ShotRecord {
    private Long id;
    private LocalDateTime shotTime;
    private double distance;      // 射门距离(米)
    private double angle;         // 射门角度(度)
    private double speed;         // 球速(km/h)
    private boolean isKnuckleball; // 是否落叶球
    private boolean isGoal;       // 是否进球
    private String shotArea;      // 射门区域
    // 构造函数、getter/setter省略
    public ShotRecord(Long id, LocalDateTime shotTime, double distance, 
                     double angle, double speed, boolean isKnuckleball, 
                     boolean isGoal, String shotArea) {
        this.id = id;
        this.shotTime = shotTime;
        this.distance = distance;
        this.angle = angle;
        this.speed = speed;
        this.isKnuckleball = isKnuckleball;
        this.isGoal = isGoal;
        this.shotArea = shotArea;
    }
    // Getters
    public Long getId() { return id; }
    public LocalDateTime getShotTime() { return shotTime; }
    public double getDistance() { return distance; }
    public double getAngle() { return angle; }
    public double getSpeed() { return speed; }
    public boolean isKnuckleball() { return isKnuckleball; }
    public boolean isGoal() { return isGoal; }
    public String getShotArea() { return shotArea; }
}
// 统计结果类
class ShotStatistics {
    private int totalShots;
    private int goals;
    private double successRate;
    private double averageSpeed;
    private double averageDistance;
    private Map<String, Integer> shotsByArea;
    private Map<String, Integer> goalsByArea;
    // Getters and Setters
    public int getTotalShots() { return totalShots; }
    public void setTotalShots(int totalShots) { this.totalShots = totalShots; }
    public int getGoals() { return goals; }
    public void setGoals(int goals) { this.goals = goals; }
    public double getSuccessRate() { return successRate; }
    public void setSuccessRate(double successRate) { this.successRate = successRate; }
    public double getAverageSpeed() { return averageSpeed; }
    public void setAverageSpeed(double averageSpeed) { this.averageSpeed = averageSpeed; }
    public double getAverageDistance() { return averageDistance; }
    public void setAverageDistance(double averageDistance) { this.averageDistance = averageDistance; }
    public Map<String, Integer> getShotsByArea() { return shotsByArea; }
    public void setShotsByArea(Map<String, Integer> shotsByArea) { this.shotsByArea = shotsByArea; }
    public Map<String, Integer> getGoalsByArea() { return goalsByArea; }
    public void setGoalsByArea(Map<String, Integer> goalsByArea) { this.goalsByArea = goalsByArea; }
}

统计分析服务类

import java.util.*;
import java.util.stream.Collectors;
public class ShotAnalysisService {
    // 统计分析落叶球射门
    public ShotStatistics analyzeKnuckleballShots(List<ShotRecord> shots) {
        // 筛选出落叶球射门
        List<ShotRecord> knuckleballShots = shots.stream()
            .filter(ShotRecord::isKnuckleball)
            .collect(Collectors.toList());
        ShotStatistics stats = new ShotStatistics();
        // 基础统计
        stats.setTotalShots(knuckleballShots.size());
        stats.setGoals((int) knuckleballShots.stream().filter(ShotRecord::isGoal).count());
        stats.setSuccessRate(calculateSuccessRate(stats.getGoals(), stats.getTotalShots()));
        // 计算平均球速和距离
        stats.setAverageSpeed(calculateAverageSpeed(knuckleballShots));
        stats.setAverageDistance(calculateAverageDistance(knuckleballShots));
        // 按射门区域统计
        Map<String, Integer> shotsByArea = new HashMap<>();
        Map<String, Integer> goalsByArea = new HashMap<>();
        for (ShotRecord shot : knuckleballShots) {
            shotsByArea.merge(shot.getShotArea(), 1, Integer::sum);
            if (shot.isGoal()) {
                goalsByArea.merge(shot.getShotArea(), 1, Integer::sum);
            }
        }
        stats.setShotsByArea(shotsByArea);
        stats.setGoalsByArea(goalsByArea);
        return stats;
    }
    // 计算成功率
    private double calculateSuccessRate(int goals, int totalShots) {
        if (totalShots == 0) return 0;
        return (double) goals / totalShots * 100;
    }
    // 计算平均球速
    private double calculateAverageSpeed(List<ShotRecord> shots) {
        return shots.stream()
            .mapToDouble(ShotRecord::getSpeed)
            .average()
            .orElse(0);
    }
    // 计算平均射门距离
    private double calculateAverageDistance(List<ShotRecord> shots) {
        return shots.stream()
            .mapToDouble(ShotRecord::getDistance)
            .average()
            .orElse(0);
    }
    // 比较落叶球和非落叶球的成功率
    public Map<String, Double> compareSuccessRates(List<ShotRecord> shots) {
        Map<String, List<ShotRecord>> groupedByType = shots.stream()
            .collect(Collectors.groupingBy(
                shot -> shot.isKnuckleball() ? "落叶球" : "普通射门"
            ));
        Map<String, Double> successRates = new HashMap<>();
        groupedByType.forEach((type, shotList) -> {
            int goals = (int) shotList.stream().filter(ShotRecord::isGoal).count();
            double rate = calculateSuccessRate(goals, shotList.size());
            successRates.put(type, rate);
        });
        return successRates;
    }
    // 分析不同距离范围的射门成功率
    public Map<String, Double> analyzeByDistanceRange(List<ShotRecord> shots) {
        Map<String, Double> result = new LinkedHashMap<>();
        // 定义距离范围
        double[] ranges = {10, 20, 30, 40, 50};
        String[] labels = {"0-10m", "10-20m", "20-30m", "30-40m", "40m以上"};
        for (int i = 0; i < ranges.length; i++) {
            double lower = i == 0 ? 0 : ranges[i-1];
            double upper = ranges[i];
            List<ShotRecord> rangeShots = shots.stream()
                .filter(s -> s.isKnuckleball())
                .filter(s -> s.getDistance() > lower && s.getDistance() <= upper)
                .collect(Collectors.toList());
            if (!rangeShots.isEmpty()) {
                int goals = (int) rangeShots.stream().filter(ShotRecord::isGoal).count();
                result.put(labels[i], calculateSuccessRate(goals, rangeShots.size()));
            } else {
                result.put(labels[i], 0.0);
            }
        }
        return result;
    }
}

数据生成和测试类

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class KnuckleballTest {
    // 模拟生成测试数据
    private static List<ShotRecord> generateTestData(int count) {
        List<ShotRecord> shots = new ArrayList<>();
        Random random = new Random(42); // 固定种子便于复现
        String[] areas = {"禁区左侧", "禁区中央", "禁区右侧", "禁区外左侧", "禁区外中央", "禁区外右侧"};
        for (int i = 0; i < count; i++) {
            Long id = (long) i;
            LocalDateTime time = LocalDateTime.now().minusMinutes(random.nextInt(1000));
            // 射门距离:8-35米
            double distance = 8 + random.nextDouble() * 27;
            // 射门角度:0-90度
            double angle = random.nextDouble() * 90;
            // 球速:70-120 km/h
            double speed = 70 + random.nextDouble() * 50;
            // 60%概率为落叶球
            boolean isKnuckleball = random.nextDouble() < 0.6;
            // 进球概率与距离成反比
            double goalProbability = isKnuckleball ? 0.3 : 0.2;
            if (distance < 15) {
                goalProbability += 0.1;
            } else if (distance > 25) {
                goalProbability -= 0.1;
            }
            boolean isGoal = random.nextDouble() < goalProbability;
            String area = areas[random.nextInt(areas.length)];
            shots.add(new ShotRecord(id, time, distance, angle, speed, 
                                    isKnuckleball, isGoal, area));
        }
        return shots;
    }
    // 格式化输出统计结果
    private static void printStatistics(ShotStatistics stats) {
        System.out.println("=== 落叶球射门统计分析 ===");
        System.out.println("总射门次数: " + stats.getTotalShots());
        System.out.println("进球数: " + stats.getGoals());
        System.out.printf("成功率: %.2f%%\n", stats.getSuccessRate());
        System.out.printf("平均球速: %.2f km/h\n", stats.getAverageSpeed());
        System.out.printf("平均射门距离: %.2f 米\n", stats.getAverageDistance());
        System.out.println("\n射门区域统计:");
        System.out.println("区域\t\t射门次数\t进球\t成功率");
        stats.getShotsByArea().forEach((area, count) -> {
            int goals = stats.getGoalsByArea().getOrDefault(area, 0);
            double rate = count > 0 ? (double) goals / count * 100 : 0;
            System.out.printf("%s\t%d\t%d\t%.2f%%\n", 
                area, count, goals, rate);
        });
    }
    public static void main(String[] args) {
        // 生成模拟数据(例如1000次射门)
        List<ShotRecord> shots = generateTestData(1000);
        ShotAnalysisService service = new ShotAnalysisService();
        // 统计分析落叶球
        ShotStatistics knuckleballStats = service.analyzeKnuckleballShots(shots);
        printStatistics(knuckleballStats);
        // 比较落叶球和普通射门
        System.out.println("\n=== 成功率对比 ===");
        Map<String, Double> comparison = service.compareSuccessRates(shots);
        comparison.forEach((type, rate) -> 
            System.out.printf("%s成功率: %.2f%%\n", type, rate));
        // 分析距离对成功率的影响
        System.out.println("\n=== 不同距离的落叶球成功率 ===");
        Map<String, Double> distanceAnalysis = service.analyzeByDistanceRange(shots);
        distanceAnalysis.forEach((range, rate) -> 
            System.out.printf("%s: %.2f%%\n", range, rate));
        // 额外分析:球速对成功率的影响
        System.out.println("\n=== 球速分析 ===");
        analyzeBySpeed(shots);
    }
    // 分析球速对成功率的影响
    private static void analyzeBySpeed(List<ShotRecord> shots) {
        List<ShotRecord> knuckleShots = shots.stream()
            .filter(ShotRecord::isKnuckleball)
            .collect(Collectors.toList());
        // 按球速分档
        double[][] speedRanges = {{70, 80}, {80, 90}, {90, 100}, {100, 110}, {110, 120}};
        String[] labels = {"70-80km/h", "80-90km/h", "90-100km/h", "100-110km/h", "110-120km/h"};
        for (int i = 0; i < speedRanges.length; i++) {
            double low = speedRanges[i][0];
            double high = speedRanges[i][1];
            long count = knuckleShots.stream()
                .filter(s -> s.getSpeed() >= low && s.getSpeed() < high)
                .count();
            long goals = knuckleShots.stream()
                .filter(s -> s.getSpeed() >= low && s.getSpeed() < high)
                .filter(ShotRecord::isGoal)
                .count();
            double rate = count > 0 ? (double) goals / count * 100 : 0;
            System.out.printf("%s: 射门%d次, 进球%d个, 成功率%.2f%%\n", 
                labels[i], count, goals, rate);
        }
    }
}

高级功能扩展

import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;
// 时间序列分析类
class TimeSeriesAnalysis {
    // 按月统计成功率
    public Map<String, ShotStatistics> analyzeByMonth(List<ShotRecord> shots) {
        return shots.stream()
            .filter(ShotRecord::isKnuckleball)
            .collect(Collectors.groupingBy(
                shot -> shot.getShotTime().getMonth().toString(),
                Collectors.collectingAndThen(
                    Collectors.toList(),
                    this::calculateStats
                )
            ));
    }
    // 计算一组射门的统计
    private ShotStatistics calculateStats(List<ShotRecord> shots) {
        ShotStatistics stats = new ShotStatistics();
        stats.setTotalShots(shots.size());
        stats.setGoals((int) shots.stream().filter(ShotRecord::isGoal).count());
        stats.setSuccessRate((double) stats.getGoals() / stats.getTotalShots() * 100);
        return stats;
    }
    // 趋势分析
    public Map<String, Double> analyzeTrend(List<ShotRecord> shots) {
        return shots.stream()
            .filter(ShotRecord::isKnuckleball)
            .sorted(Comparator.comparing(ShotRecord::getShotTime))
            .collect(Collectors.groupingBy(
                shot -> shot.getShotTime().toLocalDate().toString(),
                LinkedHashMap::new,
                Collectors.collectingAndThen(
                    Collectors.toList(),
                    list -> {
                        int goals = (int) list.stream().filter(ShotRecord::isGoal).count();
                        return (double) goals / list.size() * 100;
                    }
                )
            ));
    }
}
// 报告生成类
class ReportGenerator {
    // 生成详细报告
    public String generateReport(ShotStatistics stats, Map<String, Double> comparison) {
        StringBuilder report = new StringBuilder();
        report.append("════════════════════════════════════════\n");
        report.append("       落叶球射门成功率分析报告\n");
        report.append("════════════════════════════════════════\n\n");
        report.append("【总体统计】\n");
        report.append(String.format("总射门次数:%d\n", stats.getTotalShots()));
        report.append(String.format("进球次数:%d\n", stats.getGoals()));
        report.append(String.format("成功率:%.2f%%\n", stats.getSuccessRate()));
        report.append(String.format("平均球速:%.2f km/h\n", stats.getAverageSpeed()));
        report.append(String.format("平均射门距离:%.2f m\n\n", stats.getAverageDistance()));
        report.append("【区域分析】\n");
        report.append("区域\t\t射门数\t进球数\t成功率\n");
        stats.getShotsByArea().forEach((area, count) -> {
            int goals = stats.getGoalsByArea().getOrDefault(area, 0);
            double rate = count > 0 ? (double) goals / count * 100 : 0;
            report.append(String.format("%s\t%d\t%d\t%.2f%%\n", 
                area, count, goals, rate));
        });
        report.append("\n【成功率对比】\n");
        comparison.forEach((type, rate) -> 
            report.append(String.format("%s:%.2f%%\n", type, rate)));
        report.append("\n════════════════════════════════════════\n");
        return report.toString();
    }
}

使用示例

public class Main {
    public static void main(String[] args) {
        // 创建服务
        ShotAnalysisService service = new ShotAnalysisService();
        ReportGenerator reportGen = new ReportGenerator();
        // 生成数据
        List<ShotRecord> shots = generateTestData(2000);
        // 分析
        ShotStatistics stats = service.analyzeKnuckleballShots(shots);
        Map<String, Double> comparison = service.compareSuccessRates(shots);
        // 生成并输出报告
        String report = reportGen.generateReport(stats, comparison);
        System.out.println(report);
    }
}

主要功能说明

  1. 基础统计分析:计算总射门数、进球数、成功率
  2. 多维分析:按区域、距离、球速等维度分析
  3. 对比分析:落叶球与普通射门成功率对比
  4. 趋势分析:按时间维度分析成功率变化
  5. 报告生成:自动生成统计报告

使用建议

  1. 数据采集:通过视频分析或传感器采集真实射门数据
  2. 参数调整:根据实际需求调整距离范围、球速区间
  3. 机器学习:可在此基础上构建预测模型,预测射门成功率

这个案例提供了完整的统计分析框架,可以根据实际需求进行扩展和定制。

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