本文目录导读:

我来帮你设计一个PHP项目统计斜长传精准度的方案,这里提供完整的数据结构和实现代码:
数据库表设计
-- 球员表
CREATE TABLE players (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
team_id INT,
position VARCHAR(20)
);
-- 传球记录表
CREATE TABLE passes (
id INT PRIMARY KEY AUTO_INCREMENT,
player_id INT NOT NULL,
match_id INT NOT NULL,
pass_type ENUM('long_ball', 'through_ball', 'cross') DEFAULT 'long_ball',
start_x DECIMAL(5,2), -- 传球起始X坐标
start_y DECIMAL(5,2), -- 传球起始Y坐标
end_x DECIMAL(5,2), -- 传球落点X坐标
end_y DECIMAL(5,2), -- 传球落点Y坐标
target_x DECIMAL(5,2), -- 预期目标X坐标
target_y DECIMAL(5,2), -- 预期目标Y坐标
is_success TINYINT(1) DEFAULT 0, -- 是否成功
pass_distance DECIMAL(5,2), -- 传球距离
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_player_date (player_id, created_at)
);
-- 比赛信息表
CREATE TABLE matches (
id INT PRIMARY KEY AUTO_INCREMENT,
home_team VARCHAR(50),
away_team VARCHAR(50),
match_date DATE,
competition VARCHAR(50)
);
核心统计类
<?php
class LongPassAnalyzer {
private $pdo;
private $playerId;
public function __construct(PDO $pdo, $playerId) {
$this->pdo = $pdo;
$this->playerId = $playerId;
}
/**
* 计算单次传球精准度
*/
public function calculatePassAccuracy($pass) {
// 目标位置与实际落点距离
$targetDistance = $this->calculateDistance(
$pass['target_x'],
$pass['target_y'],
$pass['end_x'],
$pass['end_y']
);
// 根据距离计算精准度 (0-100)
$accuracy = max(0, 100 - $targetDistance * 2);
return $accuracy;
}
/**
* 获取球员所有传球统计
*/
public function getPlayerStatistics($dateFrom = null, $dateTo = null) {
$sql = "SELECT
p.id,
p.pass_type,
p.is_success,
p.pass_distance,
p.start_x, p.start_y,
p.end_x, p.end_y,
p.target_x, p.target_y,
m.match_date,
m.competition
FROM passes p
INNER JOIN matches m ON p.match_id = m.id
WHERE p.player_id = :playerId";
if ($dateFrom && $dateTo) {
$sql .= " AND m.match_date BETWEEN :dateFrom AND :dateTo";
$params = [
':playerId' => $this->playerId,
':dateFrom' => $dateFrom,
':dateTo' => $dateTo
];
} else {
$params = [':playerId' => $this->playerId];
}
$sql .= " ORDER BY m.match_date DESC";
$stmt = $this->pdo->prepare($sql);
$stmt->execute($params);
$passes = $stmt->fetchAll(PDO::FETCH_ASSOC);
$statistics = [
'total_passes' => count($passes),
'success_passes' => 0,
'avg_accuracy' => 0,
'distance_breakdown' => [],
'type_breakdown' => [],
'recent_trend' => []
];
foreach ($passes as $pass) {
// 统计成功率
if ($pass['is_success']) {
$statistics['success_passes']++;
}
// 计算精准度
$accuracy = $this->calculatePassAccuracy($pass);
$statistics['avg_accuracy'] += $accuracy;
// 按距离分组统计
$distanceCategory = $this->categorizeDistance($pass['pass_distance']);
if (!isset($statistics['distance_breakdown'][$distanceCategory])) {
$statistics['distance_breakdown'][$distanceCategory] = [
'count' => 0,
'accuracy_sum' => 0
];
}
$statistics['distance_breakdown'][$distanceCategory]['count']++;
$statistics['distance_breakdown'][$distanceCategory]['accuracy_sum'] += $accuracy;
// 按传球类型统计
// ... 类似距离统计
}
// 计算平均精准度
if ($statistics['total_passes'] > 0) {
$statistics['avg_accuracy'] = round(
$statistics['avg_accuracy'] / $statistics['total_passes'], 2
);
}
// 计算成功率
$statistics['success_rate'] = $statistics['total_passes'] > 0
? round(($statistics['success_passes'] / $statistics['total_passes']) * 100, 1)
: 0;
// 近10场比赛趋势
$statistics['recent_trend'] = $this->getRecentTrend($passes);
return $statistics;
}
/**
* 计算两点距离
*/
private function calculateDistance($x1, $y1, $x2, $y2) {
return sqrt(pow($x2 - $x1, 2) + pow($y2 - $y1, 2));
}
/**
* 距离分类
*/
private function categorizeDistance($distance) {
if ($distance < 30) return 'short';
if ($distance < 45) return 'medium';
if ($distance < 60) return 'long';
return 'very_long';
}
/**
* 获取近期趋势
*/
private function getRecentTrend($passes) {
$trend = [];
$summary = array_slice($passes, 0, 10); // 最近10场
foreach ($summary as $pass) {
$date = $pass['match_date'];
if (!isset($trend[$date])) {
$trend[$date] = [
'total' => 0,
'accuracy' => 0
];
}
$trend[$date]['total']++;
$trend[$date]['accuracy'] += $this->calculatePassAccuracy($pass);
}
// 计算每日平均
foreach ($trend as &$day) {
$day['avg_accuracy'] = $day['total'] > 0
? round($day['accuracy'] / $day['total'], 1)
: 0;
unset($day['accuracy']);
}
return $trend;
}
/**
* 多维度分析报告
*/
public function generateReport() {
$statistics = $this->getPlayerStatistics();
return [
'summary' => [
'total_pass_attempts' => $statistics['total_passes'],
'success_rate' => $statistics['success_rate'],
'avg_accuracy' => $statistics['avg_accuracy']
],
'performance_by_distance' => $this->formatDistanceBreakdown($statistics['distance_breakdown']),
'strengths' => $this->identifyStrengths($statistics),
'areas_for_improvement' => $this->identifyWeaknesses($statistics),
'recommendations' => $this->generateRecommendations($statistics)
];
}
/**
* 格式化距离统计
*/
private function formatDistanceBreakdown($distanceStats) {
$formatted = [];
foreach ($distanceStats as $category => $data) {
$formatted[$category] = [
'attempts' => $data['count'],
'avg_accuracy' => $data['count'] > 0
? round($data['accuracy_sum'] / $data['count'], 1)
: 0
];
}
return $formatted;
}
/**
* 球员对标分析(与队内平均比较)
*/
public function compareToTeamAverage($teamId, $dateFrom = null, $dateTo = null) {
$playerStats = $this->getPlayerStatistics($dateFrom, $dateTo);
// 获取队伍平均数据
$sql = "SELECT AVG(is_success) * 100 as success_rate
FROM passes p
INNER JOIN players pl ON p.player_id = pl.id
WHERE pl.team_id = :teamId";
if ($dateFrom && $dateTo) {
$sql .= " AND p.created_at BETWEEN :dateFrom AND :dateTo";
}
$stmt = $this->pdo->prepare($sql);
$stmt->execute(['teamId' => $teamId]);
$teamSuccessRate = $stmt->fetchColumn();
return [
'player' => $playerStats,
'team_avg' => [
'success_rate' => round($teamSuccessRate, 1)
],
'comparison' => [
'success_rate_diff' => round($playerStats['success_rate'] - $teamSuccessRate, 1)
]
];
}
}
使用示例
<?php
// 初始化
$pdo = new PDO('mysql:host=localhost;dbname=football', 'user', 'pass');
$analyzer = new LongPassAnalyzer($pdo, 12345);
// 获取球员统计
$stats = $analyzer->getPlayerStatistics('2024-01-01', '2024-06-30');
// 生成完整报告
$report = $analyzer->generateReport();
// 与队伍对比
$teamComparison = $analyzer->compareToTeamAverage(678);
// 输出结果
echo json_encode($stats, JSON_PRETTY_PRINT);
前端展示(可选)
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<div class="pass-accuracy-chart">
<canvas id="accuracyChart"></canvas>
</div>
<script>
const ctx = document.getElementById('accuracyChart').getContext('2d');
new Chart(ctx, {
type: 'line',
data: {
labels: Object.keys(trendData),
datasets: [{
label: '精准度趋势',
data: Object.values(trendData).map(d => d.avg_accuracy),
borderColor: 'rgba(75, 192, 192, 1)',
fill: false
}]
}
});
</script>
核心功能亮点:
- 多维度统计:按距离、类型、比赛日期分类
- 精准度算法:基于传球落点与目标位置的偏差计算
- 趋势分析:展示近10场表现变化
- 对比分析:与队内平均比较
- 个性化报告:自动识别优势和待改进方面
建议根据实际需求调整传球精准度计算的权重和阈值参数。
版权声明: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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播