php项目统计斜长传精准度如何?

wen PHP项目 1

本文目录导读:

php项目统计斜长传精准度如何?

  1. 数据库表设计
  2. 核心统计类
  3. 使用示例
  4. 前端展示(可选)
  5. 核心功能亮点:

我来帮你设计一个PHP项目统计斜长传精准度的方案,这里提供完整的数据结构和实现代码:

数据库表设计

-- 球员表
CREATE TABLE players (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50) NOT NULL,
    team_id INT,
    position VARCHAR(20)
);
-- 传球记录表
CREATE TABLE passes (
    id INT PRIMARY KEY AUTO_INCREMENT,
    player_id INT NOT NULL,
    match_id INT NOT NULL,
    pass_type ENUM('long_ball', 'through_ball', 'cross') DEFAULT 'long_ball',
    start_x DECIMAL(5,2),  -- 传球起始X坐标
    start_y DECIMAL(5,2),  -- 传球起始Y坐标
    end_x DECIMAL(5,2),    -- 传球落点X坐标
    end_y DECIMAL(5,2),    -- 传球落点Y坐标
    target_x DECIMAL(5,2), -- 预期目标X坐标
    target_y DECIMAL(5,2), -- 预期目标Y坐标
    is_success TINYINT(1) DEFAULT 0,  -- 是否成功
    pass_distance DECIMAL(5,2),       -- 传球距离
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_player_date (player_id, created_at)
);
-- 比赛信息表
CREATE TABLE matches (
    id INT PRIMARY KEY AUTO_INCREMENT,
    home_team VARCHAR(50),
    away_team VARCHAR(50),
    match_date DATE,
    competition VARCHAR(50)
);

核心统计类

<?php
class LongPassAnalyzer {
    private $pdo;
    private $playerId;
    public function __construct(PDO $pdo, $playerId) {
        $this->pdo = $pdo;
        $this->playerId = $playerId;
    }
    /**
     * 计算单次传球精准度
     */
    public function calculatePassAccuracy($pass) {
        // 目标位置与实际落点距离
        $targetDistance = $this->calculateDistance(
            $pass['target_x'], 
            $pass['target_y'], 
            $pass['end_x'], 
            $pass['end_y']
        );
        // 根据距离计算精准度 (0-100)
        $accuracy = max(0, 100 - $targetDistance * 2);
        return $accuracy;
    }
    /**
     * 获取球员所有传球统计
     */
    public function getPlayerStatistics($dateFrom = null, $dateTo = null) {
        $sql = "SELECT 
                    p.id,
                    p.pass_type,
                    p.is_success,
                    p.pass_distance,
                    p.start_x, p.start_y,
                    p.end_x, p.end_y,
                    p.target_x, p.target_y,
                    m.match_date,
                    m.competition
                FROM passes p
                INNER JOIN matches m ON p.match_id = m.id
                WHERE p.player_id = :playerId";
        if ($dateFrom && $dateTo) {
            $sql .= " AND m.match_date BETWEEN :dateFrom AND :dateTo";
            $params = [
                ':playerId' => $this->playerId,
                ':dateFrom' => $dateFrom,
                ':dateTo' => $dateTo
            ];
        } else {
            $params = [':playerId' => $this->playerId];
        }
        $sql .= " ORDER BY m.match_date DESC";
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute($params);
        $passes = $stmt->fetchAll(PDO::FETCH_ASSOC);
        $statistics = [
            'total_passes' => count($passes),
            'success_passes' => 0,
            'avg_accuracy' => 0,
            'distance_breakdown' => [],
            'type_breakdown' => [],
            'recent_trend' => []
        ];
        foreach ($passes as $pass) {
            // 统计成功率
            if ($pass['is_success']) {
                $statistics['success_passes']++;
            }
            // 计算精准度
            $accuracy = $this->calculatePassAccuracy($pass);
            $statistics['avg_accuracy'] += $accuracy;
            // 按距离分组统计
            $distanceCategory = $this->categorizeDistance($pass['pass_distance']);
            if (!isset($statistics['distance_breakdown'][$distanceCategory])) {
                $statistics['distance_breakdown'][$distanceCategory] = [
                    'count' => 0,
                    'accuracy_sum' => 0
                ];
            }
            $statistics['distance_breakdown'][$distanceCategory]['count']++;
            $statistics['distance_breakdown'][$distanceCategory]['accuracy_sum'] += $accuracy;
            // 按传球类型统计
            // ... 类似距离统计
        }
        // 计算平均精准度
        if ($statistics['total_passes'] > 0) {
            $statistics['avg_accuracy'] = round(
                $statistics['avg_accuracy'] / $statistics['total_passes'], 2
            );
        }
        // 计算成功率
        $statistics['success_rate'] = $statistics['total_passes'] > 0 
            ? round(($statistics['success_passes'] / $statistics['total_passes']) * 100, 1)
            : 0;
        // 近10场比赛趋势
        $statistics['recent_trend'] = $this->getRecentTrend($passes);
        return $statistics;
    }
    /**
     * 计算两点距离
     */
    private function calculateDistance($x1, $y1, $x2, $y2) {
        return sqrt(pow($x2 - $x1, 2) + pow($y2 - $y1, 2));
    }
    /**
     * 距离分类
     */
    private function categorizeDistance($distance) {
        if ($distance < 30) return 'short';
        if ($distance < 45) return 'medium';
        if ($distance < 60) return 'long';
        return 'very_long';
    }
    /**
     * 获取近期趋势
     */
    private function getRecentTrend($passes) {
        $trend = [];
        $summary = array_slice($passes, 0, 10); // 最近10场
        foreach ($summary as $pass) {
            $date = $pass['match_date'];
            if (!isset($trend[$date])) {
                $trend[$date] = [
                    'total' => 0,
                    'accuracy' => 0
                ];
            }
            $trend[$date]['total']++;
            $trend[$date]['accuracy'] += $this->calculatePassAccuracy($pass);
        }
        // 计算每日平均
        foreach ($trend as &$day) {
            $day['avg_accuracy'] = $day['total'] > 0 
                ? round($day['accuracy'] / $day['total'], 1) 
                : 0;
            unset($day['accuracy']);
        }
        return $trend;
    }
    /**
     * 多维度分析报告
     */
    public function generateReport() {
        $statistics = $this->getPlayerStatistics();
        return [
            'summary' => [
                'total_pass_attempts' => $statistics['total_passes'],
                'success_rate' => $statistics['success_rate'],
                'avg_accuracy' => $statistics['avg_accuracy']
            ],
            'performance_by_distance' => $this->formatDistanceBreakdown($statistics['distance_breakdown']),
            'strengths' => $this->identifyStrengths($statistics),
            'areas_for_improvement' => $this->identifyWeaknesses($statistics),
            'recommendations' => $this->generateRecommendations($statistics)
        ];
    }
    /**
     * 格式化距离统计
     */
    private function formatDistanceBreakdown($distanceStats) {
        $formatted = [];
        foreach ($distanceStats as $category => $data) {
            $formatted[$category] = [
                'attempts' => $data['count'],
                'avg_accuracy' => $data['count'] > 0 
                    ? round($data['accuracy_sum'] / $data['count'], 1)
                    : 0
            ];
        }
        return $formatted;
    }
    /**
     * 球员对标分析(与队内平均比较)
     */
    public function compareToTeamAverage($teamId, $dateFrom = null, $dateTo = null) {
        $playerStats = $this->getPlayerStatistics($dateFrom, $dateTo);
        // 获取队伍平均数据
        $sql = "SELECT AVG(is_success) * 100 as success_rate
                FROM passes p
                INNER JOIN players pl ON p.player_id = pl.id
                WHERE pl.team_id = :teamId";
        if ($dateFrom && $dateTo) {
            $sql .= " AND p.created_at BETWEEN :dateFrom AND :dateTo";
        }
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute(['teamId' => $teamId]);
        $teamSuccessRate = $stmt->fetchColumn();
        return [
            'player' => $playerStats,
            'team_avg' => [
                'success_rate' => round($teamSuccessRate, 1)
            ],
            'comparison' => [
                'success_rate_diff' => round($playerStats['success_rate'] - $teamSuccessRate, 1)
            ]
        ];
    }
}

使用示例

<?php
// 初始化
$pdo = new PDO('mysql:host=localhost;dbname=football', 'user', 'pass');
$analyzer = new LongPassAnalyzer($pdo, 12345);
// 获取球员统计
$stats = $analyzer->getPlayerStatistics('2024-01-01', '2024-06-30');
// 生成完整报告
$report = $analyzer->generateReport();
// 与队伍对比
$teamComparison = $analyzer->compareToTeamAverage(678);
// 输出结果
echo json_encode($stats, JSON_PRETTY_PRINT);

前端展示(可选)

<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<div class="pass-accuracy-chart">
    <canvas id="accuracyChart"></canvas>
</div>
<script>
const ctx = document.getElementById('accuracyChart').getContext('2d');
new Chart(ctx, {
    type: 'line',
    data: {
        labels: Object.keys(trendData),
        datasets: [{
            label: '精准度趋势',
            data: Object.values(trendData).map(d => d.avg_accuracy),
            borderColor: 'rgba(75, 192, 192, 1)',
            fill: false
        }]
    }
});
</script>

核心功能亮点:

  1. 多维度统计:按距离、类型、比赛日期分类
  2. 精准度算法:基于传球落点与目标位置的偏差计算
  3. 趋势分析:展示近10场表现变化
  4. 对比分析:与队内平均比较
  5. 个性化报告:自动识别优势和待改进方面

建议根据实际需求调整传球精准度计算的权重和阈值参数。

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