我来帮您设计一个门球短传配合成功率的统计系统,这个系统需要跟踪传球、接球和配合的完成情况。

数据库设计
数据表结构
-- 比赛信息表
CREATE TABLE matches (
id INT PRIMARY KEY AUTO_INCREMENT,
match_date DATE NOT NULL,
opponent VARCHAR(100),
venue VARCHAR(50),
status ENUM('进行中', '已完成') DEFAULT '进行中',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 球员信息表
CREATE TABLE players (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
number INT,
position VARCHAR(30),
is_active BOOLEAN DEFAULT TRUE
);
-- 传球统计表
CREATE TABLE passes (
id INT PRIMARY KEY AUTO_INCREMENT,
match_id INT NOT NULL,
passer_id INT NOT NULL,
receiver_id INT NOT NULL,
pass_type ENUM('短传', '中传', '长传') NOT NULL,
pass_zone VARCHAR(50), -- 传球区域
distance_meters DECIMAL(5,2), -- 传球距离
success BOOLEAN NOT NULL, -- 是否成功
turn_completed BOOLEAN DEFAULT FALSE, -- 是否完成配合
passer_challenges INT DEFAULT 0, -- 传球次数
receiver_challenges INT DEFAULT 0, -- 接球次数
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (match_id) REFERENCES matches(id),
FOREIGN KEY (passer_id) REFERENCES players(id),
FOREIGN KEY (receiver_id) REFERENCES players(id)
);
-- 配合序列表(记录连续传球配合)
CREATE TABLE passing_sequences (
id INT PRIMARY KEY AUTO_INCREMENT,
match_id INT NOT NULL,
start_time TIMESTAMP,
end_time TIMESTAMP,
pass_count INT DEFAULT 0, -- 连续传球次数
completed BOOLEAN DEFAULT FALSE, -- 配合是否成功完成
break_type VARCHAR(30), -- 中断原因
FOREIGN KEY (match_id) REFERENCES matches(id)
);
-- 配合序列详情(关联具体传球)
CREATE TABLE sequence_details (
id INT PRIMARY KEY AUTO_INCREMENT,
sequence_id INT NOT NULL,
pass_id INT NOT NULL,
pass_order INT NOT NULL, -- 传球顺序
FOREIGN KEY (sequence_id) REFERENCES passing_sequences(id),
FOREIGN KEY (pass_id) REFERENCES passes(id)
);
PHP后端代码
<?php
// 数据库配置
class Database {
private $host = 'localhost';
private $username = 'root';
private $password = 'password';
private $database = 'menqiu_stats';
public $conn;
public function getConnection() {
$this->conn = null;
try {
$this->conn = new PDO(
"mysql:host=" . $this->host . ";dbname=" . $this->database,
$this->username,
$this->password
);
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch(PDOException $e) {
echo "连接失败: " . $e->getMessage();
}
return $this->conn;
}
}
// 传球统计服务类
class PassStatistics {
private $db;
private $connection;
public function __construct() {
$this->db = new Database();
$this->connection = $this->db->getConnection();
}
// 记录一次传球
public function logPass($matchId, $passerId, $receiverId, $passType, $passZone, $distance, $success) {
try {
$query = "INSERT INTO passes
(match_id, passer_id, receiver_id, pass_type, pass_zone, distance_meters, success)
VALUES (?, ?, ?, ?, ?, ?, ?)";
$stmt = $this->connection->prepare($query);
$stmt->execute([
$matchId,
$passerId,
$receiverId,
$passType,
$passZone,
$distance,
$success
]);
return $this->connection->lastInsertId();
} catch (Exception $e) {
error_log($e->getMessage());
return false;
}
}
// 获取短传配合成功率
public function getShortPassSuccessRate($matchId, $zone = null) {
try {
$whereClause = "WHERE match_id = ? AND pass_type = '短传'";
$params = [$matchId];
if ($zone) {
$whereClause .= " AND pass_zone = ?";
$params[] = $zone;
}
$query = "SELECT
COUNT(*) as total_passes,
SUM(CASE WHEN success = 1 THEN 1 ELSE 0 END) as successful_passes,
ROUND(
(SUM(CASE WHEN success = 1 THEN 1 ELSE 0 END) / COUNT(*) * 100),
2
) as success_rate
FROM passes
$whereClause";
$stmt = $this->connection->prepare($query);
$stmt->execute($params);
return $stmt->fetch(PDO::FETCH_ASSOC);
} catch (Exception $e) {
error_log($e->getMessage());
return null;
}
}
// 记录配合序列
public function startPassingSequence($matchId) {
try {
$query = "INSERT INTO passing_sequences (match_id, start_time) VALUES (?, NOW())";
$stmt = $this->connection->prepare($query);
$stmt->execute([$matchId]);
return $this->connection->lastInsertId();
} catch (Exception $e) {
error_log($e->getMessage());
return false;
}
}
// 更新配合序列
public function updatePassSequence($sequenceId, $passId, $passOrder) {
try {
// 更新传球记录
$query = "UPDATE passes SET turn_completed = TRUE WHERE id = ?";
$stmt = $this->connection->prepare($query);
$stmt->execute([$passId]);
// 添加序列详情
$query = "INSERT INTO sequence_details (sequence_id, pass_id, pass_order) VALUES (?, ?, ?)";
$stmt = $this->connection->prepare($query);
$stmt->execute([$sequenceId, $passId, $passOrder]);
// 更新序列的传球数
$query = "UPDATE passing_sequences
SET pass_count = pass_count + 1,
end_time = NOW()
WHERE id = ?";
$stmt = $this->connection->prepare($query);
$stmt->execute([$sequenceId]);
return true;
} catch (Exception $e) {
error_log($e->getMessage());
return false;
}
}
// 完成配合序列
public function completePassSequence($sequenceId, $completed = true, $breakType = null) {
try {
$query = "UPDATE passing_sequences
SET completed = ?, break_type = ?, end_time = NOW()
WHERE id = ?";
$stmt = $this->connection->prepare($query);
return $stmt->execute([$completed ? 1 : 0, $breakType, $sequenceId]);
} catch (Exception $e) {
error_log($e->getMessage());
return false;
}
}
// 获取配合成功率(连续传球配合)
public function getSequenceSuccessRate($matchId) {
try {
$query = "SELECT
COUNT(*) as total_sequences,
SUM(CASE WHEN completed = 1 THEN 1 ELSE 0 END) as successful_sequences,
ROUND(
(SUM(CASE WHEN completed = 1 THEN 1 ELSE 0 END) / COUNT(*) * 100),
2
) as success_rate,
AVG(pass_count) as avg_passes_per_sequence
FROM passing_sequences
WHERE match_id = ?";
$stmt = $this->connection->prepare($query);
$stmt->execute([$matchId]);
return $stmt->fetch(PDO::FETCH_ASSOC);
} catch (Exception $e) {
error_log($e->getMessage());
return null;
}
}
// 获取球员传球统计
public function getPlayerPassingStats($matchId) {
try {
$query = "SELECT
p.name as player_name,
p.number,
COUNT(CASE WHEN pa.passer_id = p.id AND pa.pass_type = '短传' THEN 1 END) as short_passes,
SUM(CASE WHEN pa.passer_id = p.id AND pa.pass_type = '短传' AND pa.success = 1 THEN 1 ELSE 0 END) as short_successful,
ROUND(
(SUM(CASE WHEN pa.passer_id = p.id AND pa.pass_type = '短传' AND pa.success = 1 THEN 1 ELSE 0 END) /
NULLIF(COUNT(CASE WHEN pa.passer_id = p.id AND pa.pass_type = '短传' THEN 1 END), 0) * 100),
2
) as personal_success_rate
FROM players p
LEFT JOIN passes pa ON pa.passer_id = p.id
WHERE pa.match_id = ? OR pa.match_id IS NULL
GROUP BY p.id, p.name, p.number
HAVING short_passes > 0 OR short_successful > 0
ORDER BY short_passes DESC";
$stmt = $this->connection->prepare($query);
$stmt->execute([$matchId]);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (Exception $e) {
error_log($e->getMessage());
return [];
}
}
// 导出比赛统计报告
public function exportMatchReport($matchId) {
try {
// 获取比赛总体统计
$shortPassStats = $this->getShortPassSuccessRate($matchId);
$sequenceStats = $this->getSequenceSuccessRate($matchId);
$playerStats = $this->getPlayerPassingStats($matchId);
// 生成报告数据
$report = [
'short_pass_stats' => $shortPassStats,
'sequence_stats' => $sequenceStats,
'player_stats' => $playerStats,
'successful_passes_count' => $shortPassStats['successful_passes'],
'total_passes_count' => $shortPassStats['total_passes']
];
// 导出为CSV
$this->exportToCSV($report, $matchId);
return $report;
} catch (Exception $e) {
error_log($e->getMessage());
return null;
}
}
private function exportToCSV($data, $matchId) {
$filename = 'match_' . $matchId . '_pass_report.csv';
$filepath = __DIR__ . '/reports/' . $filename;
// 确保目录存在
if (!file_exists(dirname($filepath))) {
mkdir(dirname($filepath), 0777, true);
}
$fp = fopen($filepath, 'w');
// 添加标题行
fputcsv($fp, ['门球短传配合成功率报告']);
fputcsv($fp, ['比赛ID', $matchId]);
fputcsv($fp, ['短传总数', $data['short_pass_stats']['total_passes']]);
fputcsv($fp, ['成功数', $data['short_pass_stats']['successful_passes']]);
fputcsv($fp, ['成功率', $data['short_pass_stats']['success_rate'] . '%']);
fputcsv($fp, [''); // 空行
// 球员统计
fputcsv($fp, ['球员传球统计']);
fputcsv($fp, ['球员', '号码', '短传次数', '成功次数', '成功率']);
foreach ($data['player_stats'] as $player) {
fputcsv($fp, [
$player['player_name'],
$player['number'],
$player['short_passes'],
$player['short_successful'],
$player['personal_success_rate'] . '%'
]);
}
fclose($fp);
}
}
// 前端API接口
class API {
private $passStats;
public function __construct() {
$this->passStats = new PassStatistics();
}
public function handleRequest() {
$method = $_SERVER['REQUEST_METHOD'];
$action = isset($_GET['action']) ? $_GET['action'] : '';
switch ($action) {
case 'logPass':
if ($method == 'POST') {
$this->logPass();
}
break;
case 'getSuccessRate':
if ($method == 'GET') {
$this->getSuccessRate();
}
break;
case 'startSequence':
if ($method == 'POST') {
$this->startSequence();
}
break;
case 'getReport':
if ($method == 'GET') {
$this->getReport();
}
break;
default:
echo json_encode(['status' => 'error', 'message' => 'Invalid action']);
}
}
private function logPass() {
$data = json_decode(file_get_contents('php://input'), true);
$matchId = $data['match_id'] ?? 0;
$passerId = $data['passer_id'] ?? 0;
$receiverId = $data['receiver_id'] ?? 0;
$passType = $data['pass_type'] ?? '短传';
$passZone = $data['pass_zone'] ?? 'unknown';
$distance = $data['distance'] ?? 0;
$success = $data['success'] ?? false;
$result = $this->passStats->logPass(
$matchId, $passerId, $receiverId,
$passType, $passZone, $distance, $success
);
echo json_encode([
'status' => 'success',
'pass_id' => $result
]);
}
private function getSuccessRate() {
$matchId = $_GET['match_id'] ?? 0;
$zone = $_GET['zone'] ?? null;
$result = $this->passStats->getShortPassSuccessRate($matchId, $zone);
if ($result) {
echo json_encode(['status' => 'success', 'data' => $result]);
} else {
echo json_encode(['status' => 'error', 'message' => 'Failed to get statistics']);
}
}
private function startSequence() {
$data = json_decode(file_get_contents('php://input'), true);
$matchId = $data['match_id'] ?? 0;
$result = $this->passStats->startPassingSequence($matchId);
echo json_encode([
'status' => 'success',
'sequence_id' => $result
]);
}
private function getReport() {
$matchId = $_GET['match_id'] ?? 0;
$report = $this->passStats->exportMatchReport($matchId);
if ($report) {
echo json_encode(['status' => 'success', 'data' => $report]);
} else {
echo json_encode(['status' => 'error', 'message' => 'Failed to generate report']);
}
}
}
// 执行请求
$api = new API();
$api->handleRequest();
?>
前端统计展示界面
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">门球短传配合统计系统</title>
<style>
body {
font-family: 'Microsoft YaHei', Arial, sans-serif;
margin: 0;
padding: 20px;
background: #f5f5f5;
}
.container {
max-width: 1400px;
margin: 0 auto;
}
h1 {
color: #2c3e50;
text-align: center;
margin-bottom: 30px;
}
.dashboard {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20px;
margin-bottom: 30px;
}
.stat-card {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
text-align: center;
}
.stat-card .value {
font-size: 32px;
font-weight: bold;
color: #3498db;
margin: 10px 0;
}
.stat-card .label {
color: #7f8c8d;
font-size: 14px;
}
.chart-container {
background: white;
border-radius: 8px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.live-tracking {
background: white;
border-radius: 8px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.player-stats-table {
background: white;
border-radius: 8px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
table {
width: 100%;
border-collapse: collapse;
}
th, td {
padding: 12px;
text-align: left;
border-bottom: 1px solid #e0e0e0;
}
th {
background: #f8f9fa;
font-weight: bold;
color: #333;
}
.success-rate {
font-weight: bold;
color: #27ae60;
}
.btn {
background: #3498db;
color: white;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
margin: 5px;
}
.btn:hover {
background: #2980b9;
}
.btn-danger {
background: #e74c3c;
}
.btn-danger:hover {
background: #c0392b;
}
.form-group {
margin-bottom: 15px;
}
.form-group label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
.form-group input, .form-group select {
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
}
.collapsible {
background-color: #f8f9fa;
color: #333;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
}
.collapsible:hover {
background-color: #e9ecef;
}
.content {
padding: 0 18px;
display: none;
overflow: hidden;
background-color: white;
border: 1px solid #dee2e6;
border-top: none;
border-radius: 0 0 4px 4px;
}
.active, .collapsible:hover {
background-color: #e9ecef;
}
</style>
</head>
<body>
<div class="container">
<h1>🏑 门球短传配合统计系统</h1>
<!-- 统计概览 -->
<div class="dashboard">
<div class="stat-card">
<div class="label">总传球数</div>
<div class="value" id="totalPasses">0</div>
</div>
<div class="stat-card">
<div class="label">成功传球</div>
<div class="value" id="successfulPasses">0</div>
</div>
<div class="stat-card">
<div class="label">成功率</div>
<div class="value" id="successRate">0%</div>
</div>
<div class="stat-card">
<div class="label">平均配合传球数</div>
<div class="value" id="avgPasses">0</div>
</div>
</div>
<!-- 比赛选择 -->
<div class="chart-container">
<h3>选择比赛</h3>
<select id="matchSelect" onchange="loadMatchData()">
<option value="">请选择比赛</option>
</select>
<button class="btn" onclick="startNewMatch()">新建比赛</button>
</div>
<!-- 实时数据录入 -->
<div class="live-tracking">
<h3>📊 实时传球数据录入</h3>
<button class="collapsible active" onclick="toggleInputPanel()">展开/收起录入面板</button>
<div id="inputPanel" class="content" style="display: block;">
<div style="display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; gap: 20px; margin-top: 15px;">
<div class="form-group">
<label for="player1">传球球员</label>
<select id="player1">
<option value="">选择球员</option>
</select>
</div>
<div class="form-group">
<label for="player2">接球球员</label>
<select id="player2">
<option value="">选择球员</option>
</select>
</div>
<div class="form-group">
<label for="passType">传球类型</label>
<select id="passType">
<option value="短传" selected>短传</option>
<option value="中传">中传</option>
<option value="长传">长传</option>
</select>
</div>
<div class="form-group">
<label for="passZone">传球区域</label>
<select id="passZone">
<option value="前场">前场</option>
<option value="中场">中场</option>
<option value="后场">后场</option>
<option value="边路">边路</option>
</select>
</div>
</div>
<div style="display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; gap: 20px; margin-top: 15px;">
<div class="form-group">
<label for="distance">传球距离(米)</label>
<input type="number" id="distance" value="5" min="0" max="50">
</div>
<div class="form-group">
<label for="sequenceMode">配合模式</label>
<select id="sequenceMode" onchange="toggleSequenceBtn()">
<option value="single">单次传球</option>
<option value="sequence">配合传球</option>
</select>
</div>
<div class="form-group" id="sequenceBtnDiv" style="display:none;">
<button class="btn" id="sequenceBtn" onclick="startOrEndSequence()">开始配合</button>
</div>
</div>
<div style="margin-top: 20px; text-align: center;">
<button class="btn" style="width: 200px; height: 45px; font-size: 16px;" onclick="submitPass()">提交传球数据</button>
<button class="btn btn-danger" style="display:none;" id="cancelPassBtn" onclick="cancelPass()">取消传球</button>
</div>
</div>
</div>
<!-- 配合序列跟踪 -->
<div class="chart-container">
<h3>连续配合球序列</h3>
<div id="sequenceStatus">
<p>当前无进行中的配合</p>
</div>
<div id="sequenceHistory">
<table id="sequenceTable">
<thead>
<tr>
<th>序列ID</th>
<th>开始时间</th>
<th>传球次数</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody id="sequenceTableBody">
</tbody>
</table>
</div>
</div>
<!-- 球员统计表格 -->
<div class="player-stats-table">
<h3>球员传球统计</h3>
<table id="playerStatsTable">
<thead>
<tr>
<th>姓名</th>
<th>号码</th>
<th>短传总数</th>
<th>成功数</th>
<th>成功率</th>
<th>传球区域</th>
</tr>
</thead>
<tbody id="playerStatsTableBody">
</tbody>
</table>
</div>
<!-- 传球分析图表 -->
<div class="chart-container">
<h3>传球分析图表</h3>
<canvas id="passAnalysisChart" width="100%"></canvas>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
let currentSequence = null;
let matchData = {
matchId: null,
currentSequence: 0,
totalPasses: 0,
successfulPasses: 0,
passerStats: {},
receiverStats: {},
sequences: []
};
// 初始化比赛数据
function initMatch() {
const matchSelect = document.getElementById('matchSelect');
// 这里应该从服务器获取比赛列表
// 示例数据
matchSelect.innerHTML = '<option value="">请选择比赛</option>' +
'<option value="1">2024年3月15日 vs 红队</option>' +
'<option value="2">2024年3月22日 vs 蓝队</option>';
}
// 加载比赛数据
function loadMatchData() {
const matchId = document.getElementById('matchSelect').value;
if (!matchId) return;
// 这里应该从服务器获取比赛数据
// 示例数据
matchData.matchId = matchId;
matchData.totalPasses = 0;
matchData.successfulPasses = 0;
// 更新玩家列表
updatePlayerList();
updateStatsDisplay();
}
// 更新球员下拉列表
function updatePlayerList() {
const player1 = document.getElementById('player1');
const player2 = document.getElementById('player2');
// 示例球员数据
const players = [
{id: 1, name: '张三', number: 1},
{id: 2, name: '李四', number: 2},
{id: 3, name: '王五', number: 3},
{id: 4, name: '赵六', number: 4},
{id: 5, name: '孙七', number: 5}
];
const options = '<option value="">选择球员</option>' +
players.map(p => `<option value="${p.id}">${p.name} (${p.number})</option>`).join('');
player1.innerHTML = options;
player2.innerHTML = options;
}
// 统计数据显示
function updateStatsDisplay() {
const rate = matchData.totalPasses > 0 ?
Math.round((matchData.successfulPasses / matchData.totalPasses) * 100) : 0;
document.getElementById('totalPasses').textContent = matchData.totalPasses;
document.getElementById('successfulPasses').textContent = matchData.successfulPasses;
document.getElementById('successRate').textContent = rate + '%';
}
// 切换配合模式
function toggleSequenceBtn() {
const mode = document.getElementById('sequenceMode').value;
const btnDiv = document.getElementById('sequenceBtnDiv');
if (mode === 'sequence') {
btnDiv.style.display = 'block';
} else {
btnDiv.style.display = 'none';
}
}
// 开始/结束配合序列
function startOrEndSequence() {
const btn = document.getElementById('sequenceBtn');
const mode = document.getElementById('sequenceMode').value;
const matchId = matchData.matchId;
if (!matchId) {
alert('请先选择比赛');
return;
}
if (!currentSequence) {
// 开始新的配合
currentSequence = matchData.currentSequence + 1;
matchData.currentSequence = currentSequence;
btn.textContent = '结束配合';
document.getElementById('sequenceStatus').innerHTML =
`<p>配合中... (序列#${currentSequence})</p>`;
console.log(`开始配合序列 #${currentSequence}`);
} else {
// 结束配合
completeSequence();
btn.textContent = '开始配合';
currentSequence = null;
}
}
// 完成配合
function completeSequence() {
if (!currentSequence) return;
const success = matchData.successfulPasses > 0 ? true : false;
const sequenceInfo = {
id: currentSequence,
passCount: matchData.totalPasses,
completed: success
};
// 添加到历史记录
addSequenceToTable(sequenceInfo);
document.getElementById('sequenceStatus').innerHTML =
`<p>配合已结束 (序列#${currentSequence})</p>`;
}
// 添加序列到表格
function addSequenceToTable(sequenceInfo) {
const tbody = document.getElementById('sequenceTableBody');
const row = tbody.insertRow(0);
row.innerHTML = `
<td>${sequenceInfo.id}</td>
<td>${new Date().toLocaleTimeString()}</td>
<td>${sequenceInfo.passCount}</td>
<td>${sequenceInfo.completed ? '✅ 成功' : '❌ 失败'}</td>
<td><button class="btn" onclick="viewSequence(${sequenceInfo.id})">查看详情</button></td>
`;
}
// 查看序列详情
function viewSequence(id) {
alert(`查看序列 #${id} 的详细统计数据`);
// 这里应该加载序列详细数据
}
// 提交传球数据
function submitPass() {
const player1 = document.getElementById('player1').value;
const player2 = document.getElementById('player2').value;
const passType = document.getElementById('passType').value;
const passZone = document.getElementById('passZone').value;
const distance = document.getElementById('distance').value;
if (!matchData.matchId) {
alert('请先选择比赛');
return;
}
if (!player1 || !player2) {
alert('请选择传球球员和接球球员');
return;
}
if (player1 === player2) {
alert('传球球员和接球球员不能相同');
return;
}
// 这里应该发送到服务器
// 模拟成功传球(80%成功率)
const success = Math.random() < 0.8;
// 更新统计数据
matchData.totalPasses++;
if (success) {
matchData.successfulPasses++;
}
// 更新球员统计
updatePlayerStats(player1, true, success);
updatePlayerStats(player2, false, success);
// 更新显示
updateStatsDisplay();
updatePlayerStatsTable();
// 显示结果提示
const statusColor = success ? 'green' : 'red';
const statusText = success ? '✅ 传球成功' : '❌ 传球失败';
document.getElementById('passResult').innerText = statusText;
document.getElementById('passResult').style.color = statusColor;
document.getElementById('passResult').style.fontWeight = 'bold';
}
// 更新球员统计
function updatePlayerStats(playerId, isPasser, success) {
if (!matchData.passerStats[playerId]) {
matchData.passerStats[playerId] = {passes: 0, successful: 0};
}
if (isPasser) {
matchData.passerStats[playerId].passes++;
if (success) {
matchData.passerStats[playerId].successful++;
}
}
}
// 更新球员统计表格
function updatePlayerStatsTable() {
const tbody = document.getElementById('playerStatsTableBody');
tbody.innerHTML = '';
for (let playerId in matchData.passerStats) {
const stats = matchData.passerStats[playerId];
const row = tbody.insertRow();
// 这里应该从服务器获取球员名称
row.innerHTML = `
<td>球员${playerId}</td>
<td>${String(playerId).padStart(2, '0')}</td>
<td>${stats.passes}</td>
<td>${stats.successful}</td>
<td class="success-rate">${stats.passes > 0 ? Math.round((stats.successful / stats.passes) * 100) : 0}%</td>
<td>中场</td>
`;
}
}
// 新建比赛
function startNewMatch() {
const matchId = confirm('确定要开始一场新的比赛吗?');
if (matchId) {
// 这里应该新建比赛
matchData = {
matchId: Date.now(),
currentSequence: 0,
totalPasses: 0,
successfulPasses: 0,
passerStats: {},
receiverStats: {},
sequences: []
};
document.getElementById('sequenceTableBody').innerHTML = '';
document.getElementById('playerStatsTableBody').innerHTML = '';
document.getElementById('sequenceStatus').innerHTML = '<p>当前无进行中的配合</p>';
resetForm();
updateStatsDisplay();
alert('新比赛创建成功!');
}
}
// 重置表单
function resetForm() {
document.getElementById('player1').value = '';
document.getElementById('player2').value = '';
document.getElementById('passType').value = '短传';
document.getElementById('passZone').value = '前场';
document.getElementById('distance').value = '5';
document.getElementById('sequenceMode').value = 'single';
document.getElementById('sequenceBtn').textContent = '开始配合';
}
// 折叠面板
function toggleInputPanel() {
const panel = document.getElementById('inputPanel');
panel.style.display = panel.style.display === 'none' ? 'block' : 'none';
}
// 初始化
window.onload = function() {
initMatch();
// 创建结果提示元素
const resultDiv = document.createElement('div');
resultDiv.id = 'passResult';
resultDiv.style.marginTop = '10px';
resultDiv.style.textAlign = 'center';
document.querySelector('.live-tracking').appendChild(resultDiv);
};
</script>
</body>
</html>
使用说明
统计指标:
- 短传成功率:短传成功次数 / 总短传次数 × 100%
- 配合序列成功率:成功完成的配合序列 / 总配合序列 × 100%
- 平均配合传球数:总传球次数 / 配合序列数
功能模块:
- 实时数据录入:记录每次传球的数据(球员、类型、区域、距离、是否成功)
- 连续配合追踪:记录多次连续传球是否形成有效配合
- 球员统计:分析每位球员的传球成功率
- 区域分析:统计不同区域的传球成功率
- 比赛报告:生成完整的比赛统计
版权声明: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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播