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

wen PHP项目 2

本文目录导读:

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

  1. 数据库表设计
  2. 统计类 PHP 代码
  3. 更具体的统计方法
  4. 可视化图表生成(可选)
  5. 使用说明

我来帮你设计一个PHP项目统计界外球进攻威胁次数的解决方案,这需要根据你的具体数据结构来调整,我先提供一个通用的方案。

数据库表设计

-- 比赛事件表
CREATE TABLE match_events (
    id INT PRIMARY KEY AUTO_INCREMENT,
    match_id INT NOT NULL,
    team_id INT NOT NULL,
    event_type ENUM('throw_in', 'corner', 'goal_kick') NOT NULL,
    x_position DECIMAL(5,2),  -- 球场X坐标(0-100)
    y_position DECIMAL(5,2),  -- 球场Y坐标(0-100)
    threat_level TINYINT DEFAULT 0, -- 威胁等级1-5
    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,
    name VARCHAR(100) NOT NULL
);

统计类 PHP 代码

<?php
class ThrowInThreatAnalyzer {
    private $db;
    public function __construct($pdo) {
        $this->db = $pdo;
    }
    /**
     * 统计界外球进攻威胁次数
     * @param int $matchId 比赛ID
     * @param int $teamId 球队ID
     * @param string $period 时间段 (可选: 'first_half', 'second_half', 'full_match')
     * @return array 统计数据
     */
    public function analyzeThreatFrequency($matchId, $teamId, $period = 'full_match') {
        // 基础查询
        $sql = "SELECT 
                    id,
                    event_type,
                    x_position,
                    y_position,
                    threat_level,
                    created_at
                FROM match_events 
                WHERE match_id = :match_id 
                AND team_id = :team_id
                AND event_type = 'throw_in'";
        // 添加时间段筛选
        if ($period != 'full_match') {
            $sql .= " AND ";
            if ($period == 'first_half') {
                $sql .= "created_at < DATE_ADD((SELECT kickoff_time FROM matches WHERE id = :match_id), INTERVAL 45 MINUTE)";
            } else {
                $sql .= "created_at >= DATE_ADD((SELECT kickoff_time FROM matches WHERE id = :match_id), INTERVAL 45 MINUTE)";
            }
        }
        $stmt = $this->db->prepare($sql);
        $params = ['match_id' => $matchId, 'team_id' => $teamId];
        if ($period != 'full_match') {
            $params['match_id'] = $matchId; // 重复用于子查询
        }
        $stmt->execute($params);
        $events = $stmt->fetchAll(PDO::FETCH_ASSOC);
        // 统计分析
        $analysis = [
            'total_throw_ins' => count($events),
            'threat_events' => 0,
            'high_threat_events' => 0,
            'by_zone' => [
                'attack_third' => 0,   // 进攻三区
                'middle_third' => 0,    // 中场三区
                'defensive_third' => 0  // 防守三区
            ],
            'by_position' => [
                'left_flank' => 0,
                'central' => 0,
                'right_flank' => 0
            ],
            'threat_levels' => [
                1 => 0, 2 => 0, 3 => 0, 4 => 0, 5 => 0
            ],
            'threat_rate' => 0,  // 威胁率
            'average_threat' => 0 // 平均威胁值
        ];
        foreach ($events as $event) {
            // 判断区域
            $zone = $this->getZone($event['x_position']);
            $position = $this->getPosition($event['y_position']);
            // 统计区域分布
            $analysis['by_zone'][$zone]++;
            $analysis['by_position'][$position]++;
            // 威胁等级统计
            $analysis['threat_levels'][$event['threat_level']]++;
            // 判断是否为威胁事件 (威胁等级 >= 3)
            if ($event['threat_level'] >= 3) {
                $analysis['threat_events']++;
            }
            // 高威胁事件 (威胁等级 >= 4)
            if ($event['threat_level'] >= 4) {
                $analysis['high_threat_events']++;
            }
        }
        // 计算比例
        if ($analysis['total_throw_ins'] > 0) {
            $analysis['threat_rate'] = round(($analysis['threat_events'] / $analysis['total_throw_ins']) * 100, 2);
            $analysis['average_threat'] = round(array_sum(array_keys($analysis['threat_levels'])), 2);
        }
        return $analysis;
    }
    /**
     * 获取球场区域
     */
    private function getZone($xPosition) {
        // 假设球场X坐标为0-100, 0为防守端, 100为进攻端
        if ($xPosition < 33.33) {
            return 'defensive_third';
        } elseif ($xPosition < 66.67) {
            return 'middle_third';
        } else {
            return 'attack_third';
        }
    }
    /**
     * 获取位置(左中右)
     */
    private function getPosition($yPosition) {
        if ($yPosition < 33.33) {
            return 'left_flank';
        } elseif ($yPosition < 66.67) {
            return 'central';
        } else {
            return 'right_flank';
        }
    }
    /**
     * 统计一段时间内的威胁次数
     */
    public function threatOverTime($matchId, $teamId, $intervalMinutes = 5) {
        $sql = "SELECT 
                    MINUTE(created_at) / :interval_minutes AS time_bucket,
                    COUNT(*) as total,
                    SUM(CASE WHEN threat_level >= 3 THEN 1 ELSE 0 END) as threats
                FROM match_events 
                WHERE match_id = :match_id 
                AND team_id = :team_id
                AND event_type = 'throw_in'
                GROUP BY time_bucket
                ORDER BY time_bucket";
        $stmt = $this->db->prepare($sql);
        $stmt->execute([
            'match_id' => $matchId,
            'team_id' => $teamId,
            'interval_minutes' => $intervalMinutes
        ]);
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
    /**
     * 对比两队威胁情况
     */
    public function compareTeams($matchId, $teamAId, $teamBId) {
        $teamA = $this->analyzeThreatFrequency($matchId, $teamAId);
        $teamB = $this->analyzeThreatFrequency($matchId, $teamBId);
        return [
            'team_a' => $teamA,
            'team_b' => $teamB,
            'comparison' => [
                'a_more_threats' => $teamA['threat_events'] > $teamB['threat_events'],
                'difference' => abs($teamA['threat_events'] - $teamB['threat_events']),
                'a_threat_rate' => $teamA['threat_rate'],
                'b_threat_rate' => $teamB['threat_rate']
            ]
        ];
    }
}
// 使用示例
try {
    $pdo = new PDO("mysql:host=localhost;dbname=football_stats", "username", "password");
    $analyzer = new ThrowInThreatAnalyzer($pdo);
    // 统计单场比赛
    $result = $analyzer->analyzeThreatFrequency(1, 101);
    print_r($result);
    // 对比两队
    $comparison = $analyzer->compareTeams(1, 101, 102);
    print_r($comparison);
} catch (PDOException $e) {
    echo "数据库连接错误: " . $e->getMessage();
}
?>

更具体的统计方法

<?php
class AdvancedThreatStatistics {
    /**
     * 分析界外球进攻威胁特征
     */
    public function analyzeThreatCharacteristics($pdo, $matchId, $teamId) {
        // 统计不同区域的威胁表现
        $zoneStats = $this->getZoneThreatStats($pdo, $matchId, $teamId);
        // 分析威胁趋势
        $trendAnalysis = $this->getThreatTrendAnalysis($pdo, $matchId, $teamId);
        // 定义威胁评估标准
        $threatCriteria = [
            'high_threat_zone' => ['start_x' => 70, 'end_x' => 100],  // 进攻三区
            'dangerous_zone' => ['start_x' => 80, 'end_x' => 100],    // 危险区域
            'key_moments' => [85, 90],  // 关键时刻(比赛最后5分钟)
            'set_piece_potential' => 3 // 任意球/角球转化潜力
        ];
        return [
            'zone_stats' => $zoneStats,
            'trend' => $trendAnalysis,
            'key_findings' => $this->generateKeyFindings($zoneStats, $trendAnalysis, $threatCriteria)
        ];
    }
    /**
     * 获取区域威胁统计
     */
    private function getZoneThreatStats($pdo, $matchId, $teamId) {
        $sql = "SELECT 
                    CASE 
                        WHEN x_position >= 70 THEN 'high_threat_zone'
                        WHEN x_position >= 33.33 THEN 'middle_zone'
                        ELSE 'defensive_zone'
                    END as zone,
                    COUNT(*) as throw_ins,
                    AVG(threat_level) as avg_threat,
                    SUM(CASE WHEN threat_level >= 3 THEN 1 ELSE 0 END) as threat_events
                FROM match_events
                WHERE match_id = ? AND team_id = ? AND event_type = 'throw_in'
                GROUP BY zone";
        $stmt = $pdo->prepare($sql);
        $stmt->execute([$matchId, $teamId]);
        $results = $stmt->fetchAll(PDO::FETCH_ASSOC);
        // 填充默认值
        $zones = ['high_threat_zone' => 0, 'middle_zone' => 0, 'defensive_zone' => 0];
        foreach ($results as $result) {
            $zones[$result['zone']] = $result;
        }
        return $zones;
    }
    /**
     * 趋势分析
     */
    private function getThreatTrendAnalysis($pdo, $matchId, $teamId) {
        $sql = "SELECT 
                    HOUR(created_at) * 60 + MINUTE(created_at) as game_minute,
                    threat_level,
                    x_position,
                    y_position
                FROM match_events
                WHERE match_id = ? AND team_id = ? AND event_type = 'throw_in'
                ORDER BY created_at";
        $stmt = $pdo->prepare($sql);
        $stmt->execute([$matchId, $teamId]);
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
    /**
     * 生成关键发现
     */
    private function generateKeyFindings($zoneStats, $trend, $criteria) {
        $findings = [];
        // 检查进攻三区的威胁
        if ($zoneStats['high_threat_zone']['threat_events'] > 5) {
            $findings[] = "进攻三区的界外球形成了明显的威胁,共产生了 {$zoneStats['high_threat_zone']['threat_events']} 次有效威胁";
        }
        // 检查比赛末段的威胁
        $endThreats = array_filter($trend, function($event) use ($criteria) {
            foreach ($criteria['key_moments'] as $minute) {
                if ($event['game_minute'] >= $minute * 60 - 300) {
                    return true;
                }
            }
            return false;
        });
        if (count($endThreats) > 3) {
            $findings[] = "比赛末段界外球攻击活跃,可能利用防守方体力下降";
        }
        return $findings;
    }
}
?>

可视化图表生成(可选)

<?php
class ThreatChartGenerator {
    public function generateHeatmap($pdo, $matchId, $teamId) {
        // 获取位置数据
        $sql = "SELECT x_position, y_position, threat_level
                FROM match_events
                WHERE match_id = ? AND team_id = ? AND event_type = 'throw_in'";
        $stmt = $pdo->prepare($sql);
        $stmt->execute([$matchId, $teamId]);
        $events = $stmt->fetchAll(PDO::FETCH_ASSOC);
        // 转换坐标为热力图数据
        $heatmapData = [];
        foreach ($events as $event) {
            $heatmapData[] = [
                'x' => round($event['x_position'] / 10) * 10,
                'y' => round($event['y_position'] / 10) * 10,
                'value' => $event['threat_level']
            ];
        }
        // 返回用于前端展示的数据
        return json_encode([
            'type' => 'heatmap',
            'data' => $heatmapData,
            'config' => [
                'title' => '界外球进攻威胁热力图',
                'colors' => ['#00FF00', '#FFFF00', '#FF0000'] // 绿-黄-红
            ]
        ]);
    }
    public function generateLineChart($pdo, $matchId, $teamId) {
        $sql = "SELECT MINUTE(created_at) as minute, COUNT(*) as count, AVG(threat_level) as avg_threat
                FROM match_events
                WHERE match_id = ? AND team_id = ? AND event_type = 'throw_in'
                GROUP BY minute";
        $stmt = $pdo->prepare($sql);
        $stmt->execute([$matchId, $teamId]);
        $results = $stmt->fetchAll(PDO::FETCH_ASSOC);
        return json_encode([
            'type' => 'line',
            'data' => $results,
            'config' => [
                'title' => '界外球威胁趋势',
                'xlabel' => '比赛时间(分钟)',
                'ylabel' => '威胁值'
            ]
        ]);
    }
}
?>

使用说明

  1. 数据要求:需要记录每次界外球的坐标位置和威胁等级
  2. 字段说明
    • x_position: 水平位置(0-100)
    • y_position: 垂直位置(0-100)
    • threat_level: 1-5级威胁等级
  3. 统计指标
    • 总界外球次数
    • 威胁次数(等级≥3)
    • 各区域分布
    • 威胁率
    • 平均威胁值

这个方案可以灵活扩展,根据实际需求调整统计逻辑和展示方式,如果需要更具体的功能或数据结构,请提供更多细节。

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