php项目统计脚后跟传球成功几次?

wen PHP项目 2

PHP项目统计"脚后跟传球"成功次数

这是一个比较具体的足球数据分析需求,下面给你一个完整的实现思路和代码示例。

php项目统计脚后跟传球成功几次?

需求分析

要统计"脚后跟传球成功次数",需要明确几个概念:

  1. 脚后跟传球:传球时使用脚后跟部位(backheel pass)
  2. 成功:传球后球权仍在己方队员脚下
  3. 数据来源:需要有传球事件的基础数据

数据表设计

-- 比赛事件表
CREATE TABLE match_events (
    id INT PRIMARY KEY AUTO_INCREMENT,
    match_id INT NOT NULL,
    player_id INT NOT NULL,
    team_id INT NOT NULL,
    event_type VARCHAR(50) NOT NULL,      -- 'pass', 'shot', 'tackle' 等
    pass_technique VARCHAR(50) NULL,      -- 'normal', 'backheel', 'lob', 'through'
    target_player_id INT NULL,            -- 接球球员
    is_success TINYINT(1) DEFAULT 0,      -- 是否成功
    minute INT,
    second INT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_match (match_id),
    INDEX idx_player (player_id),
    INDEX idx_technique (pass_technique)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

核心统计代码

基础统计(按球员)

<?php
class PassStatistics
{
    private PDO $pdo;
    public function __construct(PDO $pdo)
    {
        $this->pdo = $pdo;
    }
    /**
     * 统计某球员在某场比赛的脚后跟传球成功次数
     */
    public function countBackheelPassesByPlayer(int $playerId, int $matchId): array
    {
        $sql = "SELECT 
                    COUNT(*) AS total_attempts,
                    SUM(CASE WHEN is_success = 1 THEN 1 ELSE 0 END) AS success_count,
                    ROUND(
                        SUM(CASE WHEN is_success = 1 THEN 1 ELSE 0 END) / COUNT(*) * 100
                    , 2) AS success_rate
                FROM match_events
                WHERE player_id = :player_id
                  AND match_id = :match_id
                  AND event_type = 'pass'
                  AND pass_technique = 'backheel'";
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute([
            ':player_id' => $playerId,
            ':match_id'  => $matchId,
        ]);
        return $stmt->fetch(PDO::FETCH_ASSOC) ?: [
            'total_attempts' => 0,
            'success_count'  => 0,
            'success_rate'   => 0,
        ];
    }
    /**
     * 统计整场比赛所有球员的脚后跟传球排行
     */
    public function topBackheelPassers(int $matchId, int $limit = 10): array
    {
        $sql = "SELECT 
                    e.player_id,
                    p.name AS player_name,
                    t.name AS team_name,
                    COUNT(*) AS attempts,
                    SUM(CASE WHEN e.is_success = 1 THEN 1 ELSE 0 END) AS successes
                FROM match_events e
                JOIN players p ON p.id = e.player_id
                JOIN teams t ON t.id = e.team_id
                WHERE e.match_id = :match_id
                  AND e.event_type = 'pass'
                  AND e.pass_technique = 'backheel'
                GROUP BY e.player_id, p.name, t.name
                ORDER BY successes DESC, attempts DESC
                LIMIT :limit";
        $stmt = $this->pdo->prepare($sql);
        $stmt->bindValue(':match_id', $matchId, PDO::PARAM_INT);
        $stmt->bindValue(':limit', $limit, PDO::PARAM_INT);
        $stmt->execute();
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
}

调用示例

$pdo = new PDO('mysql:host=localhost;dbname=football;charset=utf8mb4', 'user', 'pass', [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);
$stat = new PassStatistics($pdo);
// 查询梅西在某场比赛的脚后跟传球
$result = $stat->countBackheelPassesByPlayer(playerId: 10, matchId: 1001);
echo "脚后跟传球尝试:{$result['total_attempts']} 次\n";
echo "成功次数:{$result['success_count']} 次\n";
echo "成功率:{$result['success_rate']}%\n";
// 比赛脚后跟传球排行
$ranks = $stat->topBackheelPassers(1001, 5);
foreach ($ranks as $r) {
    printf("%-15s (%s): %d/%d\n", $r['player_name'], $r['team_name'], $r['successes'], $r['attempts']);
}

关键设计要点

数据采集阶段

  • 人工标注:Scout 或 Opta 类数据提供商手动/半自动记录
  • AI 识别:通过视频分析模型识别脚后跟触球动作(较难,需要视觉模型)
  • 重点:pass_technique 字段必须准确标注为 backheel

"成功"的定义

// 定义清晰的成功标准
$isSuccess = (
    $event['target_player_id'] === $event['teammate_id'] &&  // 队友接到
    $event['next_event_team'] === $event['team_id']           // 下一次触球是己方
);

常见扩展统计

/**
 * 按位置/赛季/赛事维度统计
 */
public function countByDimension(array $filters)
{
    $sql = "SELECT 
                COUNT(*) AS total,
                SUM(is_success) AS success
            FROM match_events e
            JOIN matches m ON m.id = e.match_id
            WHERE e.pass_technique = 'backheel'
              AND e.event_type = 'pass'";
    $params = [];
    if (!empty($filters['season_id'])) {
        $sql .= " AND m.season_id = :season_id";
        $params[':season_id'] = $filters['season_id'];
    }
    if (!empty($filters['competition_id'])) {
        $sql .= " AND m.competition_id = :competition_id";
        $params[':competition_id'] = $filters['competition_id'];
    }
    $stmt = $this->pdo->prepare($sql);
    $stmt->execute($params);
    return $stmt->fetch(PDO::FETCH_ASSOC);
}

实战建议

环节 建议
数据源 如果没有专业数据,可用 StatsBomb Open Data(含 pass_technique 字段)
字段命名 用 technique 而不是 body_part(脚后跟本质是技术动作)
性能优化 对 (match_id, event_type, pass_technique) 建复合索引
缓存 赛季级汇总数据用 Redis 缓存
幂等 事件 ID 唯一,避免重复导入导致统计翻倍

StatsBomb 数据示例

如果你使用 StatsBomb 开放数据,JSON 结构大致是:

{
  "type": {"name": "Pass"},
  "pass": {
    "technique": {"name": "Backheel"},
    "outcome": null,
    "recipient": {"id": 5503, "name": "Jordi Alba"}
  }
}

解析入库时:

$technique = $event['pass']['technique']['name'] ?? 'Normal';
$isSuccess = !isset($event['pass']['outcome']); // 无 outcome 表示成功
// 入库时 pass_technique 统一转小写存储
$passTechnique = strtolower($technique); // 'backheel'

如果你的具体场景是 StatsBomb 数据导入 + 统计、自建视频标注系统,或者是 已有数据库要加统计接口,可以告诉我,我给你更针对性的代码。

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