本文目录导读:

我来帮你设计一个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' => '威胁值'
]
]);
}
}
?>
使用说明
- 数据要求:需要记录每次界外球的坐标位置和威胁等级
- 字段说明:
x_position: 水平位置(0-100)y_position: 垂直位置(0-100)threat_level: 1-5级威胁等级
- 统计指标:
- 总界外球次数
- 威胁次数(等级≥3)
- 各区域分布
- 威胁率
- 平均威胁值
这个方案可以灵活扩展,根据实际需求调整统计逻辑和展示方式,如果需要更具体的功能或数据结构,请提供更多细节。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播