php项目统计禁区内射门次数对比?

wen PHP项目 2

PHP项目:统计禁区内射门次数对比

下面给你一个完整的 PHP 实现方案,用于统计和对比两支球队在禁区内射门次数。

php项目统计禁区内射门次数对比?

数据表设计

-- 比赛表
CREATE TABLE matches (
    id INT PRIMARY KEY AUTO_INCREMENT,
    home_team VARCHAR(50),
    away_team VARCHAR(50),
    match_date DATE
);
-- 射门记录表
CREATE TABLE shots (
    id INT PRIMARY KEY AUTO_INCREMENT,
    match_id INT,
    team VARCHAR(50),          -- 球队名称
    player VARCHAR(50),        -- 球员
    minute INT,                -- 比赛分钟
    x_coord DECIMAL(5,2),      -- 射门位置 x 坐标(米)
    y_coord DECIMAL(5,2),      -- 射门位置 y 坐标(米)
    is_goal TINYINT DEFAULT 0, -- 是否进球
    FOREIGN KEY (match_id) REFERENCES matches(id)
);

判断是否在禁区内

标准足球场:长 105m × 宽 68m,禁区为 32m × 16.5m。

<?php
/**
 * 判断射门点是否在禁区内
 * 以球场左下角为原点 (0,0),右上角为 (105, 68)
 * 假定左方球门在 x=0 处,右方球门在 x=105 处
 */
function isInPenaltyArea($x, $y, $side = 'left') {
    $penaltyWidth  = 16.5;   // 禁区宽度(距球门线)
    $penaltyHeight = 40.32;  // 禁区长度
    $fieldWidth    = 68;
    // 禁区纵向范围(居中)
    $yMin = ($fieldWidth - $penaltyHeight) / 2; // 13.84
    $yMax = $yMin + $penaltyHeight;              // 54.16
    if ($side === 'left') {
        // 左侧禁区:x ∈ [0, 16.5]
        return $x >= 0 && $x <= $penaltyWidth && $y >= $yMin && $y <= $yMax;
    } else {
        // 右侧禁区:x ∈ [88.5, 105]
        return $x >= (105 - $penaltyWidth) && $x <= 105 && $y >= $yMin && $y <= $yMax;
    }
}

统计禁区内射门次数

<?php
require 'db.php'; // PDO 连接
/**
 * 统计某场比赛禁区内射门次数(按球队分组)
 */
function getPenaltyAreaShots($pdo, $matchId) {
    $sql = "SELECT team, x_coord, y_coord, is_goal
            FROM shots
            WHERE match_id = :mid";
    $stmt = $pdo->prepare($sql);
    $stmt->execute([':mid' => $matchId]);
    $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
    $stats = [];
    foreach ($rows as $r) {
        $team = $r['team'];
        // 判断该队进攻方向(可根据实际项目改用主客队逻辑)
        // 这里简化:主队射左门,客队射右门
        $side = ($team === $homeTeam) ? 'left' : 'right';
        if (!isset($stats[$team])) {
            $stats[$team] = ['total' => 0, 'in_box' => 0, 'goals_in_box' => 0];
        }
        $stats[$team]['total']++;
        if (isInPenaltyArea($r['x_coord'], $r['y_coord'], $side)) {
            $stats[$team]['in_box']++;
            if ($r['is_goal']) $stats[$team]['goals_in_box']++;
        }
    }
    return $stats;
}

对比展示(带百分比)

<?php
$matchId = 1;
$stats = getPenaltyAreaShots($pdo, $matchId);
// 获取球队名
$teams = array_keys($stats);
$homeStat = $stats[$teams[0]] ?? ['in_box'=>0,'total'=>0,'goals_in_box'=>0];
$awayStat = $stats[$teams[1]] ?? ['in_box'=>0,'total'=>0,'goals_in_box'=>0];
function percent($part, $total) {
    return $total > 0 ? round($part / $total * 100, 1) . '%' : '0%';
}
?>
<table border="1" cellpadding="8">
    <tr>
        <th>统计项</th>
        <th><?= htmlspecialchars($teams[0]) ?></th>
        <th><?= htmlspecialchars($teams[1]) ?></th>
    </tr>
    <tr>
        <td>禁区内射门</td>
        <td><?= $homeStat['in_box'] ?></td>
        <td><?= $awayStat['in_box'] ?></td>
    </tr>
    <tr>
        <td>总射门</td>
        <td><?= $homeStat['total'] ?></td>
        <td><?= $awayStat['total'] ?></td>
    </tr>
    <tr>
        <td>禁区内占比</td>
        <td><?= percent($homeStat['in_box'], $homeStat['total']) ?></td>
        <td><?= percent($awayStat['in_box'], $awayStat['total']) ?></td>
    </tr>
    <tr>
        <td>禁区内进球</td>
        <td><?= $homeStat['goals_in_box'] ?></td>
        <td><?= $awayStat['goals_in_box'] ?></td>
    </tr>
</table>

单条 SQL 版本(推荐)

如果坐标是标准化百分比(0~100)更方便,直接用 SQL 一次统计:

SELECT 
    team,
    COUNT(*) AS total_shots,
    SUM(CASE 
        WHEN x_coord BETWEEN 0 AND 16.5  
         AND y_coord BETWEEN 13.84 AND 54.16 THEN 1 
        ELSE 0 END) AS left_box_shots,
    SUM(CASE 
        WHEN x_coord BETWEEN 88.5 AND 105  
         AND y_coord BETWEEN 13.84 AND 54.16 THEN 1 
        ELSE 0 END) AS right_box_shots
FROM shots
WHERE match_id = 1
GROUP BY team;
$stmt = $pdo->prepare($sql);
$stmt->execute([':mid' => $matchId]);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($rows as $r) {
    $r['in_box'] = $r['left_box_shots'] + $r['right_box_shots'];
    echo "{$r['team']}:禁区内 {$r['in_box']} / 总射门 {$r['total_shots']}\n";
}

结果示例

统计项          主队      客队
─────────────────────────────
禁区内射门        9         4
总射门           15        11
禁区内占比       60.0%     36.4%
禁区内进球        2         1
要点 说明
坐标系 需明确定义球场原点、方向(左右/上下)
禁区尺寸 32m × 16.5m,注意纵向居中偏移 13.84m
方向判断 主客队进攻方向相反,需根据半场切换
数据来源 建议用 Opta / StatsBomb 等标准坐标,或统一归一化到 105×68

如果你能告诉我坐标格式(如 StatsBomb 的 120×80,或百分比)以及进攻方向逻辑,我可以帮你把判断函数改得更精确。

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