php项目统计界外球进攻威胁次数?

wen PHP项目 3

本文目录导读:

php项目统计界外球进攻威胁次数?

  1. 数据库设计
  2. 核心PHP类设计
  3. 使用示例
  4. 前端展示建议

我来帮你设计一个PHP项目统计界外球进攻威胁次数的方案。

数据库设计

-- 界外球事件表
CREATE TABLE throw_in_events (
    id INT PRIMARY KEY AUTO_INCREMENT,
    match_id INT NOT NULL,
    team_id INT NOT NULL,
    player_id INT,
    period INT COMMENT '上半场/下半场',
    minute INT COMMENT '发生时间',
    field_area VARCHAR(50) COMMENT '球场区域',
    threat_level TINYINT COMMENT '威胁等级1-5',
    is_threat BOOLEAN DEFAULT FALSE,
    threat_type VARCHAR(50) COMMENT '威胁类型',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_match (match_id),
    INDEX idx_team (team_id)
);
-- 球队表(示例)
CREATE TABLE teams (
    id INT PRIMARY KEY AUTO_INCREMENT,
    team_name VARCHAR(100) NOT NULL,
    country VARCHAR(50)
);
-- 球员表(示例)
CREATE TABLE players (
    id INT PRIMARY KEY AUTO_INCREMENT,
    team_id INT,
    player_name VARCHAR(100),
    position VARCHAR(50)
);

核心PHP类设计

<?php
class ThrowInThreatAnalyzer {
    private $db;
    public function __construct($pdo) {
        $this->db = $pdo;
    }
    /**
     * 记录界外球事件
     */
    public function recordThrowIn($matchId, $teamId, $playerId, $data) {
        $sql = "INSERT INTO throw_in_events 
                (match_id, team_id, player_id, period, minute, field_area, 
                 threat_level, is_threat, threat_type) 
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
        $stmt = $this->db->prepare($sql);
        return $stmt->execute([
            $matchId, 
            $teamId, 
            $playerId,
            $data['period'],
            $data['minute'],
            $data['field_area'],
            $data['threat_level'],
            $data['threat_level'] >= 3, // 3级以上算威胁
            $this->determineThreatType($data['field_area'], $data['threat_level'])
        ]);
    }
    /**
     * 判断威胁类型
     */
    private function determineThreatType($fieldArea, $threatLevel) {
        $threatAreas = ['禁区左侧', '禁区右侧', '禁区前沿'];
        if (in_array($fieldArea, $threatAreas) && $threatLevel >= 4) {
            return 'high_danger';
        } elseif (in_array($fieldArea, $threatAreas)) {
            return 'dangerous';
        } elseif ($threatLevel >= 3) {
            return 'potential';
        }
        return 'none';
    }
    /**
     * 统计某场比赛的威胁次数
     */
    public function getMatchThreatStats($matchId, $teamId = null) {
        $sql = "SELECT 
                    COUNT(*) as total_throws,
                    SUM(CASE WHEN is_threat = 1 THEN 1 ELSE 0 END) as threat_count,
                    SUM(CASE WHEN threat_type = 'high_danger' THEN 1 ELSE 0 END) as high_threats,
                    SUM(CASE WHEN threat_type = 'dangerous' THEN 1 ELSE 0 END) as medium_threats,
                    AVG(threat_level) as avg_threat_level,
                    GROUP_CONCAT(threat_type) as threat_types
                FROM throw_in_events 
                WHERE match_id = ?";
        $params = [$matchId];
        if ($teamId) {
            $sql .= " AND team_id = ?";
            $params[] = $teamId;
        }
        $stmt = $this->db->prepare($sql);
        $stmt->execute($params);
        return $stmt->fetch(PDO::FETCH_ASSOC);
    }
    /**
     * 按区域统计威胁分布
     */
    public function getThreatByArea($matchId) {
        $sql = "SELECT 
                    field_area,
                    COUNT(*) as total,
                    SUM(CASE WHEN is_threat = 1 THEN 1 ELSE 0 END) as threats,
                    SUM(CASE WHEN threat_level >= 4 THEN 1 ELSE 0 END) as critical
                FROM throw_in_events
                WHERE match_id = ?
                GROUP BY field_area
                ORDER BY threats DESC";
        $stmt = $this->db->prepare($sql);
        $stmt->execute([$matchId]);
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
    /**
     * 获取给定时间段的威胁趋势
     */
    public function getThreatTrend($matchId, $intervalMinutes = 15) {
        $sql = "SELECT 
                    CASE 
                        WHEN minute BETWEEN 0 AND ? THEN '0-15'
                        WHEN minute BETWEEN ? AND ? THEN '15-30'
                        WHEN minute BETWEEN ? AND ? THEN '30-45'
                        WHEN minute BETWEEN ? AND ? THEN '45-60'
                        WHEN minute BETWEEN ? AND ? THEN '60-75'
                        ELSE '75-90'
                    END as time_range,
                    COUNT(*) as throws,
                    SUM(CASE WHEN is_threat = 1 THEN 1 ELSE 0 END) as threats
                FROM throw_in_events
                WHERE match_id = ?
                GROUP BY time_range
                ORDER BY MIN(minute)";
        $stmt = $this->db->prepare($sql);
        $stmt->execute([15, 15, 30, 30, 45, 45, 60, 60, 75, $matchId]);
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
    /**
     * 计算威胁转化率
     */
    public function getThreatConversionRate($matchId, $teamId = null) {
        $stats = $this->getMatchThreatStats($matchId, $teamId);
        if ($stats['total_throws'] == 0) {
            return 0;
        }
        return round(($stats['threat_count'] / $stats['total_throws']) * 100, 2);
    }
    /**
     * 球员威胁贡献度分析
     */
    public function getPlayerThreatAnalysis($matchId) {
        $sql = "SELECT 
                    p.player_name,
                    COUNT(t.id) as total_throws,
                    SUM(CASE WHEN t.is_threat = 1 THEN 1 ELSE 0 END) as threats,
                    AVG(t.threat_level) as avg_threat,
                    MAX(t.threat_level) as max_threat
                FROM throw_in_events t
                JOIN players p ON t.player_id = p.id
                WHERE t.match_id = ? AND t.is_threat = 1
                GROUP BY t.player_id, p.player_name
                ORDER BY threats DESC
                LIMIT 10";
        $stmt = $this->db->prepare($sql);
        $stmt->execute([$matchId]);
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
    /**
     * 实时威胁检测(简化版)
     */
    public function calculateRealTimeThreat($data) {
        $score = 0;
        // 距离球门越近,威胁越大
        $distanceScores = [
            '本方半场' => 1,
            '中场' => 2,
            '前场' => 3,
            '禁区前沿' => 4,
            '禁区内' => 5,
            '禁区两侧' => 4
        ];
        $score += $distanceScores[$data['field_area']] ?? 2;
        // 配合位置加分
        if (isset($data['in_attack_phase'])) {
            $score += 1;
        }
        // 人数优势加分
        if (isset($data['numbers_advantage']) && $data['numbers_advantage']) {
            $score += 1;
        }
        // 时间因素(比赛末段威胁更大)
        if (isset($data['minute']) && $data['minute'] > 80) {
            $score += 0.5;
        }
        return min(5, round($score));
    }
}

使用示例

<?php
// 初始化
$pdo = new PDO('mysql:host=localhost;dbname=football', 'user', 'password');
$analyzer = new ThrowInThreatAnalyzer($pdo);
// 1. 记录一次界外球
$analyzer->recordThrowIn(1, 1, 10, [
    'period' => 1,
    'minute' => 25,
    'field_area' => '禁区右侧',
    'threat_level' => 4
]);
// 2. 统计全场威胁
$stats = $analyzer->getMatchThreatStats(1);
print_r($stats);
// 3. 查看特定球队
$teamStats = $analyzer->getMatchThreatStats(1, 1);
echo "威胁次数: " . $teamStats['threat_count'];
// 4. 威胁转化率
$rate = $analyzer->getThreatConversionRate(1, 1);
echo "转化率: " . $rate . "%";
// 5. 区域分布
$areas = $analyzer->getThreatByArea(1);
foreach ($areas as $area) {
    echo "{$area['field_area']}: {$area['threats']}次威胁\n";
}
// 6. 时间趋势
$trends = $analyzer->getThreatTrend(1);
foreach ($trends as $trend) {
    echo "{$trend['time_range']}: {$trend['threats']}次威胁\n";
}

前端展示建议

<!-- 威胁统计卡片 -->
<div class="threat-card">
    <h3>界外球威胁统计</h3>
    <div class="stats-grid">
        <div class="stat">
            <span class="label">总界外球</span>
            <span class="value"><?php echo $stats['total_throws']; ?></span>
        </div>
        <div class="stat">
            <span class="label">威胁次数</span>
            <span class="value"><?php echo $stats['threat_count']; ?></span>
        </div>
        <div class="stat">
            <span class="label">高威胁</span>
            <span class="value"><?php echo $stats['high_threats']; ?></span>
        </div>
        <div class="stat">
            <span class="label">平均威胁度</span>
            <span class="value"><?php echo number_format($stats['avg_threat_level'], 1); ?></span>
        </div>
    </div>
</div>

这个系统可以灵活扩展,你可以根据实际需求调整威胁判定逻辑和统计维度,是否需要我补充更具体的功能或样式?

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