php项目统计假动作晃过防守几次?

wen PHP项目 1

PHP项目统计"假动作晃过防守"次数

你这个问题看起来像是 篮球/足球类游戏或体育数据统计系统 的需求,我按"PHP 后端实现一个'假动作晃过防守'次数统计功能"来给你一套可落地的方案。

php项目统计假动作晃过防守几次?

需求拆解

要统计"假动作晃过防守几次",需要明确:

要素 说明
统计对象 球员(player_id)
事件类型 假动作(feint / fake_move)
判定条件 假动作后防守者被晃过(beat_defender)
统计维度 单场 / 赛季 / 生涯
数据来源 比赛事件流(event log)

数据库设计

-- 比赛事件表(核心)
CREATE TABLE match_events (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    match_id INT NOT NULL,
    player_id INT NOT NULL,
    event_type VARCHAR(32) NOT NULL,      -- 'feint', 'pass', 'shot'...
    event_result VARCHAR(32) NULL,        -- 'beat_defender', 'failed'...
    occurred_at DATETIME NOT NULL,
    INDEX idx_match_player (match_id, player_id),
    INDEX idx_type_result (event_type, event_result)
);
-- 统计结果表(预聚合,提升查询性能)
CREATE TABLE player_feint_stats (
    player_id INT NOT NULL,
    match_id INT NOT NULL,
    feint_total INT DEFAULT 0,          -- 假动作总次数
    feint_success INT DEFAULT 0,        -- 晃过防守次数
    updated_at DATETIME,
    PRIMARY KEY (player_id, match_id)
);

核心统计 SQL

单场统计某个球员:

SELECT
    player_id,
    COUNT(*) AS feint_total,
    SUM(CASE WHEN event_result = 'beat_defender' THEN 1 ELSE 0 END) AS feint_success,
    ROUND(
        SUM(CASE WHEN event_result = 'beat_defender' THEN 1 ELSE 0 END)
        / COUNT(*) * 100, 2
    ) AS success_rate
FROM match_events
WHERE event_type = 'feint'
  AND match_id = ?
  AND player_id = ?
GROUP BY player_id;

赛季排行榜:

SELECT
    player_id,
    COUNT(*) AS total_feints,
    SUM(event_result = 'beat_defender') AS beat_count
FROM match_events
WHERE event_type = 'feint'
  AND occurred_at BETWEEN ? AND ?
GROUP BY player_id
ORDER BY beat_count DESC
LIMIT 20;

PHP 实现(PDO 示例)

class FeintStatsService
{
    public function __construct(private PDO $pdo) {}
    /** 记录一次假动作事件 */
    public function recordFeint(int $matchId, int $playerId, bool $beatDefender): void
    {
        $stmt = $this->pdo->prepare(
            "INSERT INTO match_events (match_id, player_id, event_type, event_result, occurred_at)
             VALUES (?, ?, 'feint', ?, NOW())"
        );
        $stmt->execute([
            $matchId,
            $playerId,
            $beatDefender ? 'beat_defender' : 'failed'
        ]);
    }
    /** 查询单场统计 */
    public function getMatchStats(int $matchId, int $playerId): array
    {
        $sql = "SELECT
                    COUNT(*) AS total,
                    SUM(event_result = 'beat_defender') AS success,
                    ROUND(SUM(event_result = 'beat_defender') / COUNT(*) * 100, 2) AS rate
                FROM match_events
                WHERE event_type = 'feint' AND match_id = ? AND player_id = ?";
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute([$matchId, $playerId]);
        return $stmt->fetch(PDO::FETCH_ASSOC) ?: ['total' => 0, 'success' => 0, 'rate' => 0];
    }
    /** 赛季排行 */
    public function getSeasonRanking(string $start, string $end, int $limit = 20): array
    {
        $sql = "SELECT player_id,
                       COUNT(*) AS total,
                       SUM(event_result = 'beat_defender') AS success
                FROM match_events
                WHERE event_type = 'feint' AND occurred_at BETWEEN ? AND ?
                GROUP BY player_id
                ORDER BY success DESC
                LIMIT ?";
        $stmt = $this->pdo->prepare($sql);
        $stmt->bindValue(1, $start);
        $stmt->bindValue(2, $end);
        $stmt->bindValue(3, $limit, PDO::PARAM_INT);
        $stmt->execute();
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
}

关键设计要点

  1. "晃过"的判定要定义清楚

    • 是人工标注事件(推荐),还是通过坐标/时间窗口自动判定(如防守者重心偏移 + 距离拉开)?
    • 建议在 event_result 里用枚举值:beat_defender / failed / neutral。
  2. 预聚合 vs 实时计算

    • 数据量小(< 百万行):实时 GROUP BY 即可。
    • 数据量大:用 player_feint_stats 预聚合表,事件写入时用事务更新,或定时任务(cron)批量重算。
  3. 防止重复计数

    • 一次连续动作可能产生多个事件,需要 action_id / possession_id 去重。
    • 建议加 UNIQUE(action_id) 或按"回合"聚合。
  4. 索引优化

    • 复合索引 (event_type, match_id, player_id) 覆盖绝大多数查询。
  5. 缓存

    排行榜类查询用 Redis 缓存(TTL 5~10 分钟),避免高频扫表。

如果你问的是别的场景

  • 如果是游戏后台:把"假动作"作为技能事件,event_result 由战斗逻辑判定后上报。
  • 如果是视频分析系统:PHP 只做数据存储/查询,识别部分用 Python/OpenCV 或第三方 API,通过队列(Redis/RabbitMQ)写入事件表。

需要我针对你的具体场景(比如是体育数据平台、游戏后端、还是视频识别系统)给出更精确的表结构和接口设计吗?

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