php项目如何分析赛季末的斗志差异?

wen PHP项目 1

PHP项目分析赛季末斗志差异的方案

"斗志差异"在体育/游戏类项目中通常需要先量化再分析,下面是完整的PHP实现思路。

php项目如何分析赛季末的斗志差异?

先定义"斗志"的可量化指标

斗志是抽象概念,需要映射为数据,常见代理指标:

维度 指标示例
拼抢强度 抢断数、争顶成功率、跑动距离
关键时刻表现 末节/加时得分、关键球命中率
落后时的反应 落后时追分效率、逆转次数
比赛投入度 犯规数、黄牌、犯规战术使用
稳定性 赛季末 vs 赛季中数据波动

数据准备(MySQL 表结构示例)

CREATE TABLE match_stats (
    id INT PRIMARY KEY AUTO_INCREMENT,
    team_id INT,
    player_id INT,
    match_date DATE,
    season VARCHAR(20),
    is_home TINYINT,
    minutes_played INT,
    tackles INT,           -- 抢断
    duels_won INT,         -- 对抗成功
    distance_km DECIMAL(5,2),
    points_scored INT,
    point_diff INT,        -- 该场分差(负为落后)
    quarter_points JSON,   -- 各节得分,用于末节分析
    result TINYINT         -- 1胜 0负
);
CREATE TABLE season_phase (
    season VARCHAR(20),
    phase ENUM('early','mid','late'),  -- 赛季早/中/末
    start_date DATE,
    end_date DATE
);

核心分析逻辑(PHP)

计算每个阶段的斗志指数

<?php
class MoraleAnalyzer
{
    private PDO $db;
    public function __construct(PDO $db)
    {
        $this->db = $db;
    }
    /**
     * 计算某球队在指定阶段的斗志指数
     * 通过标准化各指标后加权求和
     */
    public function calculateMoraleIndex(int $teamId, string $phase): array
    {
        $sql = "SELECT 
                    AVG(s.tackles)              AS avg_tackles,
                    AVG(s.duels_won)            AS avg_duels,
                    AVG(s.distance_km)          AS avg_distance,
                    AVG(CASE WHEN s.point_diff < 0 
                        THEN s.points_scored ELSE NULL END) AS avg_comeback_pts,
                    SUM(CASE WHEN s.point_diff < 0 AND s.result = 1 
                        THEN 1 ELSE 0 END)      AS comebacks,
                    COUNT(*)                    AS games
                FROM match_stats s
                JOIN season_phase p ON s.match_date BETWEEN p.start_date AND p.end_date
                WHERE s.team_id = :team AND p.phase = :phase
                GROUP BY s.team_id";
        $stmt = $this->db->prepare($sql);
        $stmt->execute([':team' => $teamId, ':phase' => $phase]);
        return $stmt->fetch(PDO::FETCH_ASSOC) ?: [];
    }
    /**
     * 对全联盟做 Z-score 标准化,消除量纲差异
     */
    public function normalize(array $allTeams): array
    {
        $metrics = ['avg_tackles','avg_duels','avg_distance','avg_comeback_pts'];
        $result = [];
        foreach ($metrics as $m) {
            $values = array_column($allTeams, $m);
            $mean = array_sum($values) / count($values);
            $variance = array_sum(array_map(fn($v) => ($v - $mean) ** 2, $values)) / count($values);
            $std = sqrt($variance) ?: 1;
            foreach ($allTeams as $i => $row) {
                $result[$i][$m . '_z'] = ($row[$m] - $mean) / $std;
            }
        }
        return $result;
    }
    /**
     * 加权合成斗志指数(权重可调,建议用历史数据回归确定)
     */
    public function compositeScore(array $zScores): float
    {
        $weights = [
            'avg_tackles_z'      => 0.25,
            'avg_duels_z'        => 0.25,
            'avg_distance_z'     => 0.30,
            'avg_comeback_pts_z' => 0.20,
        ];
        $score = 0;
        foreach ($weights as $k => $w) {
            $score += ($zScores[$k] ?? 0) * $w;
        }
        return round($score, 3);
    }
}

对比赛季末 vs 赛季中的差异

public function comparePhases(int $teamId): array
{
    $mid  = $this->calculateMoraleIndex($teamId, 'mid');
    $late = $this->calculateMoraleIndex($teamId, 'late');
    return [
        'team_id'       => $teamId,
        'mid_index'     => $this->compositeScore($this->normalize([$mid])[0]),
        'late_index'    => $this->compositeScore($this->normalize([$late])[0]),
        'delta'         => /* late - mid */,
        'trend'         => /* 上升 / 下滑 / 持平 */,
    ];
}

批量分析所有球队并输出排名

public function analyzeLeague(string $season): array
{
    $teams = $this->db->query("SELECT DISTINCT team_id FROM match_stats")->fetchAll();
    $output = [];
    foreach ($teams as $t) {
        $output[] = $this->comparePhases((int)$t['team_id']);
    }
    // 按温差(delta)排序,找"赛季末斗志最旺/最松懈"的队
    usort($output, fn($a, $b) => $b['delta'] <=> $a['delta']);
    return $output;
}

统计显著性检验(避免把噪声当趋势)

可用简单的两样本 t 检验判断差异是否显著:

public function tTest(array $groupA, array $groupB): array
{
    $nA = count($groupA); $nB = count($groupB);
    $mA = array_sum($groupA)/$nA; $mB = array_sum($groupB)/$nB;
    $vA = array_sum(array_map(fn($x)=>($x-$mA)**2,$groupA))/($nA-1);
    $vB = array_sum(array_map(fn($x)=>($x-$mB)**2,$groupB))/($nB-1);
    $se = sqrt($vA/$nA + $vB/$nB) ?: 1e-9;
    $t  = ($mA - $mB) / $se;
    // 自由度用 Welch 近似,再查 t 分布表判断 p 值
    return ['t' => $t, 'mean_diff' => $mA - $mB, 'significant' => abs($t) > 2.0];
}

可视化与报表

  • 用 Chart.js 前端画折线:横轴赛季阶段,纵轴斗志指数
  • 用 PhpSpreadsheet 导出各队"赛季末斗志变化表"
  • 生成对比雷达图(拼抢/跑动/逆风表现多维度)

工程注意事项

  1. 指标口径统一:主/客场、对手强弱需做调整(可用对手强度加权)。
  2. 样本量控制:赛季末场次少,避免用单场数据下结论,至少聚合 5–8 场。
  3. 缺失值处理:未出场/伤停要排除或单独标记。
  4. 权重可解释:合成斗志指数时应能解释每项贡献,便于业务方质疑时回溯。
  5. 数据缓存:批量分析结果按 season+phase 缓存,避免每次实时重算。

验证思路

  • 用历史赛季数据做回溯验证:斗志指数高的队,赛季末实际胜率/逆转成功率是否也高。
  • 引入对照组:赛季初 vs 赛季中做同样计算,确认"末段特有"趋势而非全季通病。

如果你能提供具体场景(篮球/足球/电竞?)和数据字段,我可以把指标权重和 SQL 进一步定制到可直接落地。

上一篇这个php项目怎么看两队更衣室氛围差异?

下一篇当前分类已是最新一篇

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

友情链接攻略窝 · 礼包窝 · 配置窝 · 换算窝 · 算法窝 · 查文窝 · 手册窝 · 问答窝 · 全文搜 · 手册库
相关站点礼包窝 · 查文窝